Skip to content

Commit

Permalink
Also removes the pc field from EbpfError::AccessViolation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lichtso committed Sep 28, 2023
1 parent 0b19ae2 commit 09e3c6e
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 207 deletions.
12 changes: 4 additions & 8 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
35 changes: 17 additions & 18 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -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);
};
}

Expand Down Expand Up @@ -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
Expand Down
36 changes: 14 additions & 22 deletions src/jit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,17 +186,16 @@ 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],
Expand All @@ -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 {
Expand Down Expand Up @@ -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::<u64>() 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::<u64>() 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);
Expand Down Expand Up @@ -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::<u64>() as i32)));

self.emit_ins(X86Instruction::return_near());
}
Expand Down
Loading

0 comments on commit 09e3c6e

Please sign in to comment.