diff --git a/src/jit.rs b/src/jit.rs index cfd5e658..245ea262 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -1010,6 +1010,7 @@ impl JitCompiler { if self.config.enable_instruction_tracing { X86Instruction::load_immediate(OperandSize::S64, R11, self.pc as i64).emit(self)?; emit_call(self, TARGET_PC_TRACE)?; + X86Instruction::load_immediate(OperandSize::S64, R11, 0).emit(self)?; } let dst = REGISTER_MAP[insn.dst as usize]; @@ -1267,7 +1268,11 @@ impl JitCompiler { emit_jcc(self, 0x85, TARGET_PC_RUST_EXCEPTION)?; } else if let Some(target_pc) = executable.lookup_bpf_function(insn.imm as u32) { emit_bpf_call(self, Value::Constant64(target_pc as i64, false))?; + } else if self.config.disable_unresolved_symbols_at_runtime { + X86Instruction::load_immediate(OperandSize::S64, R11, self.pc as i64).emit(self)?; + emit_jmp(self, TARGET_PC_CALL_UNSUPPORTED_INSTRUCTION)?; } else { + emit_validate_instruction_count(self, true, Some(self.pc))?; // executable.report_unresolved_symbol(self.pc)?; // Workaround for unresolved symbols in ELF: Report error at runtime instead of compiletime emit_rust_call(self, Value::Constant64(Executable::::report_unresolved_symbol as *const u8 as i64, false), &[ @@ -1276,7 +1281,6 @@ impl JitCompiler { Argument { index: 0, value: Value::RegisterIndirect(RBP, slot_on_environment_stack(self, EnvironmentStackSlot::OptRetValPtr), false) }, ], None, true)?; X86Instruction::load_immediate(OperandSize::S64, R11, self.pc as i64).emit(self)?; - emit_validate_instruction_count(self, false, None)?; emit_jmp(self, TARGET_PC_RUST_EXCEPTION)?; } }, diff --git a/src/vm.rs b/src/vm.rs index 2edfd6d5..f04aa978 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -199,6 +199,8 @@ pub struct Config { pub enable_instruction_tracing: bool, /// Enable dynamic string allocation for labels pub enable_symbol_and_section_labels: bool, + /// Disable reporting of unresolved symbols at runtime + pub disable_unresolved_symbols_at_runtime: bool, /// Reject ELF files containing issues that the verifier did not catch before (up to v0.2.21) pub reject_broken_elfs: bool, /// Ratio of random no-ops per instruction in JIT (0.0 = OFF) @@ -218,6 +220,7 @@ impl Default for Config { enable_instruction_meter: true, enable_instruction_tracing: false, enable_symbol_and_section_labels: false, + disable_unresolved_symbols_at_runtime: true, reject_broken_elfs: false, noop_instruction_ratio: 1.0 / 256.0, sanitize_user_provided_values: true, @@ -966,6 +969,8 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EbpfVm<'a, E, I> { next_pc, )?; next_pc = self.check_pc(pc, target_pc)?; + } else if self.executable.get_config().disable_unresolved_symbols_at_runtime { + return Err(EbpfError::UnsupportedInstruction(pc + ebpf::ELF_INSN_DUMP_OFFSET)); } else { self.executable.report_unresolved_symbol(pc)?; } diff --git a/tests/ubpf_execution.rs b/tests/ubpf_execution.rs index a3fbc507..bb9020b3 100644 --- a/tests/ubpf_execution.rs +++ b/tests/ubpf_execution.rs @@ -3027,8 +3027,8 @@ fn test_non_terminate_early() { { |_vm, res: Result| { matches!(res.unwrap_err(), - EbpfError::ElfError(ElfError::UnresolvedSymbol(a, b, c)) - if a == "Unknown" && b == 35 && c == 48 + EbpfError::UnsupportedInstruction(pc) + if pc == 35 ) } }, @@ -3179,7 +3179,7 @@ fn test_err_call_unresolved() { [], (), { - |_vm, res: Result| matches!(res.unwrap_err(), EbpfError::ElfError(ElfError::UnresolvedSymbol(symbol, pc, offset)) if symbol == "Unknown" && pc == 34 && offset == 40) + |_vm, res: Result| matches!(res.unwrap_err(), EbpfError::UnsupportedInstruction(pc) if pc == 34) }, 6 );