From a8716e9c269e2f6af1289dbb34d331fe3fb3b748 Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Tue, 29 Oct 2024 12:32:11 +0000 Subject: [PATCH] src/interpreter.rs: Use wrapping_offset() for load/store operations 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] https://github.com/rust-lang/rust/pull/130251 [1] https://github.com/qmonnet/rbpf/issues/115 Reported-by: Ben Kimock Signed-off-by: Quentin Monnet --- src/interpreter.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/interpreter.rs b/src/interpreter.rs index f4c2e466..a3775639 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -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]); },