From 5d8afc58f441da36ea44b0304733f19eb82dbbe9 Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Mon, 20 Dec 2021 17:38:31 +0100 Subject: [PATCH 1/3] aya-bpf-macros: Fix LSM macro documentation It was causing `cargo doc` inside bpf/ to fail. Signed-off-by: Michal Rostecki --- bpf/aya-bpf-macros/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bpf/aya-bpf-macros/src/lib.rs b/bpf/aya-bpf-macros/src/lib.rs index 4ae01f83..c7e2d5bf 100644 --- a/bpf/aya-bpf-macros/src/lib.rs +++ b/bpf/aya-bpf-macros/src/lib.rs @@ -168,7 +168,7 @@ pub fn raw_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream { /// Marks a function as an LSM program that can be attached to Linux LSM hooks. /// Used to implement security policy and audit logging. /// -/// LSM probes can be attached to the kernel's [security hooks][1] to implement mandatory +/// LSM probes can be attached to the kernel's security hooks to implement mandatory /// access control policy and security auditing. /// /// LSM probes require a kernel compiled with `CONFIG_BPF_LSM=y` and `CONFIG_DEBUG_INFO_BTF=y`. From 54377b6140620dadf17a2c1f9a27334d44b67ab1 Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Tue, 23 Nov 2021 19:49:01 +0100 Subject: [PATCH 2/3] aya-bpf: Allow to convert probe arguments to mutable pointers Before this change, arguments fetched with `arg` from `ProbeContext` could be only fetched as const pointers. This change allows to get mut pointers as well. Signed-off-by: Michal Rostecki --- bpf/aya-bpf/src/args.rs | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/bpf/aya-bpf/src/args.rs b/bpf/aya-bpf/src/args.rs index 310a9611..42bfad9f 100644 --- a/bpf/aya-bpf/src/args.rs +++ b/bpf/aya-bpf/src/args.rs @@ -120,6 +120,55 @@ impl FromPtRegs for *const T { } } +#[cfg(bpf_target_arch = "x86_64")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + match n { + 0 => ctx.rdi().map(|v| v as _), + 1 => ctx.rsi().map(|v| v as _), + 2 => ctx.rdx().map(|v| v as _), + 3 => ctx.rcx().map(|v| v as _), + 4 => ctx.r8().map(|v| v as _), + 5 => ctx.r9().map(|v| v as _), + _ => None, + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + ctx.rax().map(|v| v as _) + } +} + +#[cfg(bpf_target_arch = "armv7")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 6 { + ctx.uregs().map(|regs| regs[n] as _) + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + ctx.uregs().map(|regs| regs[0] as _) + } +} + +#[cfg(bpf_target_arch = "aarch64")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 7 { + ctx.regs().map(|regs| regs[n] as _) + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + ctx.regs().map(|regs| regs[0] as _) + } +} + /// Helper macro to implement [`FromPtRegs`] for a primitive type. macro_rules! impl_from_pt_regs { ($type:ident) => { From 1df3b17d291f5a38de10280a7025f963dea18ee8 Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Tue, 14 Dec 2021 12:37:39 +0100 Subject: [PATCH 3/3] aya-bpf: Add bpf_probe_write_user helper This helper allows to write to mutable pointers in the userspace, which come from userspace functions that uprobes attach to. Signed-off-by: Michal Rostecki --- bpf/aya-bpf/src/helpers.rs | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/bpf/aya-bpf/src/helpers.rs b/bpf/aya-bpf/src/helpers.rs index 1b7ea5b4..868c5c2d 100644 --- a/bpf/aya-bpf/src/helpers.rs +++ b/bpf/aya-bpf/src/helpers.rs @@ -364,6 +364,45 @@ pub unsafe fn bpf_probe_read_kernel_str(src: *const u8, dest: &mut [u8]) -> Resu Ok(len as usize) } +/// 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`. +#[allow(clippy::fn_to_numeric_cast_with_truncation)] +#[inline] +pub unsafe fn bpf_probe_write_user(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::() as u32, + ); + if ret < 0 { + return Err(ret); + } + + Ok(()) +} + /// Read the `comm` field associated with the current task struct /// as a `[c_char; 16]`. ///