Skip to content

Commit

Permalink
src/interpreter.rs: Use wrapping_offset() for load/store operations
Browse files Browse the repository at this point in the history
Rust 1.83 introduces some additional out-of-bound checks [0], making it
illegal to attempt to load at an out-of-bound access when trying to
load/store values from/to register in rbpf's interpreter, and causing
the program to panick even before we reach the safety checks from
check_mem().

I understand we need to use wrapping_offset() rather than offset() in
that case, which causes the operation itself (but not the resulting
poitner) to be safe, and the checked to be deferred. See also the
related GitHub issue [1].

[0] rust-lang/rust#130251
[1] #115

Reported-by: Ben Kimock <[email protected]>
Signed-off-by: Quentin Monnet <[email protected]>
  • Loading branch information
qmonnet committed Oct 29, 2024
1 parent 93e7dcd commit cfb363c
Showing 1 changed file with 12 additions and 12 deletions.
24 changes: 12 additions & 12 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,75 +139,75 @@ pub fn execute_program(
// BPF_LDX class
ebpf::LD_B_REG => reg[_dst] = unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u8;
let x = (reg[_src] as *const u8).wrapping_offset(insn.off as isize) as *const u8;
check_mem_load(x as u64, 1, insn_ptr)?;
x.read_unaligned() as u64
},
ebpf::LD_H_REG => reg[_dst] = unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u16;
let x = (reg[_src] as *const u8).wrapping_offset(insn.off as isize) as *const u16;
check_mem_load(x as u64, 2, insn_ptr)?;
x.read_unaligned() as u64
},
ebpf::LD_W_REG => reg[_dst] = unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u32;
let x = (reg[_src] as *const u8).wrapping_offset(insn.off as isize) as *const u32;
check_mem_load(x as u64, 4, insn_ptr)?;
x.read_unaligned() as u64
},
ebpf::LD_DW_REG => reg[_dst] = unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u64;
let x = (reg[_src] as *const u8).wrapping_offset(insn.off as isize) as *const u64;
check_mem_load(x as u64, 8, insn_ptr)?;
x.read_unaligned()
},

// BPF_ST class
ebpf::ST_B_IMM => unsafe {
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u8;
check_mem_store(x as u64, 1, insn_ptr)?;
x.write_unaligned(insn.imm as u8);
},
ebpf::ST_H_IMM => unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u16;
check_mem_store(x as u64, 2, insn_ptr)?;
x.write_unaligned(insn.imm as u16);
},
ebpf::ST_W_IMM => unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u32;
check_mem_store(x as u64, 4, insn_ptr)?;
x.write_unaligned(insn.imm as u32);
},
ebpf::ST_DW_IMM => unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u64;
check_mem_store(x as u64, 8, insn_ptr)?;
x.write_unaligned(insn.imm as u64);
},

// BPF_STX class
ebpf::ST_B_REG => unsafe {
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u8;
check_mem_store(x as u64, 1, insn_ptr)?;
x.write_unaligned(reg[_src] as u8);
},
ebpf::ST_H_REG => unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u16;
check_mem_store(x as u64, 2, insn_ptr)?;
x.write_unaligned(reg[_src] as u16);
},
ebpf::ST_W_REG => unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u32;
check_mem_store(x as u64, 4, insn_ptr)?;
x.write_unaligned(reg[_src] as u32);
},
ebpf::ST_DW_REG => unsafe {
#[allow(clippy::cast_ptr_alignment)]
let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
let x = (reg[_dst] as *const u8).wrapping_offset(insn.off as isize) as *mut u64;
check_mem_store(x as u64, 8, insn_ptr)?;
x.write_unaligned(reg[_src]);
},
Expand Down

0 comments on commit cfb363c

Please sign in to comment.