123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838 |
- //! This module contains kernel helper functions that may be exposed to specific BPF
- //! program types. These helpers can be used to perform common tasks, query and operate on
- //! data exposed by the kernel, and perform some operations that would normally be denied
- //! by the BPF verifier.
- //!
- //! Here, we provide some higher-level wrappers around the underlying kernel helpers, but
- //! also expose bindings to the underlying helpers as a fall-back in case of a missing
- //! implementation.
- use core::mem::{self, MaybeUninit};
- pub use aya_bpf_bindings::helpers as gen;
- #[doc(hidden)]
- pub use gen::*;
- use crate::{
- check_bounds_signed,
- cty::{c_char, c_long, c_void},
- };
- /// Read bytes stored at `src` and store them as a `T`.
- ///
- /// Generally speaking, the more specific [`bpf_probe_read_user`] and
- /// [`bpf_probe_read_kernel`] should be preferred over this function.
- ///
- /// Returns a bitwise copy of `mem::size_of::<T>()` bytes stored at the user space address
- /// `src`. See `bpf_probe_read_kernel` for reading kernel space memory.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const c_int = 0 as _;
- /// let my_int: c_int = unsafe { bpf_probe_read(kernel_ptr)? };
- ///
- /// // Do something with my_int
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub unsafe fn bpf_probe_read<T>(src: *const T) -> Result<T, c_long> {
- let mut v: MaybeUninit<T> = MaybeUninit::uninit();
- let ret = gen::bpf_probe_read(
- v.as_mut_ptr() as *mut c_void,
- mem::size_of::<T>() as u32,
- src as *const c_void,
- );
- if ret == 0 {
- Ok(v.assume_init())
- } else {
- Err(ret)
- }
- }
- /// Read bytes from the pointer `src` into the provided destination buffer.
- ///
- /// Generally speaking, the more specific [`bpf_probe_read_user_buf`] and
- /// [`bpf_probe_read_kernel_buf`] should be preferred over this function.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_buf};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let ptr: *const u8 = 0 as _;
- /// let mut buf = [0u8; 16];
- /// unsafe { bpf_probe_read_buf(ptr, &mut buf)? };
- ///
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub unsafe fn bpf_probe_read_buf(src: *const u8, dst: &mut [u8]) -> Result<(), c_long> {
- let ret = gen::bpf_probe_read(
- dst.as_mut_ptr() as *mut c_void,
- dst.len() as u32,
- src as *const c_void,
- );
- if ret == 0 {
- Ok(())
- } else {
- Err(ret)
- }
- }
- /// Read bytes stored at the _user space_ pointer `src` and store them as a `T`.
- ///
- /// Returns a bitwise copy of `mem::size_of::<T>()` bytes stored at the user space address
- /// `src`. See `bpf_probe_read_kernel` for reading kernel space memory.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_user};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let user_ptr: *const c_int = 0 as _;
- /// let my_int: c_int = unsafe { bpf_probe_read_user(user_ptr)? };
- ///
- /// // Do something with my_int
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub unsafe fn bpf_probe_read_user<T>(src: *const T) -> Result<T, c_long> {
- let mut v: MaybeUninit<T> = MaybeUninit::uninit();
- let ret = gen::bpf_probe_read_user(
- v.as_mut_ptr() as *mut c_void,
- mem::size_of::<T>() as u32,
- src as *const c_void,
- );
- if ret == 0 {
- Ok(v.assume_init())
- } else {
- Err(ret)
- }
- }
- /// Read bytes from the _user space_ pointer `src` into the provided destination
- /// buffer.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_user_buf};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let user_ptr: *const u8 = 0 as _;
- /// let mut buf = [0u8; 16];
- /// unsafe { bpf_probe_read_user_buf(user_ptr, &mut buf)? };
- ///
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub unsafe fn bpf_probe_read_user_buf(src: *const u8, dst: &mut [u8]) -> Result<(), c_long> {
- let ret = gen::bpf_probe_read_user(
- dst.as_mut_ptr() as *mut c_void,
- dst.len() as u32,
- src as *const c_void,
- );
- if ret == 0 {
- Ok(())
- } else {
- Err(ret)
- }
- }
- /// Read bytes stored at the _kernel space_ pointer `src` and store them as a `T`.
- ///
- /// Returns a bitwise copy of `mem::size_of::<T>()` bytes stored at the kernel space address
- /// `src`. See `bpf_probe_read_user` for reading user space memory.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_kernel};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const c_int = 0 as _;
- /// let my_int: c_int = unsafe { bpf_probe_read_kernel(kernel_ptr)? };
- ///
- /// // Do something with my_int
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub unsafe fn bpf_probe_read_kernel<T>(src: *const T) -> Result<T, c_long> {
- let mut v: MaybeUninit<T> = MaybeUninit::uninit();
- let ret = gen::bpf_probe_read_kernel(
- v.as_mut_ptr() as *mut c_void,
- mem::size_of::<T>() as u32,
- src as *const c_void,
- );
- if ret == 0 {
- Ok(v.assume_init())
- } else {
- Err(ret)
- }
- }
- /// Read bytes from the _kernel space_ pointer `src` into the provided destination
- /// buffer.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::{c_int, c_long}, helpers::bpf_probe_read_kernel_buf};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const u8 = 0 as _;
- /// let mut buf = [0u8; 16];
- /// unsafe { bpf_probe_read_kernel_buf(kernel_ptr, &mut buf)? };
- ///
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub unsafe fn bpf_probe_read_kernel_buf(src: *const u8, dst: &mut [u8]) -> Result<(), c_long> {
- let ret = gen::bpf_probe_read_kernel(
- dst.as_mut_ptr() as *mut c_void,
- dst.len() as u32,
- src as *const c_void,
- );
- if ret == 0 {
- Ok(())
- } else {
- Err(ret)
- }
- }
- /// Read a null-terminated string stored at `src` into `dest`.
- ///
- /// Generally speaking, the more specific [`bpf_probe_read_user_str`] and
- /// [`bpf_probe_read_kernel_str`] should be preferred over this function.
- ///
- /// In case the length of `dest` is smaller then the length of `src`, the read bytes will
- /// be truncated to the size of `dest`.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_str};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const u8 = 0 as _;
- /// let mut my_str = [0u8; 16];
- /// let num_read = unsafe { bpf_probe_read_str(kernel_ptr, &mut my_str)? };
- ///
- /// // Do something with num_read and my_str
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns Err(-1).
- #[deprecated(
- note = "Use `bpf_probe_read_user_str_bytes` or `bpf_probe_read_kernel_str_bytes` instead"
- )]
- #[inline]
- pub unsafe fn bpf_probe_read_str(src: *const u8, dest: &mut [u8]) -> Result<usize, c_long> {
- let len = gen::bpf_probe_read_str(
- dest.as_mut_ptr() as *mut c_void,
- dest.len() as u32,
- src as *const c_void,
- );
- let len = usize::try_from(len).map_err(|core::num::TryFromIntError { .. }| -1)?;
- // this can never happen, it's needed to tell the verifier that len is bounded.
- Ok(len.min(dest.len()))
- }
- /// Read a null-terminated string from _user space_ stored at `src` into `dest`.
- ///
- /// In case the length of `dest` is smaller then the length of `src`, the read bytes will
- /// be truncated to the size of `dest`.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_user_str};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let user_ptr: *const u8 = 0 as _;
- /// let mut my_str = [0u8; 16];
- /// let num_read = unsafe { bpf_probe_read_user_str(user_ptr, &mut my_str)? };
- ///
- /// // Do something with num_read and my_str
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns Err(-1).
- #[deprecated(note = "Use `bpf_probe_read_user_str_bytes` instead")]
- #[inline]
- pub unsafe fn bpf_probe_read_user_str(src: *const u8, dest: &mut [u8]) -> Result<usize, c_long> {
- let len = gen::bpf_probe_read_user_str(
- dest.as_mut_ptr() as *mut c_void,
- dest.len() as u32,
- src as *const c_void,
- );
- let len = usize::try_from(len).map_err(|core::num::TryFromIntError { .. }| -1)?;
- // this can never happen, it's needed to tell the verifier that len is bounded.
- Ok(len.min(dest.len()))
- }
- /// Returns a byte slice read from _user space_ address `src`.
- ///
- /// Reads at most `dest.len()` bytes from the `src` address, truncating if the
- /// length of the source string 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.
- ///
- /// # Examples
- ///
- /// With an array allocated on the stack (not recommended for bigger strings,
- /// eBPF stack limit is 512 bytes):
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_user_str_bytes};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let user_ptr: *const u8 = 0 as _;
- /// let mut buf = [0u8; 16];
- /// let my_str_bytes = unsafe { bpf_probe_read_user_str_bytes(user_ptr, &mut buf)? };
- ///
- /// // Do something with my_str_bytes
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// With a `PerCpuArray` (with size defined by us):
- ///
- /// ```no_run
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_user_str_bytes};
- /// use aya_bpf::{macros::map, maps::PerCpuArray};
- ///
- /// #[repr(C)]
- /// pub struct Buf {
- /// pub buf: [u8; 4096],
- /// }
- ///
- /// #[map]
- /// pub static mut BUF: PerCpuArray<Buf> = PerCpuArray::with_max_entries(1, 0);
- ///
- /// # fn try_test() -> Result<(), c_long> {
- /// # let user_ptr: *const u8 = 0 as _;
- /// let buf = unsafe {
- /// let ptr = BUF.get_ptr_mut(0).ok_or(0)?;
- /// &mut *ptr
- /// };
- /// let my_str_bytes = unsafe { bpf_probe_read_user_str_bytes(user_ptr, &mut buf.buf)? };
- ///
- /// // Do something with my_str_bytes
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// You can also convert the resulted bytes slice into `&str` using
- /// [core::str::from_utf8_unchecked]:
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_user_str_bytes};
- /// # use aya_bpf::{macros::map, maps::PerCpuArray};
- /// # #[repr(C)]
- /// # pub struct Buf {
- /// # pub buf: [u8; 4096],
- /// # }
- /// # #[map]
- /// # pub static mut BUF: PerCpuArray<Buf> = PerCpuArray::with_max_entries(1, 0);
- /// # fn try_test() -> Result<(), c_long> {
- /// # let user_ptr: *const u8 = 0 as _;
- /// # let buf = unsafe {
- /// # let ptr = BUF.get_ptr_mut(0).ok_or(0)?;
- /// # &mut *ptr
- /// # };
- /// let my_str = unsafe {
- /// core::str::from_utf8_unchecked(bpf_probe_read_user_str_bytes(user_ptr, &mut buf.buf)?)
- /// };
- ///
- /// // Do something with my_str
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns Err(-1).
- #[inline]
- pub unsafe fn bpf_probe_read_user_str_bytes(
- src: *const u8,
- dest: &mut [u8],
- ) -> Result<&[u8], c_long> {
- let len = gen::bpf_probe_read_user_str(
- dest.as_mut_ptr() as *mut c_void,
- dest.len() as u32,
- src as *const c_void,
- );
- read_str_bytes(len, dest)
- }
- fn read_str_bytes(len: i64, dest: &[u8]) -> Result<&[u8], c_long> {
- // The lower bound is 0, since it's what is returned for b"\0". See the
- // bpf_probe_read_user_[user|kernel]_bytes_empty integration tests. The upper bound
- // check is not needed since the helper truncates, but the verifier doesn't
- // know that so we show it the upper bound.
- if !check_bounds_signed(len, 0, dest.len() as i64) {
- return Err(-1);
- }
- // len includes the NULL terminator but not for b"\0" for which the kernel
- // returns len=0. So we do a saturating sub and for b"\0" we return the
- // empty slice, for all other cases we omit the terminator.
- let len = usize::try_from(len).map_err(|core::num::TryFromIntError { .. }| -1)?;
- let len = len.saturating_sub(1);
- dest.get(..len).ok_or(-1)
- }
- /// Read a null-terminated string from _kernel space_ stored at `src` into `dest`.
- ///
- /// In case the length of `dest` is smaller then the length of `src`, the read bytes will
- /// be truncated to the size of `dest`.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_kernel_str};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const u8 = 0 as _;
- /// let mut my_str = [0u8; 16];
- /// let num_read = unsafe { bpf_probe_read_kernel_str(kernel_ptr, &mut my_str)? };
- ///
- /// // Do something with num_read and my_str
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns Err(-1).
- #[deprecated(note = "Use bpf_probe_read_kernel_str_bytes instead")]
- #[inline]
- pub unsafe fn bpf_probe_read_kernel_str(src: *const u8, dest: &mut [u8]) -> Result<usize, c_long> {
- let len = gen::bpf_probe_read_kernel_str(
- dest.as_mut_ptr() as *mut c_void,
- dest.len() as u32,
- src as *const c_void,
- );
- let len = usize::try_from(len).map_err(|core::num::TryFromIntError { .. }| -1)?;
- // this can never happen, it's needed to tell the verifier that len is bounded.
- Ok(len.min(dest.len()))
- }
- /// Returns a byte slice read from _kernel space_ address `src`.
- ///
- /// Reads at most `dest.len()` bytes from the `src` address, truncating if the
- /// length of the source string 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.
- ///
- /// # Examples
- ///
- /// With an array allocated on the stack (not recommended for bigger strings,
- /// eBPF stack limit is 512 bytes):
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_kernel_str_bytes};
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const u8 = 0 as _;
- /// let mut buf = [0u8; 16];
- /// let my_str_bytes = unsafe { bpf_probe_read_kernel_str_bytes(kernel_ptr, &mut buf)? };
- ///
- /// // Do something with my_str_bytes
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// With a `PerCpuArray` (with size defined by us):
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_kernel_str_bytes};
- /// use aya_bpf::{macros::map, maps::PerCpuArray};
- ///
- /// #[repr(C)]
- /// pub struct Buf {
- /// pub buf: [u8; 4096],
- /// }
- ///
- /// #[map]
- /// pub static mut BUF: PerCpuArray<Buf> = PerCpuArray::with_max_entries(1, 0);
- ///
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const u8 = 0 as _;
- /// let buf = unsafe {
- /// let ptr = BUF.get_ptr_mut(0).ok_or(0)?;
- /// &mut *ptr
- /// };
- /// let my_str_bytes = unsafe { bpf_probe_read_kernel_str_bytes(kernel_ptr, &mut buf.buf)? };
- ///
- /// // Do something with my_str_bytes
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// You can also convert the resulted bytes slice into `&str` using
- /// [core::str::from_utf8_unchecked]:
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{cty::c_long, helpers::bpf_probe_read_kernel_str_bytes};
- /// # use aya_bpf::{macros::map, maps::PerCpuArray};
- /// # #[repr(C)]
- /// # pub struct Buf {
- /// # pub buf: [u8; 4096],
- /// # }
- /// # #[map]
- /// # pub static mut BUF: PerCpuArray<Buf> = PerCpuArray::with_max_entries(1, 0);
- /// # fn try_test() -> Result<(), c_long> {
- /// # let kernel_ptr: *const u8 = 0 as _;
- /// # let buf = unsafe {
- /// # let ptr = BUF.get_ptr_mut(0).ok_or(0)?;
- /// # &mut *ptr
- /// # };
- /// let my_str = unsafe {
- /// core::str::from_utf8_unchecked(bpf_probe_read_kernel_str_bytes(kernel_ptr, &mut buf.buf)?)
- /// };
- ///
- /// // Do something with my_str
- /// # Ok::<(), c_long>(())
- /// # }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns Err(-1).
- #[inline]
- pub unsafe fn bpf_probe_read_kernel_str_bytes(
- src: *const u8,
- dest: &mut [u8],
- ) -> Result<&[u8], c_long> {
- let len = gen::bpf_probe_read_kernel_str(
- dest.as_mut_ptr() as *mut c_void,
- dest.len() as u32,
- src as *const c_void,
- );
- read_str_bytes(len, dest)
- }
- /// Write bytes to the _user space_ pointer `src` and store them as a `T`.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::{
- /// # cty::{c_int, c_long},
- /// # helpers::bpf_probe_write_user,
- /// # programs::ProbeContext,
- /// # };
- /// fn try_test(ctx: ProbeContext) -> Result<(), c_long> {
- /// let retp: *mut c_int = ctx.arg(0).ok_or(1)?;
- /// let val: i32 = 1;
- /// // Write the value to the userspace pointer.
- /// unsafe { bpf_probe_write_user(retp, &val as *const i32)? };
- ///
- /// Ok::<(), c_long>(())
- /// }
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub unsafe fn bpf_probe_write_user<T>(dst: *mut T, src: *const T) -> Result<(), c_long> {
- let ret = gen::bpf_probe_write_user(
- dst as *mut c_void,
- src as *const c_void,
- mem::size_of::<T>() as u32,
- );
- if ret == 0 {
- Ok(())
- } else {
- Err(ret)
- }
- }
- /// Read the `comm` field associated with the current task struct
- /// as a `[u8; 16]`.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::helpers::bpf_get_current_comm;
- /// let comm = bpf_get_current_comm();
- ///
- /// // Do something with comm
- /// ```
- ///
- /// # Errors
- ///
- /// On failure, this function returns a negative value wrapped in an `Err`.
- #[inline]
- pub fn bpf_get_current_comm() -> Result<[u8; 16], c_long> {
- let mut comm: [u8; 16usize] = [0; 16];
- let ret = unsafe { gen::bpf_get_current_comm(&mut comm as *mut _ as *mut c_void, 16u32) };
- if ret == 0 {
- Ok(comm)
- } else {
- Err(ret)
- }
- }
- /// Read the process id and thread group id associated with the current task struct as
- /// a `u64`.
- ///
- /// In the return value, the upper 32 bits are the `tgid`, and the lower 32 bits are the
- /// `pid`. That is, the returned value is equal to: `(tgid << 32) | pid`. A caller may
- /// access the individual fields by either casting to a `u32` or performing a `>> 32` bit
- /// shift and casting to a `u32`.
- ///
- /// Note that the naming conventions used in the kernel differ from user space. From the
- /// perspective of user space, `pid` may be thought of as the thread id, and `tgid` may be
- /// thought of as the process id. For single-threaded processes, these values are
- /// typically the same.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::helpers::bpf_get_current_pid_tgid;
- /// let tgid = (bpf_get_current_pid_tgid() >> 32) as u32;
- /// let pid = bpf_get_current_pid_tgid() as u32;
- ///
- /// // Do something with pid and tgid
- /// ```
- #[inline]
- pub fn bpf_get_current_pid_tgid() -> u64 {
- unsafe { gen::bpf_get_current_pid_tgid() }
- }
- /// Read the user id and group id associated with the current task struct as
- /// a `u64`.
- ///
- /// In the return value, the upper 32 bits are the `gid`, and the lower 32 bits are the
- /// `uid`. That is, the returned value is equal to: `(gid << 32) | uid`. A caller may
- /// access the individual fields by either casting to a `u32` or performing a `>> 32` bit
- /// shift and casting to a `u32`.
- ///
- /// # Examples
- ///
- /// ```no_run
- /// # #![allow(dead_code)]
- /// # use aya_bpf::helpers::bpf_get_current_uid_gid;
- /// let gid = (bpf_get_current_uid_gid() >> 32) as u32;
- /// let uid = bpf_get_current_uid_gid() as u32;
- ///
- /// // Do something with uid and gid
- /// ```
- #[inline]
- pub fn bpf_get_current_uid_gid() -> u64 {
- unsafe { gen::bpf_get_current_uid_gid() }
- }
- /// Prints a debug message to the BPF debugging pipe.
- ///
- /// The [format string syntax][fmt] is the same as that of the `printk` kernel
- /// function. It is passed in as a fixed-size byte array (`&[u8; N]`), so you
- /// will have to prefix your string literal with a `b`. A terminating zero byte
- /// is appended automatically.
- ///
- /// The macro can read from arbitrary pointers, so it must be used in an `unsafe`
- /// scope in order to compile.
- ///
- /// Invocations with less than 4 arguments call the `bpf_trace_printk` helper,
- /// otherwise the `bpf_trace_vprintk` function is called. The latter function
- /// requires a kernel version >= 5.16 whereas the former has been around since
- /// the dawn of eBPF. The return value of the BPF helper is also returned from
- /// this macro.
- ///
- /// Messages can be read by executing the following command in a second terminal:
- ///
- /// ```bash
- /// sudo cat /sys/kernel/debug/tracing/trace_pipe
- /// ```
- ///
- /// If no messages are printed when calling [`bpf_printk!`] after executing the
- /// above command, it is possible that tracing must first be enabled by running:
- ///
- /// ```bash
- /// echo 1 | sudo tee /sys/kernel/debug/tracing/tracing_on
- /// ```
- ///
- /// # Example
- ///
- /// ```no_run
- /// # use aya_bpf::helpers::bpf_printk;
- /// unsafe {
- /// bpf_printk!(b"hi there! dec: %d, hex: 0x%08X", 42, 0x1234);
- /// }
- /// ```
- ///
- /// [fmt]: https://www.kernel.org/doc/html/latest/core-api/printk-formats.html#printk-specifiers
- #[macro_export]
- macro_rules! bpf_printk {
- ($fmt:literal $(,)? $($arg:expr),* $(,)?) => {{
- use $crate::helpers::PrintkArg;
- const FMT: [u8; { $fmt.len() + 1 }] = $crate::helpers::zero_pad_array::<
- { $fmt.len() }, { $fmt.len() + 1 }>(*$fmt);
- let data = [$(PrintkArg::from($arg)),*];
- $crate::helpers::bpf_printk_impl(&FMT, &data)
- }};
- }
- // Macros are always exported from the crate root. Also export it from `helpers`.
- #[doc(inline)]
- pub use bpf_printk;
- /// Argument ready to be passed to `printk` BPF helper.
- #[repr(transparent)]
- #[derive(Copy, Clone)]
- pub struct PrintkArg(u64);
- impl PrintkArg {
- /// Manually construct a `printk` BPF helper argument.
- #[inline]
- pub fn from_raw(x: u64) -> Self {
- Self(x)
- }
- }
- macro_rules! impl_integer_promotion {
- ($($ty:ty : via $via:ty),* $(,)?) => {$(
- /// Create `printk` arguments from integer types.
- impl From<$ty> for PrintkArg {
- #[inline]
- fn from(x: $ty) -> PrintkArg {
- PrintkArg(x as $via as u64)
- }
- }
- )*}
- }
- impl_integer_promotion!(
- char: via u64,
- u8: via u64,
- u16: via u64,
- u32: via u64,
- u64: via u64,
- usize: via u64,
- i8: via i64,
- i16: via i64,
- i32: via i64,
- i64: via i64,
- isize: via i64,
- );
- /// Construct `printk` BPF helper arguments from constant pointers.
- impl<T> From<*const T> for PrintkArg {
- #[inline]
- fn from(x: *const T) -> Self {
- PrintkArg(x as usize as u64)
- }
- }
- /// Construct `printk` BPF helper arguments from mutable pointers.
- impl<T> From<*mut T> for PrintkArg {
- #[inline]
- fn from(x: *mut T) -> Self {
- PrintkArg(x as usize as u64)
- }
- }
- /// Expands the given byte array to `DST_LEN`, right-padding it with zeros. If
- /// `DST_LEN` is smaller than `SRC_LEN`, the array is instead truncated.
- ///
- /// This function serves as a helper for the [`bpf_printk!`] macro.
- #[doc(hidden)]
- pub const fn zero_pad_array<const SRC_LEN: usize, const DST_LEN: usize>(
- src: [u8; SRC_LEN],
- ) -> [u8; DST_LEN] {
- let mut out: [u8; DST_LEN] = [0u8; DST_LEN];
- // The `min` function is not `const`. Hand-roll it.
- let mut i = if DST_LEN > SRC_LEN { SRC_LEN } else { DST_LEN };
- while i > 0 {
- i -= 1;
- out[i] = src[i];
- }
- out
- }
- /// Internal helper function for the [`bpf_printk!`] macro.
- ///
- /// The BPF helpers require the length for both the format string as well as
- /// the argument array to be of constant size to pass the verifier. Const
- /// generics are used to represent this requirement in Rust.
- #[inline]
- #[doc(hidden)]
- pub unsafe fn bpf_printk_impl<const FMT_LEN: usize, const NUM_ARGS: usize>(
- fmt: &[u8; FMT_LEN],
- args: &[PrintkArg; NUM_ARGS],
- ) -> i64 {
- // This function can't be wrapped in `helpers.rs` because it has variadic
- // arguments. We also can't turn the definitions in `helpers.rs` into
- // `const`s because MIRI believes casting arbitrary integers to function
- // pointers to be an error.
- let printk: unsafe extern "C" fn(fmt: *const c_char, fmt_size: u32, ...) -> c_long =
- mem::transmute(6usize);
- let fmt_ptr = fmt.as_ptr() as *const c_char;
- let fmt_size = fmt.len() as u32;
- match NUM_ARGS {
- 0 => printk(fmt_ptr, fmt_size),
- 1 => printk(fmt_ptr, fmt_size, args[0]),
- 2 => printk(fmt_ptr, fmt_size, args[0], args[1]),
- 3 => printk(fmt_ptr, fmt_size, args[0], args[1], args[2]),
- _ => gen::bpf_trace_vprintk(fmt_ptr, fmt_size, args.as_ptr() as _, (NUM_ARGS * 8) as _),
- }
- }
|