Thomas Eizinger 1 week ago committed by GitHub
commit 9963233747
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,4 +1,4 @@
use core::{cell::UnsafeCell, marker::PhantomData, mem, ptr::NonNull}; use core::{cell::UnsafeCell, fmt, marker::PhantomData, mem, ptr::NonNull};
use aya_ebpf_cty::c_long; use aya_ebpf_cty::c_long;
@ -14,9 +14,30 @@ pub struct Array<T> {
_t: PhantomData<T>, _t: PhantomData<T>,
} }
#[derive(Debug)]
pub struct OutOfBounds {
length: u32,
index: u32,
}
impl core::error::Error for OutOfBounds {}
impl fmt::Display for OutOfBounds {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Array index {} is out of bounds; length = {}",
self.index, self.length
)
}
}
unsafe impl<T: Sync> Sync for Array<T> {} unsafe impl<T: Sync> Sync for Array<T> {}
impl<T> Array<T> { impl<T> Array<T> {
/// Constructs a new [`Array`] with `max_entries` entries.
///
/// All the entries are zero-initialized.
pub const fn with_max_entries(max_entries: u32, flags: u32) -> Array<T> { pub const fn with_max_entries(max_entries: u32, flags: u32) -> Array<T> {
Array { Array {
def: UnsafeCell::new(bpf_map_def { def: UnsafeCell::new(bpf_map_def {
@ -47,25 +68,36 @@ impl<T> Array<T> {
} }
} }
/// Get a reference to an array element at the given index.
///
/// Arrays are zero-initialised upon creation so this will always return a reference to `T` as long as the index is within bounds.
/// All fields of `T` may therefore be in their default state, i.e. `bool` will be `false`, `u32` will be `0`, etc.
#[inline(always)] #[inline(always)]
pub fn get(&self, index: u32) -> Option<&T> { pub fn get(&self, index: u32) -> Result<&T, OutOfBounds> {
// FIXME: alignment // FIXME: alignment
unsafe { self.lookup(index).map(|p| p.as_ref()) } unsafe { self.lookup(index).map(|p| p.as_ref()) }
} }
/// Like [`Array::get`] but returns a pointer instead.
#[inline(always)] #[inline(always)]
pub fn get_ptr(&self, index: u32) -> Option<*const T> { pub fn get_ptr(&self, index: u32) -> Result<*const T, OutOfBounds> {
unsafe { self.lookup(index).map(|p| p.as_ptr() as *const T) } unsafe { self.lookup(index).map(|p| p.as_ptr() as *const T) }
} }
/// Like [`Array::get`] but returns a mutable pointer instead.
#[inline(always)] #[inline(always)]
pub fn get_ptr_mut(&self, index: u32) -> Option<*mut T> { pub fn get_ptr_mut(&self, index: u32) -> Result<*mut T, OutOfBounds> {
unsafe { self.lookup(index).map(|p| p.as_ptr()) } unsafe { self.lookup(index).map(|p| p.as_ptr()) }
} }
#[inline(always)] #[inline(always)]
unsafe fn lookup(&self, index: u32) -> Option<NonNull<T>> { unsafe fn lookup(&self, index: u32) -> Result<NonNull<T>, OutOfBounds> {
lookup(self.def.get(), &index) let map_def = self.def.get();
lookup(map_def, &index).ok_or(OutOfBounds {
length: unsafe { (*map_def).max_entries },
index,
})
} }
/// Sets the value of the element at the given index. /// Sets the value of the element at the given index.

@ -22,7 +22,7 @@ fn read_str_bytes(
let Some(ilen) = ilen else { let Some(ilen) = ilen else {
return; return;
}; };
let Some(ptr) = RESULT.get_ptr_mut(0) else { let Ok(ptr) = RESULT.get_ptr_mut(0) else {
return; return;
}; };
let dst = unsafe { ptr.as_mut() }; let dst = unsafe { ptr.as_mut() };
@ -68,6 +68,7 @@ pub fn test_bpf_probe_read_kernel_str_bytes(ctx: ProbeContext) {
bpf_probe_read_kernel_str_bytes, bpf_probe_read_kernel_str_bytes,
KERNEL_BUFFER KERNEL_BUFFER
.get_ptr(0) .get_ptr(0)
.ok()
.and_then(|ptr| unsafe { ptr.as_ref() }) .and_then(|ptr| unsafe { ptr.as_ref() })
.map(|buf| buf.as_ptr()), .map(|buf| buf.as_ptr()),
ctx.arg::<usize>(0), ctx.arg::<usize>(0),

@ -29,7 +29,7 @@ static MAP_WITH_LOOOONG_NAAAAAAAAME: HashMap<u32, u8> = HashMap::<u32, u8>::with
#[socket_filter] #[socket_filter]
pub fn simple_prog(_ctx: SkBuffContext) -> i64 { pub fn simple_prog(_ctx: SkBuffContext) -> i64 {
// So that these maps show up under the `map_ids` field. // So that these maps show up under the `map_ids` field.
FOO.get(0); let _ = FOO.get(0);
// If we use the literal value `0` instead of the local variable `i`, then an additional // If we use the literal value `0` instead of the local variable `i`, then an additional
// `.rodata` map will be associated with the program. // `.rodata` map will be associated with the program.
let i = 0; let i = 0;

@ -18,7 +18,7 @@ pub fn sys_enter(ctx: RawTracePointContext) -> i32 {
let common_type: u16 = unsafe { ctx.arg(0) }; let common_type: u16 = unsafe { ctx.arg(0) };
let common_flags: u8 = unsafe { ctx.arg(1) }; let common_flags: u8 = unsafe { ctx.arg(1) };
if let Some(ptr) = RESULT.get_ptr_mut(0) { if let Ok(ptr) = RESULT.get_ptr_mut(0) {
unsafe { unsafe {
(*ptr).common_type = common_type; (*ptr).common_type = common_type;
(*ptr).common_flags = common_flags; (*ptr).common_flags = common_flags;

@ -72,7 +72,7 @@ pub fn redirect_dev_chain(_ctx: XdpContext) -> u32 {
#[inline(always)] #[inline(always)]
fn inc_hit(index: u32) { fn inc_hit(index: u32) {
if let Some(hit) = HITS.get_ptr_mut(index) { if let Ok(hit) = HITS.get_ptr_mut(index) {
unsafe { *hit += 1 }; unsafe { *hit += 1 };
} }
} }

@ -30,7 +30,7 @@ pub fn test_64_32_call_relocs(_ctx: ProbeContext) {
#[inline(never)] #[inline(never)]
fn set_result(index: u32, value: u64) { fn set_result(index: u32, value: u64) {
unsafe { unsafe {
if let Some(v) = RESULTS.get_ptr_mut(index) { if let Ok(v) = RESULTS.get_ptr_mut(index) {
*v = value; *v = value;
} }
} }

@ -21,7 +21,7 @@ pub fn test_bpf_strncmp(ctx: ProbeContext) -> Result<(), c_long> {
let mut b1 = [0u8; 3]; let mut b1 = [0u8; 3];
let _: &[u8] = unsafe { bpf_probe_read_user_str_bytes(s1, &mut b1) }?; let _: &[u8] = unsafe { bpf_probe_read_user_str_bytes(s1, &mut b1) }?;
let ptr = RESULT.get_ptr_mut(0).ok_or(-1)?; let ptr = RESULT.get_ptr_mut(0).map_err(|_| -1)?;
let dst = unsafe { ptr.as_mut() }; let dst = unsafe { ptr.as_mut() };
let TestResult(dst_res) = dst.ok_or(-1)?; let TestResult(dst_res) = dst.ok_or(-1)?;
*dst_res = bpf_strncmp(&b1, c"ff"); *dst_res = bpf_strncmp(&b1, c"ff");

Loading…
Cancel
Save