diff --git a/src/jit.rs b/src/jit.rs index 89efd9c3..9c4a92af 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -1020,8 +1020,25 @@ impl JitCompiler { let src = REGISTER_MAP[insn.src as usize]; let target_pc = (self.pc as isize + insn.off as isize + 1) as usize; - match insn.opc { + if self.config.disable_deprecated_load_instructions { + match insn.opc { + ebpf::LD_ABS_B + | ebpf::LD_ABS_H + | ebpf::LD_ABS_W + | ebpf::LD_ABS_DW + | ebpf::LD_IND_B + | ebpf::LD_IND_H + | ebpf::LD_IND_W + | ebpf::LD_IND_DW => { + return Err(EbpfError::UnsupportedInstruction( + self.pc + ebpf::ELF_INSN_DUMP_OFFSET, + )) + } + _ => {} + }; + } + match insn.opc { // BPF_LD class ebpf::LD_ABS_B => { emit_address_translation(self, R11, Value::Constant64(ebpf::MM_INPUT_START.wrapping_add(insn.imm as u32 as u64) as i64, true), 1, AccessType::Load)?; diff --git a/src/vm.rs b/src/vm.rs index b327c92b..d4098190 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -207,6 +207,8 @@ pub struct Config { pub verify_mul64_imm_nonzero: bool, /// Feature flag for the SHIFT_IMM >= 32 verification check pub verify_shift32_imm: bool, + /// Disable ldabs* and ldind* instructions + pub disable_deprecated_load_instructions: bool, } impl Default for Config { fn default() -> Self { @@ -221,6 +223,7 @@ impl Default for Config { reject_unresolved_syscalls: false, reject_section_virtual_address_file_offset_mismatch: false, reject_all_writable_sections: false, + disable_deprecated_load_instructions: false, noop_instruction_ratio: 1.0 / 256.0, sanitize_user_provided_values: true, encrypt_environment_registers: true, @@ -668,6 +671,7 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EbpfVm<'a, E, I> { // Check config outside of the instruction loop let instruction_meter_enabled = self.executable.get_config().enable_instruction_meter; let instruction_tracing_enabled = self.executable.get_config().enable_instruction_tracing; + let disable_deprecated_load_instructions = self.executable.get_config().disable_deprecated_load_instructions; // Loop on instructions let entry = self.executable.get_entrypoint_instruction_offset()?; @@ -691,6 +695,24 @@ impl<'a, E: UserDefinedError, I: InstructionMeter> EbpfVm<'a, E, I> { self.tracer.trace(state); } + if disable_deprecated_load_instructions { + match insn.opc { + ebpf::LD_ABS_B + | ebpf::LD_ABS_H + | ebpf::LD_ABS_W + | ebpf::LD_ABS_DW + | ebpf::LD_IND_B + | ebpf::LD_IND_H + | ebpf::LD_IND_W + | ebpf::LD_IND_DW => { + return Err(EbpfError::UnsupportedInstruction( + pc + ebpf::ELF_INSN_DUMP_OFFSET, + )) + } + _ => {} + }; + } + match insn.opc { // BPF_LD class diff --git a/tests/ubpf_execution.rs b/tests/ubpf_execution.rs index 917e0564..12858a45 100644 --- a/tests/ubpf_execution.rs +++ b/tests/ubpf_execution.rs @@ -76,6 +76,15 @@ macro_rules! test_interpreter_and_jit { } macro_rules! test_interpreter_and_jit_asm { + ($source:tt, $config:tt, $mem:tt, ($($location:expr => $syscall_function:expr; $syscall_context_object:expr),* $(,)?), $check:block, $expected_instruction_count:expr) => { + #[allow(unused_mut)] + { + let mut syscall_registry = SyscallRegistry::default(); + $(test_interpreter_and_jit!(register, syscall_registry, $location => $syscall_function; $syscall_context_object);)* + let mut executable = assemble($source, None, $config, syscall_registry).unwrap(); + test_interpreter_and_jit!(executable, $mem, ($($location => $syscall_function; $syscall_context_object),*), $check, $expected_instruction_count); + } + }; ($source:tt, $mem:tt, ($($location:expr => $syscall_function:expr; $syscall_context_object:expr),* $(,)?), $check:block, $expected_instruction_count:expr) => { #[allow(unused_mut)] { @@ -83,10 +92,7 @@ macro_rules! test_interpreter_and_jit_asm { enable_instruction_tracing: true, ..Config::default() }; - let mut syscall_registry = SyscallRegistry::default(); - $(test_interpreter_and_jit!(register, syscall_registry, $location => $syscall_function; $syscall_context_object);)* - let mut executable = assemble($source, None, config, syscall_registry).unwrap(); - test_interpreter_and_jit!(executable, $mem, ($($location => $syscall_function; $syscall_context_object),*), $check, $expected_instruction_count); + test_interpreter_and_jit_asm!($source, config, $mem, ($($location => $syscall_function; $syscall_context_object),*), $check, $expected_instruction_count); } }; } @@ -1009,6 +1015,27 @@ fn test_err_ldabsb_nomem() { ); } +#[test] +fn test_err_ldabsb_disabled() { + let config = Config { + disable_deprecated_load_instructions: true, + ..Config::default() + }; + + test_interpreter_and_jit_asm!( + " + ldabsb 0x3 + exit", + config, + [], + (), + { + |_vm, res: Result| matches!(res.unwrap_err(), EbpfError::UnsupportedInstruction(pc) if pc == 29) + }, + 1 + ); +} + #[test] fn test_ldindb() { test_interpreter_and_jit_asm!(