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