diff --git a/benches/memory_mapping.rs b/benches/memory_mapping.rs index 799db71d1..a6966db4b 100644 --- a/benches/memory_mapping.rs +++ b/benches/memory_mapping.rs @@ -81,7 +81,6 @@ macro_rules! bench_gapped_randomized_access_with_1024_entries { AccessType::Load, 0x100000000 + (prng.gen::() % frame_count * (frame_size * 2)), 1, - 0, ) .is_ok()); }); @@ -119,7 +118,6 @@ macro_rules! bench_randomized_access_with_0001_entry { AccessType::Load, 0x100000000 + (prng.gen::() % content.len() as u64), 1, - 0, ); }); } @@ -153,7 +151,6 @@ macro_rules! bench_randomized_access_with_n_entries { AccessType::Load, 0x100000000 + (prng.gen::() % end_address), 1, - 0, ); }); } @@ -199,7 +196,7 @@ macro_rules! bench_randomized_mapping_with_n_entries { let config = Config::default(); let memory_mapping = $mem::new(memory_regions, &config, &SBPFVersion::V2).unwrap(); bencher.iter(|| { - let _ = memory_mapping.map(AccessType::Load, 0x100000000, 1, 0); + let _ = memory_mapping.map(AccessType::Load, 0x100000000, 1); }); } }; @@ -248,7 +245,7 @@ macro_rules! bench_mapping_with_n_entries { let config = Config::default(); let memory_mapping = $mem::new(memory_regions, &config, &SBPFVersion::V2).unwrap(); bencher.iter(|| { - let _ = memory_mapping.map(AccessType::Load, 0x100000000, 1, 0); + let _ = memory_mapping.map(AccessType::Load, 0x100000000, 1); }); } }; @@ -310,13 +307,13 @@ fn do_bench_mapping_operation(bencher: &mut Bencher, op: MemoryOperation, vm_add match op { MemoryOperation::Map => bencher.iter(|| { - let _ = memory_mapping.map(AccessType::Load, vm_addr, 8, 0).unwrap(); + let _ = memory_mapping.map(AccessType::Load, vm_addr, 8).unwrap(); }), MemoryOperation::Load => bencher.iter(|| { - let _ = memory_mapping.load::(vm_addr, 0).unwrap(); + let _ = memory_mapping.load::(vm_addr).unwrap(); }), MemoryOperation::Store(val) => bencher.iter(|| { - let _ = memory_mapping.store(val, vm_addr, 0).unwrap(); + let _ = memory_mapping.store(val, vm_addr).unwrap(); }), } } diff --git a/src/debugger.rs b/src/debugger.rs index be35061a3..23f971ee4 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -152,7 +152,6 @@ impl<'a, 'b, C: ContextObject> Target for Interpreter<'a, 'b, C> { fn get_host_ptr( interpreter: &mut Interpreter, mut vm_addr: u64, - pc: usize, ) -> Result<*mut u8, EbpfError> { if vm_addr < ebpf::MM_PROGRAM_START { vm_addr += ebpf::MM_PROGRAM_START; @@ -161,7 +160,6 @@ fn get_host_ptr( AccessType::Load, vm_addr, std::mem::size_of::() as u64, - pc + ebpf::ELF_INSN_DUMP_OFFSET, ) { ProgramResult::Ok(host_addr) => Ok(host_addr as *mut u8), ProgramResult::Err(err) => Err(err), @@ -197,7 +195,7 @@ impl<'a, 'b, C: ContextObject> SingleThreadBase for Interpreter<'a, 'b, C> { fn read_addrs(&mut self, start_addr: u64, data: &mut [u8]) -> TargetResult<(), Self> { for (vm_addr, val) in (start_addr..).zip(data.iter_mut()) { - let host_ptr = match get_host_ptr(self, vm_addr, self.pc) { + let host_ptr = match get_host_ptr(self, vm_addr) { Ok(host_ptr) => host_ptr, // The debugger is sometimes requesting more data than we have access to, just skip these _ => continue, diff --git a/src/error.rs b/src/error.rs index 513ee9410..411db9858 100644 --- a/src/error.rs +++ b/src/error.rs @@ -63,15 +63,11 @@ pub enum EbpfError { #[error("Invalid memory region at index {0}")] InvalidMemoryRegion(usize), /// Access violation (general) - #[error( - "Access violation in {4} section at address {2:#x} of size {3:?} at BPF instruction #{0}" - )] - AccessViolation(usize, AccessType, u64, u64, &'static str), + #[error("Access violation in {3} section at address {1:#x} of size {2:?}")] + AccessViolation(AccessType, u64, u64, &'static str), /// Access violation (stack specific) - #[error( - "Access violation in stack frame {4} at address {2:#x} of size {3:?} at BPF instruction #{0}" - )] - StackAccessViolation(usize, AccessType, u64, u64, i64), + #[error("Access violation in stack frame {3} at address {1:#x} of size {2:?}")] + StackAccessViolation(AccessType, u64, u64, i64), /// Invalid instruction #[error("invalid BPF instruction")] InvalidInstruction, diff --git a/src/interpreter.rs b/src/interpreter.rs index cb0679787..529d59b5f 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -22,11 +22,10 @@ use std::convert::TryInto; /// Virtual memory operation helper. macro_rules! translate_memory_access { - (_impl, $self:ident, $op:ident, $vm_addr:ident, $pc:ident, $T:ty, $($rest:expr),*) => { + (_impl, $self:ident, $op:ident, $vm_addr:ident, $T:ty, $($rest:expr),*) => { match $self.vm.memory_mapping.$op::<$T>( $($rest,)* $vm_addr, - $pc + ebpf::ELF_INSN_DUMP_OFFSET, ) { ProgramResult::Ok(v) => v, ProgramResult::Err(err) => { @@ -37,13 +36,13 @@ macro_rules! translate_memory_access { }; // MemoryMapping::load() - ($self:ident, load, $vm_addr:ident, $pc:ident, $T:ty) => { - translate_memory_access!(_impl, $self, load, $vm_addr, $pc, $T,) + ($self:ident, load, $vm_addr:ident, $T:ty) => { + translate_memory_access!(_impl, $self, load, $vm_addr, $T,) }; // MemoryMapping::store() - ($self:ident, store, $value:expr, $vm_addr:ident, $pc:ident, $T:ty) => { - translate_memory_access!(_impl, $self, store, $vm_addr, $pc, $T, ($value) as $T); + ($self:ident, store, $value:expr, $vm_addr:ident, $T:ty) => { + translate_memory_access!(_impl, $self, store, $vm_addr, $T, ($value) as $T); }; } @@ -202,55 +201,55 @@ impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { // BPF_LDX class ebpf::LD_B_REG => { let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; - self.reg[dst] = translate_memory_access!(self, load, vm_addr, pc, u8); + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u8); }, ebpf::LD_H_REG => { let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; - self.reg[dst] = translate_memory_access!(self, load, vm_addr, pc, u16); + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u16); }, ebpf::LD_W_REG => { let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; - self.reg[dst] = translate_memory_access!(self, load, vm_addr, pc, u32); + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u32); }, ebpf::LD_DW_REG => { let vm_addr = (self.reg[src] as i64).wrapping_add(insn.off as i64) as u64; - self.reg[dst] = translate_memory_access!(self, load, vm_addr, pc, u64); + self.reg[dst] = translate_memory_access!(self, load, vm_addr, u64); }, // BPF_ST class ebpf::ST_B_IMM => { let vm_addr = (self.reg[dst] as i64).wrapping_add( insn.off as i64) as u64; - translate_memory_access!(self, store, insn.imm, vm_addr, pc, u8); + translate_memory_access!(self, store, insn.imm, vm_addr, u8); }, ebpf::ST_H_IMM => { let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; - translate_memory_access!(self, store, insn.imm, vm_addr, pc, u16); + translate_memory_access!(self, store, insn.imm, vm_addr, u16); }, ebpf::ST_W_IMM => { let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; - translate_memory_access!(self, store, insn.imm, vm_addr, pc, u32); + translate_memory_access!(self, store, insn.imm, vm_addr, u32); }, ebpf::ST_DW_IMM => { let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; - translate_memory_access!(self, store, insn.imm, vm_addr, pc, u64); + translate_memory_access!(self, store, insn.imm, vm_addr, u64); }, // BPF_STX class ebpf::ST_B_REG => { let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; - translate_memory_access!(self, store, self.reg[src], vm_addr, pc, u8); + translate_memory_access!(self, store, self.reg[src], vm_addr, u8); }, ebpf::ST_H_REG => { let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; - translate_memory_access!(self, store, self.reg[src], vm_addr, pc, u16); + translate_memory_access!(self, store, self.reg[src], vm_addr, u16); }, ebpf::ST_W_REG => { let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; - translate_memory_access!(self, store, self.reg[src], vm_addr, pc, u32); + translate_memory_access!(self, store, self.reg[src], vm_addr, u32); }, ebpf::ST_DW_REG => { let vm_addr = (self.reg[dst] as i64).wrapping_add(insn.off as i64) as u64; - translate_memory_access!(self, store, self.reg[src], vm_addr, pc, u64); + translate_memory_access!(self, store, self.reg[src], vm_addr, u64); }, // BPF_ALU class diff --git a/src/jit.rs b/src/jit.rs index 345cc8851..6e88f793d 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -181,22 +181,21 @@ impl PartialEq for JitProgram { // Used to define subroutines and then call them // See JitCompiler::set_anchor() and JitCompiler::relative_to_anchor() const ANCHOR_TRACE: usize = 0; -const ANCHOR_CALL_EXCEEDED_MAX_INSTRUCTIONS: usize = 1; +const ANCHOR_THROW_EXCEEDED_MAX_INSTRUCTIONS: usize = 1; const ANCHOR_EPILOGUE: usize = 2; const ANCHOR_THROW_EXCEPTION_UNCHECKED: usize = 3; const ANCHOR_EXIT: usize = 4; const ANCHOR_THROW_EXCEPTION: usize = 5; -const ANCHOR_ACCESS_VIOLATION: usize = 6; -const ANCHOR_CALL_DEPTH_EXCEEDED: usize = 7; -const ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT: usize = 8; -const ANCHOR_DIV_BY_ZERO: usize = 9; -const ANCHOR_DIV_OVERFLOW: usize = 10; -const ANCHOR_CALL_UNSUPPORTED_INSTRUCTION: usize = 11; -const ANCHOR_EXTERNAL_FUNCTION_CALL: usize = 12; -const ANCHOR_ANCHOR_INTERNAL_FUNCTION_CALL_PROLOGUE: usize = 13; -const ANCHOR_ANCHOR_INTERNAL_FUNCTION_CALL_REG: usize = 14; -const ANCHOR_TRANSLATE_MEMORY_ADDRESS: usize = 22; -const ANCHOR_COUNT: usize = 31; // Update me when adding or removing anchors +const ANCHOR_CALL_DEPTH_EXCEEDED: usize = 6; +const ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT: usize = 7; +const ANCHOR_DIV_BY_ZERO: usize = 8; +const ANCHOR_DIV_OVERFLOW: usize = 9; +const ANCHOR_CALL_UNSUPPORTED_INSTRUCTION: usize = 10; +const ANCHOR_EXTERNAL_FUNCTION_CALL: usize = 11; +const ANCHOR_ANCHOR_INTERNAL_FUNCTION_CALL_PROLOGUE: usize = 12; +const ANCHOR_ANCHOR_INTERNAL_FUNCTION_CALL_REG: usize = 13; +const ANCHOR_TRANSLATE_MEMORY_ADDRESS: usize = 21; +const ANCHOR_COUNT: usize = 30; // Update me when adding or removing anchors const REGISTER_MAP: [u8; 11] = [ CALLER_SAVED_REGISTERS[0], @@ -215,8 +214,8 @@ const REGISTER_MAP: [u8; 11] = [ // Special registers: // ARGUMENT_REGISTERS[0] RDI BPF program counter limit (used by instruction meter) // CALLER_SAVED_REGISTERS[8] R11 Scratch register -// CALLER_SAVED_REGISTERS[7] R10 Unused for the most part, scratch register for exception handling -// CALLEE_SAVED_REGISTERS[0] RBP Constant pointer to initial RSP - 8 +// CALLER_SAVED_REGISTERS[7] R10 Scratch register +// CALLEE_SAVED_REGISTERS[0] RBP Constant pointer to vm object, see slot_on_environment_stack() #[derive(Copy, Clone, Debug)] pub enum OperandSize { @@ -876,7 +875,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { } else { self.emit_ins(X86Instruction::cmp(OperandSize::S64, R11, ARGUMENT_REGISTERS[0], None)); } - self.emit_ins(X86Instruction::conditional_jump_immediate(if exclusive { 0x82 } else { 0x86 }, self.relative_to_anchor(ANCHOR_CALL_EXCEEDED_MAX_INSTRUCTIONS, 6))); + self.emit_ins(X86Instruction::conditional_jump_immediate(if exclusive { 0x82 } else { 0x86 }, self.relative_to_anchor(ANCHOR_THROW_EXCEEDED_MAX_INSTRUCTIONS, 6))); } #[inline] @@ -1285,9 +1284,9 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { fn emit_set_exception_kind(&mut self, err: EbpfError) { let err_discriminant = ProgramResult::Err(EbpfError::JitNotCompiled).discriminant(); let err_kind = unsafe { *(&err as *const _ as *const u64) }; - self.emit_ins(X86Instruction::lea(OperandSize::S64, RBP, R10, Some(X86IndirectAccess::Offset(self.slot_on_environment_stack(RuntimeEnvironmentSlot::ProgramResult) + std::mem::size_of::() as i32)))); - self.emit_ins(X86Instruction::store_immediate(OperandSize::S64, R10, X86IndirectAccess::Offset(-(std::mem::size_of::() as i32)), err_discriminant as i64)); // result.discriminant = err_discriminant; - self.emit_ins(X86Instruction::store_immediate(OperandSize::S64, R10, X86IndirectAccess::Offset(0), err_kind as i64)); // err.kind = err_kind; + self.emit_ins(X86Instruction::lea(OperandSize::S64, RBP, R10, Some(X86IndirectAccess::Offset(self.slot_on_environment_stack(RuntimeEnvironmentSlot::ProgramResult))))); + self.emit_ins(X86Instruction::store_immediate(OperandSize::S64, R10, X86IndirectAccess::Offset(0), err_discriminant as i64)); // result.discriminant = err_discriminant; + self.emit_ins(X86Instruction::store_immediate(OperandSize::S64, R10, X86IndirectAccess::Offset(std::mem::size_of::() as i32), err_kind as i64)); // err.kind = err_kind; } fn emit_result_is_err(&mut self, destination: u8) { @@ -1341,7 +1340,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { self.emit_ins(X86Instruction::return_near()); // Handler for EbpfError::ExceededMaxInstructions - self.set_anchor(ANCHOR_CALL_EXCEEDED_MAX_INSTRUCTIONS); + self.set_anchor(ANCHOR_THROW_EXCEEDED_MAX_INSTRUCTIONS); self.emit_set_exception_kind(EbpfError::ExceededMaxInstructions); self.emit_ins(X86Instruction::mov(OperandSize::S64, ARGUMENT_REGISTERS[0], R11)); // R11 = instruction_meter; // Fall through @@ -1354,7 +1353,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { self.set_anchor(ANCHOR_EXIT); self.emit_validate_instruction_count(false, None); self.emit_ins(X86Instruction::lea(OperandSize::S64, RBP, R10, Some(X86IndirectAccess::Offset(self.slot_on_environment_stack(RuntimeEnvironmentSlot::ProgramResult))))); - self.emit_ins(X86Instruction::store(OperandSize::S64, REGISTER_MAP[0], R10, X86IndirectAccess::Offset(8))); // result.return_value = R0; + self.emit_ins(X86Instruction::store(OperandSize::S64, REGISTER_MAP[0], R10, X86IndirectAccess::Offset(std::mem::size_of::() as i32))); // result.return_value = R0; self.emit_ins(X86Instruction::load_immediate(OperandSize::S64, REGISTER_MAP[0], 0)); self.emit_ins(X86Instruction::jump_immediate(self.relative_to_anchor(ANCHOR_EPILOGUE, 5))); @@ -1364,12 +1363,6 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { self.emit_validate_instruction_count(false, None); self.emit_ins(X86Instruction::jump_immediate(self.relative_to_anchor(ANCHOR_THROW_EXCEPTION_UNCHECKED, 5))); - // Handler for EbpfError::AccessViolation - self.set_anchor(ANCHOR_ACCESS_VIOLATION); - self.emit_ins(X86Instruction::store(OperandSize::S64, R11, R10, X86IndirectAccess::Offset(std::mem::size_of::() as i32 * 2))); // result.pc = self.pc; - self.emit_ins(X86Instruction::alu(OperandSize::S64, 0x81, 0, R10, ebpf::ELF_INSN_DUMP_OFFSET as i64, Some(X86IndirectAccess::Offset(std::mem::size_of::() as i32 * 2)))); // result.pc += ebpf::ELF_INSN_DUMP_OFFSET; - self.emit_ins(X86Instruction::jump_immediate(self.relative_to_anchor(ANCHOR_THROW_EXCEPTION, 5))); - // Handler for EbpfError::CallDepthExceeded self.set_anchor(ANCHOR_CALL_DEPTH_EXCEEDED); self.emit_set_exception_kind(EbpfError::CallDepthExceeded); @@ -1547,11 +1540,10 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> { self.emit_result_is_err(R11); self.emit_ins(X86Instruction::pop(R11)); // R11 = self.pc self.emit_ins(X86Instruction::xchg(OperandSize::S64, R11, RSP, Some(X86IndirectAccess::OffsetIndexShift(0, RSP, 0)))); // Swap return address and self.pc - self.emit_ins(X86Instruction::lea(OperandSize::S64, RBP, R10, Some(X86IndirectAccess::Offset(self.slot_on_environment_stack(RuntimeEnvironmentSlot::ProgramResult))))); - self.emit_ins(X86Instruction::conditional_jump_immediate(0x85, self.relative_to_anchor(ANCHOR_ACCESS_VIOLATION, 6))); + self.emit_ins(X86Instruction::conditional_jump_immediate(0x85, self.relative_to_anchor(ANCHOR_THROW_EXCEPTION, 6))); // unwrap() the result into R11 - self.emit_ins(X86Instruction::load(OperandSize::S64, R10, R11, X86IndirectAccess::Offset(8))); + self.emit_ins(X86Instruction::load(OperandSize::S64, RBP, R11, X86IndirectAccess::Offset(self.slot_on_environment_stack(RuntimeEnvironmentSlot::ProgramResult) + std::mem::size_of::() as i32))); self.emit_ins(X86Instruction::return_near()); } diff --git a/src/memory_region.rs b/src/memory_region.rs index 367d614d0..9f519f2d0 100644 --- a/src/memory_region.rs +++ b/src/memory_region.rs @@ -330,7 +330,7 @@ impl<'a> UnalignedMemoryMapping<'a> { } /// Given a list of regions translate from virtual machine to host address - pub fn map(&self, access_type: AccessType, vm_addr: u64, len: u64, pc: usize) -> ProgramResult { + pub fn map(&self, access_type: AccessType, vm_addr: u64, len: u64) -> ProgramResult { // Safety: // &mut references to the mapping cache are only created internally from methods that do not // invoke each other. UnalignedMemoryMapping is !Sync, so the cache reference below is @@ -346,7 +346,6 @@ impl<'a> UnalignedMemoryMapping<'a> { access_type, vm_addr, len, - pc, ) } }; @@ -357,21 +356,14 @@ impl<'a> UnalignedMemoryMapping<'a> { } } - generate_access_violation( - self.config, - self.sbpf_version, - access_type, - vm_addr, - len, - pc, - ) + generate_access_violation(self.config, self.sbpf_version, access_type, vm_addr, len) } /// Loads `size_of::()` bytes from the given address. /// /// See [MemoryMapping::load]. #[inline(always)] - pub fn load>(&self, mut vm_addr: u64, pc: usize) -> ProgramResult { + pub fn load>(&self, mut vm_addr: u64) -> ProgramResult { let mut len = mem::size_of::() as u64; debug_assert!(len <= mem::size_of::() as u64); @@ -399,7 +391,6 @@ impl<'a> UnalignedMemoryMapping<'a> { AccessType::Load, vm_addr, len, - pc, ) } }; @@ -443,7 +434,6 @@ impl<'a> UnalignedMemoryMapping<'a> { AccessType::Load, initial_vm_addr, initial_len, - pc, ) } @@ -451,7 +441,7 @@ impl<'a> UnalignedMemoryMapping<'a> { /// /// See [MemoryMapping::store]. #[inline] - pub fn store(&self, value: T, mut vm_addr: u64, pc: usize) -> ProgramResult { + pub fn store(&self, value: T, mut vm_addr: u64) -> ProgramResult { let mut len = mem::size_of::() as u64; // Safety: @@ -481,7 +471,6 @@ impl<'a> UnalignedMemoryMapping<'a> { AccessType::Store, vm_addr, len, - pc, ) } }; @@ -524,7 +513,6 @@ impl<'a> UnalignedMemoryMapping<'a> { AccessType::Store, initial_vm_addr, initial_len, - pc, ) } @@ -547,7 +535,7 @@ impl<'a> UnalignedMemoryMapping<'a> { } } Err( - generate_access_violation(self.config, self.sbpf_version, access_type, vm_addr, 0, 0) + generate_access_violation(self.config, self.sbpf_version, access_type, vm_addr, 0) .unwrap_err(), ) } @@ -647,7 +635,7 @@ impl<'a> AlignedMemoryMapping<'a> { } /// Given a list of regions translate from virtual machine to host address - pub fn map(&self, access_type: AccessType, vm_addr: u64, len: u64, pc: usize) -> ProgramResult { + pub fn map(&self, access_type: AccessType, vm_addr: u64, len: u64) -> ProgramResult { let index = vm_addr .checked_shr(ebpf::VIRTUAL_ADDRESS_BITS as u32) .unwrap_or(0) as usize; @@ -659,23 +647,16 @@ impl<'a> AlignedMemoryMapping<'a> { } } } - generate_access_violation( - self.config, - self.sbpf_version, - access_type, - vm_addr, - len, - pc, - ) + generate_access_violation(self.config, self.sbpf_version, access_type, vm_addr, len) } /// Loads `size_of::()` bytes from the given address. /// /// See [MemoryMapping::load]. #[inline] - pub fn load>(&self, vm_addr: u64, pc: usize) -> ProgramResult { + pub fn load>(&self, vm_addr: u64) -> ProgramResult { let len = mem::size_of::() as u64; - match self.map(AccessType::Load, vm_addr, len, pc) { + match self.map(AccessType::Load, vm_addr, len) { ProgramResult::Ok(host_addr) => { ProgramResult::Ok(unsafe { ptr::read_unaligned::(host_addr as *const _) }.into()) } @@ -687,11 +668,11 @@ impl<'a> AlignedMemoryMapping<'a> { /// /// See [MemoryMapping::store]. #[inline] - pub fn store(&self, value: T, vm_addr: u64, pc: usize) -> ProgramResult { + pub fn store(&self, value: T, vm_addr: u64) -> ProgramResult { let len = mem::size_of::() as u64; debug_assert!(len <= mem::size_of::() as u64); - match self.map(AccessType::Store, vm_addr, len, pc) { + match self.map(AccessType::Store, vm_addr, len) { ProgramResult::Ok(host_addr) => { // Safety: // map succeeded so we can write at least `len` bytes @@ -723,7 +704,7 @@ impl<'a> AlignedMemoryMapping<'a> { } } Err( - generate_access_violation(self.config, self.sbpf_version, access_type, vm_addr, 0, 0) + generate_access_violation(self.config, self.sbpf_version, access_type, vm_addr, 0) .unwrap_err(), ) } @@ -808,11 +789,11 @@ impl<'a> MemoryMapping<'a> { } /// Map virtual memory to host memory. - pub fn map(&self, access_type: AccessType, vm_addr: u64, len: u64, pc: usize) -> ProgramResult { + pub fn map(&self, access_type: AccessType, vm_addr: u64, len: u64) -> ProgramResult { match self { MemoryMapping::Identity => ProgramResult::Ok(vm_addr), - MemoryMapping::Aligned(m) => m.map(access_type, vm_addr, len, pc), - MemoryMapping::Unaligned(m) => m.map(access_type, vm_addr, len, pc), + MemoryMapping::Aligned(m) => m.map(access_type, vm_addr, len), + MemoryMapping::Unaligned(m) => m.map(access_type, vm_addr, len), } } @@ -820,13 +801,13 @@ impl<'a> MemoryMapping<'a> { /// /// Works across memory region boundaries. #[inline] - pub fn load>(&self, vm_addr: u64, pc: usize) -> ProgramResult { + pub fn load>(&self, vm_addr: u64) -> ProgramResult { match self { MemoryMapping::Identity => unsafe { ProgramResult::Ok(ptr::read_unaligned(vm_addr as *const T).into()) }, - MemoryMapping::Aligned(m) => m.load::(vm_addr, pc), - MemoryMapping::Unaligned(m) => m.load::(vm_addr, pc), + MemoryMapping::Aligned(m) => m.load::(vm_addr), + MemoryMapping::Unaligned(m) => m.load::(vm_addr), } } @@ -834,14 +815,14 @@ impl<'a> MemoryMapping<'a> { /// /// Works across memory region boundaries if `len` does not fit within a single region. #[inline] - pub fn store(&self, value: T, vm_addr: u64, pc: usize) -> ProgramResult { + pub fn store(&self, value: T, vm_addr: u64) -> ProgramResult { match self { MemoryMapping::Identity => unsafe { ptr::write_unaligned(vm_addr as *mut T, value); ProgramResult::Ok(0) }, - MemoryMapping::Aligned(m) => m.store(value, vm_addr, pc), - MemoryMapping::Unaligned(m) => m.store(value, vm_addr, pc), + MemoryMapping::Aligned(m) => m.store(value, vm_addr), + MemoryMapping::Unaligned(m) => m.store(value, vm_addr), } } @@ -902,7 +883,6 @@ fn generate_access_violation( access_type: AccessType, vm_addr: u64, len: u64, - pc: usize, ) -> ProgramResult { let stack_frame = (vm_addr as i64) .saturating_sub(ebpf::MM_STACK_START as i64) @@ -912,7 +892,6 @@ fn generate_access_violation( && (-1..(config.max_call_depth as i64).saturating_add(1)).contains(&stack_frame) { ProgramResult::Err(EbpfError::StackAccessViolation( - pc, access_type, vm_addr, len, @@ -927,7 +906,6 @@ fn generate_access_violation( _ => "unknown", }; ProgramResult::Err(EbpfError::AccessViolation( - pc, access_type, vm_addr, len, @@ -1060,13 +1038,13 @@ mod test { let config = Config::default(); let m = UnalignedMemoryMapping::new(vec![], &config, &SBPFVersion::V2).unwrap(); assert_error!( - m.map(AccessType::Load, ebpf::MM_INPUT_START, 8, 0), + m.map(AccessType::Load, ebpf::MM_INPUT_START, 8), "AccessViolation" ); let m = AlignedMemoryMapping::new(vec![], &config, &SBPFVersion::V2).unwrap(); assert_error!( - m.map(AccessType::Load, ebpf::MM_INPUT_START, 8, 0), + m.map(AccessType::Load, ebpf::MM_INPUT_START, 8), "AccessViolation" ); } @@ -1091,15 +1069,12 @@ mod test { for frame in 0..4 { let address = ebpf::MM_STACK_START + frame * 4; assert!(m.region(AccessType::Load, address).is_ok()); - assert!(m.map(AccessType::Load, address, 2, 0).is_ok()); - assert_error!( - m.map(AccessType::Load, address + 2, 2, 0), - "AccessViolation" - ); - assert_eq!(m.load::(address, 0).unwrap(), 0xFFFF); - assert_error!(m.load::(address + 2, 0), "AccessViolation"); - assert!(m.store::(0xFFFF, address, 0).is_ok()); - assert_error!(m.store::(0xFFFF, address + 2, 0), "AccessViolation"); + assert!(m.map(AccessType::Load, address, 2).is_ok()); + assert_error!(m.map(AccessType::Load, address + 2, 2), "AccessViolation"); + assert_eq!(m.load::(address).unwrap(), 0xFFFF); + assert_error!(m.load::(address + 2), "AccessViolation"); + assert!(m.store::(0xFFFF, address).is_ok()); + assert_error!(m.store::(0xFFFF, address + 2), "AccessViolation"); } } } @@ -1157,18 +1132,17 @@ mod test { .unwrap(); assert_eq!( - m.map(AccessType::Load, ebpf::MM_INPUT_START, 1, 0).unwrap(), + m.map(AccessType::Load, ebpf::MM_INPUT_START, 1).unwrap(), mem1.as_ptr() as u64 ); assert_eq!( - m.map(AccessType::Store, ebpf::MM_INPUT_START, 1, 0) - .unwrap(), + m.map(AccessType::Store, ebpf::MM_INPUT_START, 1).unwrap(), mem1.as_ptr() as u64 ); assert_error!( - m.map(AccessType::Load, ebpf::MM_INPUT_START, 2, 0), + m.map(AccessType::Load, ebpf::MM_INPUT_START, 2), "AccessViolation" ); @@ -1177,7 +1151,6 @@ mod test { AccessType::Load, ebpf::MM_INPUT_START + mem1.len() as u64, 1, - 0, ) .unwrap(), mem2.as_ptr() as u64 @@ -1188,7 +1161,6 @@ mod test { AccessType::Load, ebpf::MM_INPUT_START + (mem1.len() + mem2.len()) as u64, 1, - 0, ) .unwrap(), mem3.as_ptr() as u64 @@ -1199,7 +1171,6 @@ mod test { AccessType::Load, ebpf::MM_INPUT_START + (mem1.len() + mem2.len() + mem3.len()) as u64, 1, - 0, ) .unwrap(), mem4.as_ptr() as u64 @@ -1210,7 +1181,6 @@ mod test { AccessType::Load, ebpf::MM_INPUT_START + (mem1.len() + mem2.len() + mem3.len() + mem4.len()) as u64, 1, - 0, ), "AccessViolation" ); @@ -1369,19 +1339,16 @@ mod test { ) .unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0x2211); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0x44332211); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0x2211); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0x44332211); assert_eq!( - m.load::(ebpf::MM_INPUT_START, 0).unwrap(), + m.load::(ebpf::MM_INPUT_START).unwrap(), 0x8877665544332211 ); - assert_eq!(m.load::(ebpf::MM_INPUT_START + 1, 0).unwrap(), 0x3322); - assert_eq!( - m.load::(ebpf::MM_INPUT_START + 1, 0).unwrap(), - 0x55443322 - ); + assert_eq!(m.load::(ebpf::MM_INPUT_START + 1).unwrap(), 0x3322); + assert_eq!(m.load::(ebpf::MM_INPUT_START + 1).unwrap(), 0x55443322); assert_eq!( - m.load::(ebpf::MM_INPUT_START + 1, 0).unwrap(), + m.load::(ebpf::MM_INPUT_START + 1).unwrap(), 0x9988776655443322 ); } @@ -1413,16 +1380,16 @@ mod test { &SBPFVersion::V2, ) .unwrap(); - m.store(0x1122u16, ebpf::MM_INPUT_START, 0).unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0x1122); + m.store(0x1122u16, ebpf::MM_INPUT_START).unwrap(); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0x1122); - m.store(0x33445566u32, ebpf::MM_INPUT_START, 0).unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0x33445566); + m.store(0x33445566u32, ebpf::MM_INPUT_START).unwrap(); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0x33445566); - m.store(0x778899AABBCCDDEEu64, ebpf::MM_INPUT_START, 0) + m.store(0x778899AABBCCDDEEu64, ebpf::MM_INPUT_START) .unwrap(); assert_eq!( - m.load::(ebpf::MM_INPUT_START, 0).unwrap(), + m.load::(ebpf::MM_INPUT_START).unwrap(), 0x778899AABBCCDDEE ); } @@ -1441,20 +1408,20 @@ mod test { ) .unwrap(); - m.store(0x1122334455667788u64, ebpf::MM_INPUT_START, 0) + m.store(0x1122334455667788u64, ebpf::MM_INPUT_START) .unwrap(); assert_eq!( - m.load::(ebpf::MM_INPUT_START, 0).unwrap(), + m.load::(ebpf::MM_INPUT_START).unwrap(), 0x1122334455667788 ); - m.store(0x22334455u32, ebpf::MM_INPUT_START, 0).unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0x22334455); + m.store(0x22334455u32, ebpf::MM_INPUT_START).unwrap(); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0x22334455); - m.store(0x3344u16, ebpf::MM_INPUT_START, 0).unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0x3344); + m.store(0x3344u16, ebpf::MM_INPUT_START).unwrap(); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0x3344); - m.store(0x55u8, ebpf::MM_INPUT_START, 0).unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0x55); + m.store(0x55u8, ebpf::MM_INPUT_START).unwrap(); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0x55); } #[test] @@ -1475,20 +1442,17 @@ mod test { ) .unwrap(); - m.store(0x1122334455667788u64, ebpf::MM_INPUT_START, 0) + m.store(0x1122334455667788u64, ebpf::MM_INPUT_START) .unwrap(); assert_eq!( - m.load::(ebpf::MM_INPUT_START, 0).unwrap(), + m.load::(ebpf::MM_INPUT_START).unwrap(), 0x1122334455667788 ); - m.store(0xAABBCCDDu32, ebpf::MM_INPUT_START + 4, 0).unwrap(); - assert_eq!( - m.load::(ebpf::MM_INPUT_START + 4, 0).unwrap(), - 0xAABBCCDD - ); + m.store(0xAABBCCDDu32, ebpf::MM_INPUT_START + 4).unwrap(); + assert_eq!(m.load::(ebpf::MM_INPUT_START + 4).unwrap(), 0xAABBCCDD); - m.store(0xEEFFu16, ebpf::MM_INPUT_START + 6, 0).unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START + 6, 0).unwrap(), 0xEEFF); + m.store(0xEEFFu16, ebpf::MM_INPUT_START + 6).unwrap(); + assert_eq!(m.load::(ebpf::MM_INPUT_START + 6).unwrap(), 0xEEFF); } #[test] @@ -1505,21 +1469,12 @@ mod test { &SBPFVersion::V2, ) .unwrap(); - m.store(0x11u8, ebpf::MM_INPUT_START, 0).unwrap(); - assert_error!( - m.store(0x11u8, ebpf::MM_INPUT_START - 1, 0), - "AccessViolation" - ); - assert_error!( - m.store(0x11u8, ebpf::MM_INPUT_START + 1, 0), - "AccessViolation" - ); + m.store(0x11u8, ebpf::MM_INPUT_START).unwrap(); + assert_error!(m.store(0x11u8, ebpf::MM_INPUT_START - 1), "AccessViolation"); + assert_error!(m.store(0x11u8, ebpf::MM_INPUT_START + 1), "AccessViolation"); // this gets us line coverage for the case where we're completely // outside the address space (the case above is just on the edge) - assert_error!( - m.store(0x11u8, ebpf::MM_INPUT_START + 2, 0), - "AccessViolation" - ); + assert_error!(m.store(0x11u8, ebpf::MM_INPUT_START + 2), "AccessViolation"); let mut mem1 = vec![0xFF; 4]; let mut mem2 = vec![0xDD; 4]; @@ -1532,14 +1487,14 @@ mod test { &SBPFVersion::V2, ) .unwrap(); - m.store(0x1122334455667788u64, ebpf::MM_INPUT_START, 0) + m.store(0x1122334455667788u64, ebpf::MM_INPUT_START) .unwrap(); assert_eq!( - m.load::(ebpf::MM_INPUT_START, 0).unwrap(), + m.load::(ebpf::MM_INPUT_START).unwrap(), 0x1122334455667788u64 ); assert_error!( - m.store(0x1122334455667788u64, ebpf::MM_INPUT_START + 1, 0), + m.store(0x1122334455667788u64, ebpf::MM_INPUT_START + 1), "AccessViolation" ); } @@ -1558,10 +1513,10 @@ mod test { &SBPFVersion::V2, ) .unwrap(); - assert_eq!(m.load::(ebpf::MM_INPUT_START, 0).unwrap(), 0xff); - assert_error!(m.load::(ebpf::MM_INPUT_START - 1, 0), "AccessViolation"); - assert_error!(m.load::(ebpf::MM_INPUT_START + 1, 0), "AccessViolation"); - assert_error!(m.load::(ebpf::MM_INPUT_START + 2, 0), "AccessViolation"); + assert_eq!(m.load::(ebpf::MM_INPUT_START).unwrap(), 0xff); + assert_error!(m.load::(ebpf::MM_INPUT_START - 1), "AccessViolation"); + assert_error!(m.load::(ebpf::MM_INPUT_START + 1), "AccessViolation"); + assert_error!(m.load::(ebpf::MM_INPUT_START + 2), "AccessViolation"); let mem1 = vec![0xFF; 4]; let mem2 = vec![0xDD; 4]; @@ -1575,13 +1530,10 @@ mod test { ) .unwrap(); assert_eq!( - m.load::(ebpf::MM_INPUT_START, 0).unwrap(), + m.load::(ebpf::MM_INPUT_START).unwrap(), 0xDDDDDDDDFFFFFFFF ); - assert_error!( - m.load::(ebpf::MM_INPUT_START + 1, 0), - "AccessViolation" - ); + assert_error!(m.load::(ebpf::MM_INPUT_START + 1), "AccessViolation"); } #[test] @@ -1602,7 +1554,7 @@ mod test { &SBPFVersion::V2, ) .unwrap(); - m.store(0x11223344, ebpf::MM_INPUT_START, 0).unwrap(); + m.store(0x11223344, ebpf::MM_INPUT_START).unwrap(); } #[test] @@ -1622,7 +1574,7 @@ mod test { .unwrap(); assert_eq!( - m.map(AccessType::Load, ebpf::MM_INPUT_START, 1, 0).unwrap(), + m.map(AccessType::Load, ebpf::MM_INPUT_START, 1).unwrap(), mem1.as_ptr() as u64 ); @@ -1631,7 +1583,6 @@ mod test { AccessType::Load, ebpf::MM_INPUT_START + mem1.len() as u64, 1, - 0, ) .unwrap(), mem2.as_ptr() as u64 @@ -1672,7 +1623,6 @@ mod test { AccessType::Load, ebpf::MM_INPUT_START + mem1.len() as u64, 1, - 0, ) .unwrap(), mem3.as_ptr() as u64 @@ -1696,7 +1646,7 @@ mod test { .unwrap(); assert_eq!( - m.map(AccessType::Load, ebpf::MM_STACK_START, 1, 0).unwrap(), + m.map(AccessType::Load, ebpf::MM_STACK_START, 1).unwrap(), mem2.as_ptr() as u64 ); @@ -1725,7 +1675,7 @@ mod test { .unwrap(); assert_eq!( - m.map(AccessType::Load, ebpf::MM_STACK_START, 1, 0).unwrap(), + m.map(AccessType::Load, ebpf::MM_STACK_START, 1).unwrap(), mem3.as_ptr() as u64 ); } @@ -1753,13 +1703,11 @@ mod test { .unwrap(); assert_eq!( - m.map(AccessType::Load, ebpf::MM_PROGRAM_START, 1, 0) - .unwrap(), + m.map(AccessType::Load, ebpf::MM_PROGRAM_START, 1).unwrap(), original.as_ptr() as u64 ); assert_eq!( - m.map(AccessType::Store, ebpf::MM_PROGRAM_START, 1, 0) - .unwrap(), + m.map(AccessType::Store, ebpf::MM_PROGRAM_START, 1).unwrap(), copied.borrow().as_ptr() as u64 ); } @@ -1788,19 +1736,18 @@ mod test { .unwrap(); assert_eq!( - m.map(AccessType::Load, ebpf::MM_PROGRAM_START, 1, 0) - .unwrap(), + m.map(AccessType::Load, ebpf::MM_PROGRAM_START, 1).unwrap(), original.as_ptr() as u64 ); - assert_eq!(m.load::(ebpf::MM_PROGRAM_START, 0).unwrap(), 11); - assert_eq!(m.load::(ebpf::MM_PROGRAM_START + 1, 0).unwrap(), 22); + assert_eq!(m.load::(ebpf::MM_PROGRAM_START).unwrap(), 11); + assert_eq!(m.load::(ebpf::MM_PROGRAM_START + 1).unwrap(), 22); assert!(copied.borrow().is_empty()); - m.store(33u8, ebpf::MM_PROGRAM_START, 0).unwrap(); + m.store(33u8, ebpf::MM_PROGRAM_START).unwrap(); assert_eq!(original[0], 11); - assert_eq!(m.load::(ebpf::MM_PROGRAM_START, 0).unwrap(), 33); - assert_eq!(m.load::(ebpf::MM_PROGRAM_START + 1, 0).unwrap(), 22); + assert_eq!(m.load::(ebpf::MM_PROGRAM_START).unwrap(), 33); + assert_eq!(m.load::(ebpf::MM_PROGRAM_START + 1).unwrap(), 22); } } @@ -1833,9 +1780,9 @@ mod test { ) .unwrap(); - m.store(55u8, ebpf::MM_PROGRAM_START, 0).unwrap(); + m.store(55u8, ebpf::MM_PROGRAM_START).unwrap(); assert_eq!(original1[0], 11); - assert_eq!(m.load::(ebpf::MM_PROGRAM_START, 0).unwrap(), 55); + assert_eq!(m.load::(ebpf::MM_PROGRAM_START).unwrap(), 55); } } @@ -1853,8 +1800,7 @@ mod test { ) .unwrap(); - m.map(AccessType::Store, ebpf::MM_PROGRAM_START, 1, 0) - .unwrap(); + m.map(AccessType::Store, ebpf::MM_PROGRAM_START, 1).unwrap(); } #[test] @@ -1871,6 +1817,6 @@ mod test { ) .unwrap(); - m.store(33u8, ebpf::MM_PROGRAM_START, 0).unwrap(); + m.store(33u8, ebpf::MM_PROGRAM_START).unwrap(); } } diff --git a/src/syscalls.rs b/src/syscalls.rs index 53aa35a00..df8c805ac 100644 --- a/src/syscalls.rs +++ b/src/syscalls.rs @@ -176,10 +176,7 @@ pub fn bpf_mem_frob( memory_mapping: &mut MemoryMapping, result: &mut ProgramResult, ) { - let host_addr = question_mark!( - memory_mapping.map(AccessType::Store, vm_addr, len, 0), - result - ); + let host_addr = question_mark!(memory_mapping.map(AccessType::Store, vm_addr, len), result); for i in 0..len { unsafe { let p = (host_addr + i) as *mut u8; @@ -226,8 +223,8 @@ pub fn bpf_str_cmp( *result = ProgramResult::Ok(u64::MAX); return; } - let mut a = question_mark!(memory_mapping.map(AccessType::Load, arg1, 1, 0), result); - let mut b = question_mark!(memory_mapping.map(AccessType::Load, arg2, 1, 0), result); + let mut a = question_mark!(memory_mapping.map(AccessType::Load, arg1, 1), result); + let mut b = question_mark!(memory_mapping.map(AccessType::Load, arg2, 1), result); unsafe { let mut a_val = *(a as *const u8); let mut b_val = *(b as *const u8); @@ -258,10 +255,7 @@ pub fn bpf_syscall_string( memory_mapping: &mut MemoryMapping, result: &mut ProgramResult, ) { - let host_addr = question_mark!( - memory_mapping.map(AccessType::Load, vm_addr, len, 0), - result - ); + let host_addr = question_mark!(memory_mapping.map(AccessType::Load, vm_addr, len), result); let c_buf: *const i8 = host_addr as *const i8; unsafe { for i in 0..len { diff --git a/tests/execution.rs b/tests/execution.rs index 06ddae37b..33c4ba876 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -892,7 +892,6 @@ fn test_err_ldxdw_oob() { (), TestContextObject::new(1), ProgramResult::Err(EbpfError::AccessViolation( - 29, AccessType::Load, 0x400000006, 8, @@ -911,7 +910,6 @@ fn test_err_ldxdw_nomem() { (), TestContextObject::new(1), ProgramResult::Err(EbpfError::AccessViolation( - 29, AccessType::Load, 0x400000006, 8, @@ -1959,7 +1957,6 @@ fn test_err_dynamic_stack_out_of_bound() { (), TestContextObject::new(1), ProgramResult::Err(EbpfError::AccessViolation( - 29, AccessType::Store, ebpf::MM_STACK_START - 1, 1, @@ -1977,7 +1974,6 @@ fn test_err_dynamic_stack_out_of_bound() { (), TestContextObject::new(1), ProgramResult::Err(EbpfError::AccessViolation( - 29, AccessType::Store, ebpf::MM_STACK_START + config.stack_size() as u64, 1, @@ -2011,7 +2007,6 @@ fn test_err_dynamic_stack_ptr_overflow() { (), TestContextObject::new(7), ProgramResult::Err(EbpfError::AccessViolation( - 36, AccessType::Store, u64::MAX, 1, @@ -2188,7 +2183,6 @@ fn test_err_mem_access_out_of_bound() { mem, TestContextObject::new(3), ProgramResult::Err(EbpfError::AccessViolation( - 31, AccessType::Store, address, 1, @@ -2418,7 +2412,7 @@ fn test_err_syscall_string() { "bpf_syscall_string" => syscalls::bpf_syscall_string, ), TestContextObject::new(2), - ProgramResult::Err(EbpfError::AccessViolation(0, AccessType::Load, 0, 0, "unknown")), + ProgramResult::Err(EbpfError::AccessViolation(AccessType::Load, 0, 0, "unknown")), ); } @@ -3413,7 +3407,6 @@ fn test_err_fixed_stack_out_of_bound() { (), TestContextObject::new(1), ProgramResult::Err(EbpfError::AccessViolation( - 29, AccessType::Store, 0x1FFFFD000, 1,