bpf: Add bpf_d_path helper

Add a helper which writes a full path of the given `path` kernel object
to the buffer. Useful for resolving paths when using `file` or `ìnode`
objects.
pull/257/head
Mike Rostecki 2 years ago
parent 464fb54b25
commit 30f77baeb7

@ -9,6 +9,7 @@
use core::mem::{self, MaybeUninit};
use aya_bpf_bindings::bindings::path;
pub use aya_bpf_bindings::helpers as gen;
#[doc(hidden)]
pub use gen::*;
@ -837,3 +838,100 @@ pub unsafe fn bpf_printk_impl<const FMT_LEN: usize, const NUM_ARGS: usize>(
_ => gen::bpf_trace_vprintk(fmt_ptr, fmt_size, args.as_ptr() as _, (NUM_ARGS * 8) as _),
}
}
/// Returns a byte slice with a path read from the given `path` kernel object.
///
/// Reads at most `dest.len()` bytes, truncating if the length of the path is
/// larger than `dest`. On success, the destination buffer is always null
/// terminated, and the returned slice includes the bytes up to and not including
/// NULL.
///
/// # Safety
///
/// This function is inherently unsafe, since it operates on mutable raw
/// pointers.
///
/// # Examples
///
/// With an array allocated on the stack (not recommended for bigger paths,
/// eBPF stack limit is 512 bytes).
///
/// ```no_run
/// # use aya_bpf::{cty::c_long, helpers::bpf_d_path, programs::LsmContext};
/// pub const PATH_LEN: usize = 32;
///
/// #[derive(Copy, Clone)]
/// #[repr(C)]
/// pub struct Path {
/// pub path: [u8; PATH_LEN],
/// }
///
/// # fn try_lsm(ctx: LsmContext) -> Result<i32, i32> {
/// let path: *mut path = unsafe { ctx.arg(0) };
/// let mut buf = [0u8; PATH_LEN];
/// let path = unsafe { bpf_d_path(path, buf.as_mut_ptr())? };
///
/// // Do something with path
/// # Ok(0)
/// # }
/// ```
///
/// With a `PerCpuArray`:
///
/// ```no_run
/// use aya_bpf::{bindings::path, macros::map, maps::PerCpuArray};
/// # use aya_bpf::{helpers::bpf_d_path, programs::LsmContext};
///
/// pub const PATH_LEN: usize = 512;
///
/// #[repr(C)]
/// pub struct Path {
/// pub path: [u8; PATH_LEN],
/// }
///
/// #[map]
/// pub static PATH_BUF: PerCpuArray<Path> = PerCpuArray::with_max_entries(1, 0);
///
/// # fn try_lsm(ctx: LsmContext) -> Result<i32, i32> {
/// let path: *mut path = unsafe { ctx.arg(0) };
/// let buf = unsafe {
/// let ptr = PATH_BUF.get_mut(0).ok_or(0)?
/// &mut *ptr
/// };
/// let path = unsafe { bpf_d_path(path, &mut buf.path)? };
/// # Ok(0)
/// # }
/// ```
///
/// You can also convert the resulted bytes slice into `&str` using
/// [core::str::from_utf8_unchecked]:
///
/// ```no_run
/// # use aya_bpf::{cty::c_long, helpers::bpf_d_path, programs::LsmContext};
/// # use core::str::from_utf8_unchecked;
/// # pub const PATH_LEN: usize = 512;
/// # #[repr(C)]
/// # pub struct Path {
/// # pub path: [u8; PATH_LEN],
/// # }
/// # #[map]
/// # pub static PATH_BUF: PerCpuArray<Path> = PerCpuArray::with_max_entries(1, 0);
/// # fn try_lsm(ctx: LsmContext) -> Result<i32, i32> {
/// # let path: *mut path = unsafe { ctx.arg(0) };
/// # let mut buf = [0u8; PATH_LEN];
/// let path_str = unsafe { core::str::from_utf8_unchecked(bpf_d_path(path, &mut buf)?) };
///
/// // Do something with path_str
/// # Ok(0)
/// # }
/// ```
///
/// # Errors
///
/// On failure, this function returns Err(-1).
#[inline(always)]
pub unsafe fn bpf_d_path(path: *mut path, dest: &mut [u8]) -> Result<&[u8], c_long> {
let len = gen::bpf_d_path(path, dest.as_mut_ptr() as *mut c_char, dest.len() as u32);
read_str_bytes(len, dest)
}

Loading…
Cancel
Save