Ver Fonte

src/verifier.rs: Allow ending with backward jumps

Programs don't always have to have their list of instructions ending
with an `exit` instruction, they can jump backwards to a branch ending
with `exit`.

We don't have the checks to validate that all branches end with `exit`
in the verifier, but we can allow the last instruction to be a backward
jump, at least.

Fixes: #62
Signed-off-by: Quentin Monnet <quentin@isovalent.com>
Quentin Monnet há 2 anos atrás
pai
commit
e90e6a9c77
2 ficheiros alterados com 12 adições e 2 exclusões
  1. 2 2
      src/verifier.rs
  2. 10 0
      tests/ubpf_verifier.rs

+ 2 - 2
src/verifier.rs

@@ -40,8 +40,8 @@ fn check_prog_len(prog: &[u8]) -> Result<(), Error> {
     if prog.is_empty() {
         reject("no program set, call set_program() to load one")?;
     }
-    let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
-    if last_insn.opc != ebpf::EXIT {
+    let last_opc = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1).opc;
+    if last_opc & ebpf::BPF_CLS_MASK != ebpf::BPF_JMP {
         reject("program does not end with “EXIT” instruction")?;
     }
 

+ 10 - 0
tests/ubpf_verifier.rs

@@ -115,6 +115,16 @@ fn test_verifier_err_no_exit() {
     vm.execute_program().unwrap();
 }
 
+#[test]
+fn test_verifier_err_no_exit_backward_jump() {
+    let prog = assemble("
+        ja +1
+        exit
+        ja -2").unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
+    vm.execute_program().unwrap();
+}
+
 #[test]
 #[should_panic(expected = "[Verifier] Error: eBPF program length limited to 4096, here 4097")]
 fn test_verifier_err_too_many_instructions() {