1 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 2 // Converted from the tests for uBPF <https://github.com/iovisor/ubpf> 3 // Copyright 2015 Big Switch Networks, Inc 4 // Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com> 5 6 // The tests contained in this file are extracted from the unit tests of uBPF software. Each test 7 // in this file has a name in the form `test_verifier_<name>`, and corresponds to the 8 // (human-readable) code in `ubpf/tree/master/tests/<name>`, available at 9 // <https://github.com/iovisor/ubpf/tree/master/tests> (hyphen had to be replaced with underscores 10 // as Rust will not accept them in function names). It is strongly advised to refer to the uBPF 11 // version to understand what these program do. 12 // 13 // Each program was assembled from the uBPF version with the assembler provided by uBPF itself, and 14 // available at <https://github.com/iovisor/ubpf/tree/master/ubpf>. 15 // The very few modifications that have been realized should be indicated. 16 17 // These are unit tests for the eBPF “verifier”. 18 19 extern crate rbpf; 20 21 use rbpf::{assembler::assemble, ebpf}; 22 23 #[test] 24 #[should_panic(expected = "[Verifier] Error: unsupported argument for LE/BE (insn #0)")] 25 fn test_verifier_err_endian_size() { 26 let prog = &[ 27 0xdc, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 28 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 29 ]; 30 let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); 31 vm.execute_program().unwrap(); 32 } 33 34 #[test] 35 #[should_panic(expected = "[Verifier] Error: incomplete LD_DW instruction (insn #0)")] 36 fn test_verifier_err_incomplete_lddw() { 37 // Note: ubpf has test-err-incomplete-lddw2, which is the same 38 let prog = &[ 39 0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 40 0x00, 41 ]; 42 let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); 43 vm.execute_program().unwrap(); 44 } 45 46 #[test] 47 #[should_panic(expected = "[Verifier] Error: infinite loop")] 48 fn test_verifier_err_infinite_loop() { 49 let prog = assemble( 50 " 51 ja -1 52 exit", 53 ) 54 .unwrap(); 55 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 56 vm.execute_program().unwrap(); 57 } 58 59 #[test] 60 #[should_panic(expected = "[Verifier] Error: invalid destination register (insn #0)")] 61 fn test_verifier_err_invalid_reg_dst() { 62 let prog = assemble( 63 " 64 mov r11, 1 65 exit", 66 ) 67 .unwrap(); 68 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 69 vm.execute_program().unwrap(); 70 } 71 72 #[test] 73 #[should_panic(expected = "[Verifier] Error: invalid source register (insn #0)")] 74 fn test_verifier_err_invalid_reg_src() { 75 let prog = assemble( 76 " 77 mov r0, r11 78 exit", 79 ) 80 .unwrap(); 81 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 82 vm.execute_program().unwrap(); 83 } 84 85 #[test] 86 #[should_panic(expected = "[Verifier] Error: jump to middle of LD_DW at #2 (insn #0)")] 87 fn test_verifier_err_jmp_lddw() { 88 let prog = assemble( 89 " 90 ja +1 91 lddw r0, 0x1122334455667788 92 exit", 93 ) 94 .unwrap(); 95 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 96 vm.execute_program().unwrap(); 97 } 98 99 #[test] 100 #[should_panic(expected = "[Verifier] Error: jump out of code to #3 (insn #0)")] 101 fn test_verifier_err_jmp_out() { 102 let prog = assemble( 103 " 104 ja +2 105 exit", 106 ) 107 .unwrap(); 108 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 109 vm.execute_program().unwrap(); 110 } 111 112 #[test] 113 #[should_panic(expected = "[Verifier] Error: program does not end with “EXIT” instruction")] 114 fn test_verifier_err_no_exit() { 115 let prog = assemble( 116 " 117 mov32 r0, 0", 118 ) 119 .unwrap(); 120 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 121 vm.execute_program().unwrap(); 122 } 123 124 #[test] 125 fn test_verifier_err_no_exit_backward_jump() { 126 let prog = assemble( 127 " 128 ja +1 129 exit 130 ja -2", 131 ) 132 .unwrap(); 133 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 134 vm.execute_program().unwrap(); 135 } 136 137 #[test] 138 #[should_panic(expected = "[Verifier] Error: eBPF program length limited to 1000000, here 1000001")] 139 fn test_verifier_err_too_many_instructions() { 140 // uBPF uses 65637 instructions, because it sets its limit at 65636. 141 // We use the classic 4096 limit from kernel, so no need to produce as many instructions. 142 let mut prog = (0..(1_000_000 * ebpf::INSN_SIZE)) 143 .map(|x| match x % 8 { 144 0 => 0xb7, 145 1 => 0x01, 146 _ => 0, 147 }) 148 .collect::<Vec<u8>>(); 149 prog.append(&mut vec![0x95, 0, 0, 0, 0, 0, 0, 0]); 150 151 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 152 vm.execute_program().unwrap(); 153 } 154 155 #[test] 156 #[should_panic(expected = "[Verifier] Error: unknown eBPF opcode 0x6 (insn #0)")] 157 fn test_verifier_err_unknown_opcode() { 158 let prog = &[ 159 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 160 0x00, 161 ]; 162 let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); 163 vm.execute_program().unwrap(); 164 } 165 166 #[test] 167 #[should_panic(expected = "[Verifier] Error: cannot write into register r10 (insn #0)")] 168 fn test_verifier_err_write_r10() { 169 let prog = assemble( 170 " 171 mov r10, 1 172 exit", 173 ) 174 .unwrap(); 175 let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap(); 176 vm.execute_program().unwrap(); 177 } 178