diff --git a/src/interpreter.rs b/src/interpreter.rs index 2a4581903..23961980b 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -528,7 +528,9 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { // Do not delegate the check to the verifier, since self.registered functions can be // changed after the program has been verified. ebpf::CALL_IMM => { - if let Some((_, function)) = self.executable.get_loader().get_function_registry(self.executable.get_sbpf_version()).lookup_by_key(insn.imm as u32) { + if let (false, Some((_, function))) = + (self.executable.get_sbpf_version().static_syscalls(), + self.executable.get_loader().get_function_registry(self.executable.get_sbpf_version()).lookup_by_key(insn.imm as u32)) { // SBPFv1 syscall self.reg[0] = match self.dispatch_syscall(function) { ProgramResult::Ok(value) => *value, diff --git a/src/jit.rs b/src/jit.rs index 54267b9c5..1d7222666 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -708,7 +708,9 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { ebpf::JSLE_REG => self.emit_conditional_branch_reg(0x8e, false, src, dst, target_pc), ebpf::CALL_IMM => { // For JIT, external functions MUST be registered at compile time. - if let Some((_, function)) = self.executable.get_loader().get_function_registry(self.executable.get_sbpf_version()).lookup_by_key(insn.imm as u32) { + if let (false, Some((_, function))) = + (self.executable.get_sbpf_version().static_syscalls(), + self.executable.get_loader().get_function_registry(self.executable.get_sbpf_version()).lookup_by_key(insn.imm as u32)) { // SBPFv1 syscall self.emit_syscall_dispatch(function); } else if let Some((_function_name, target_pc)) = self.executable.get_function_registry().lookup_by_key(insn.imm as u32) { diff --git a/tests/execution.rs b/tests/execution.rs index a75aad0ab..df8bfb52d 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -4088,6 +4088,40 @@ fn test_mod() { ); } +#[test] +fn test_invalid_call_imm() { + // In SBPFv2, `call_imm` N shall not be dispatched to a syscall. + let prog = &[ + 0x85, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // call_imm 2 + 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + let config = Config { + enabled_sbpf_versions: SBPFVersion::V2..=SBPFVersion::V2, + enable_instruction_tracing: true, + ..Config::default() + }; + let mut loader = BuiltinProgram::new_loader_with_dense_registration(config); + loader + .register_function("syscall_string", 2, syscalls::SyscallString::vm) + .unwrap(); + let mut executable = Executable::::from_text_bytes( + prog, + Arc::new(loader), + SBPFVersion::V2, + FunctionRegistry::default(), + ) + .unwrap(); + + test_interpreter_and_jit!( + false, + executable, + [], + TestContextObject::new(1), + ProgramResult::Err(EbpfError::UnsupportedInstruction), + ); +} + #[test] #[should_panic(expected = "Invalid syscall should have been detected in the verifier.")] fn test_invalid_exit_or_return() {