diff --git a/src/interpreter.rs b/src/interpreter.rs index 7f6eb8c3..35a9699e 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -469,7 +469,7 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { return false; } check_pc!(self, next_pc, target_pc.wrapping_sub(self.program_vm_addr) / ebpf::INSN_SIZE as u64); - if self.executable.get_sbpf_version().static_syscalls() && self.executable.get_function_registry().lookup_by_key(next_pc as u32).is_none() { + if self.executable.get_sbpf_version().stricter_controlflow() && self.executable.get_function_registry().lookup_by_key(next_pc as u32).is_none() { self.vm.due_insn_count += 1; self.reg[11] = next_pc; throw_error!(self, EbpfError::UnsupportedInstruction); diff --git a/src/jit.rs b/src/jit.rs index 05935ff7..477c263c 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -1632,7 +1632,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { } // There is no `VerifierError::JumpToMiddleOfLDDW` for `call imm` so patch it here let call_unsupported_instruction = self.anchors[ANCHOR_CALL_UNSUPPORTED_INSTRUCTION] as usize; - if self.executable.get_sbpf_version().static_syscalls() { + if self.executable.get_sbpf_version().stricter_controlflow() { let mut prev_pc = 0; for current_pc in self.executable.get_function_registry().keys() { if current_pc as usize >= self.result.pc_section.len() { diff --git a/src/program.rs b/src/program.rs index fcb22898..500aa5fc 100644 --- a/src/program.rs +++ b/src/program.rs @@ -76,6 +76,11 @@ impl SBPFVersion { pub fn static_syscalls(&self) -> bool { self != &SBPFVersion::V1 } + + /// Restricts jump and call targets to function boundaries + pub fn stricter_controlflow(&self) -> bool { + self != &SBPFVersion::V1 + } } /// Holds the function symbols of an Executable diff --git a/src/verifier.rs b/src/verifier.rs index 87f8b572..b6f25eeb 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -231,7 +231,7 @@ impl Verifier for RequisiteVerifier { let insn = ebpf::get_insn(prog, insn_ptr); let mut store = false; - if sbpf_version.static_syscalls() && function_iter.peek() == Some(&insn_ptr) { + if sbpf_version.stricter_controlflow() && function_iter.peek() == Some(&insn_ptr) { function_range.start = function_iter.next().unwrap_or(0); function_range.end = *function_iter.peek().unwrap_or(&program_range.end); let insn = ebpf::get_insn(prog, function_range.end.saturating_sub(1)); @@ -374,8 +374,8 @@ impl Verifier for RequisiteVerifier { ebpf::JSLT_REG => { check_jmp_offset(prog, insn_ptr, &function_range)?; }, ebpf::JSLE_IMM => { check_jmp_offset(prog, insn_ptr, &function_range)?; }, ebpf::JSLE_REG => { check_jmp_offset(prog, insn_ptr, &function_range)?; }, - ebpf::CALL_IMM if sbpf_version.static_syscalls() && insn.src != 0 => { check_call_target(insn.imm as u32, function_registry)?; }, - ebpf::CALL_IMM if sbpf_version.static_syscalls() && insn.src == 0 => { check_call_target(insn.imm as u32, syscall_registry)?; }, + ebpf::CALL_IMM if sbpf_version.stricter_controlflow() && insn.src != 0 => { check_call_target(insn.imm as u32, function_registry)?; }, + ebpf::CALL_IMM if sbpf_version.stricter_controlflow() && insn.src == 0 => { check_call_target(insn.imm as u32, syscall_registry)?; }, ebpf::CALL_IMM => {}, ebpf::CALL_REG => { check_callx_register(&insn, insn_ptr, sbpf_version)?; }, ebpf::EXIT => {},