Ver código fonte

Merge pull request #142 from vadorovsky/args-mut-ptr

aya-bpf: Add bpf_probe_write_user helper
Alessandro Decina 3 anos atrás
pai
commit
923cd9b767
3 arquivos alterados com 89 adições e 1 exclusões
  1. 1 1
      bpf/aya-bpf-macros/src/lib.rs
  2. 49 0
      bpf/aya-bpf/src/args.rs
  3. 39 0
      bpf/aya-bpf/src/helpers.rs

+ 1 - 1
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`.

+ 49 - 0
bpf/aya-bpf/src/args.rs

@@ -120,6 +120,55 @@ impl<T> FromPtRegs for *const T {
     }
 }
 
+#[cfg(bpf_target_arch = "x86_64")]
+impl<T> FromPtRegs for *mut T {
+    fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
+        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<Self> {
+        ctx.rax().map(|v| v as _)
+    }
+}
+
+#[cfg(bpf_target_arch = "armv7")]
+impl<T> FromPtRegs for *mut T {
+    fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
+        if n <= 6 {
+            ctx.uregs().map(|regs| regs[n] as _)
+        } else {
+            None
+        }
+    }
+
+    fn from_retval(ctx: &pt_regs) -> Option<Self> {
+        ctx.uregs().map(|regs| regs[0] as _)
+    }
+}
+
+#[cfg(bpf_target_arch = "aarch64")]
+impl<T> FromPtRegs for *mut T {
+    fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
+        if n <= 7 {
+            ctx.regs().map(|regs| regs[n] as _)
+        } else {
+            None
+        }
+    }
+
+    fn from_retval(ctx: &pt_regs) -> Option<Self> {
+        ctx.regs().map(|regs| regs[0] as _)
+    }
+}
+
 /// Helper macro to implement [`FromPtRegs`] for a primitive type.
 macro_rules! impl_from_pt_regs {
     ($type:ident) => {

+ 39 - 0
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<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 {
+        return Err(ret);
+    }
+
+    Ok(())
+}
+
 /// Read the `comm` field associated with the current task struct
 /// as a `[c_char; 16]`.
 ///