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)")]
test_verifier_err_endian_size()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)")]
test_verifier_err_incomplete_lddw()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")]
test_verifier_err_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)")]
test_verifier_err_invalid_reg_dst()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)")]
test_verifier_err_invalid_reg_src()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)")]
test_verifier_err_jmp_lddw()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)")]
test_verifier_err_jmp_out()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")]
test_verifier_err_no_exit()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]
test_verifier_err_no_exit_backward_jump()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")]
test_verifier_err_too_many_instructions()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)")]
test_verifier_err_unknown_opcode()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)")]
test_verifier_err_write_r10()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