ubpf_verifier.rs 5.3 KB

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