mirror of https://github.com/aya-rs/aya
bpf: Handle raw tracepoint arguments
Provide an `arg()` method in `RawTracepointArgs` wrapper of `bpf_raw_tracepoint_args` and also in `RawTracepointContext`, so it's directly available in raw tracepoint programs. The methods and traits implemented here are unsafe. There is no way to reliably check the number of available arguments, so requesting a non-existing one leads to undefined behavior.reviewable/pr543/r4
parent
28a28c9872
commit
f34d355d7d
@ -1,19 +1,25 @@
|
||||
use core::ffi::c_void;
|
||||
|
||||
use crate::EbpfContext;
|
||||
use crate::{args::FromRawTracepointArgs, bindings::bpf_raw_tracepoint_args, EbpfContext};
|
||||
|
||||
pub struct RawTracePointContext {
|
||||
ctx: *mut c_void,
|
||||
ctx: *mut bpf_raw_tracepoint_args,
|
||||
}
|
||||
|
||||
impl RawTracePointContext {
|
||||
pub fn new(ctx: *mut c_void) -> RawTracePointContext {
|
||||
RawTracePointContext { ctx }
|
||||
RawTracePointContext {
|
||||
ctx: ctx as *mut bpf_raw_tracepoint_args,
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn arg<T: FromRawTracepointArgs>(&self, n: usize) -> T {
|
||||
T::from_argument(&*self.ctx, n)
|
||||
}
|
||||
}
|
||||
|
||||
impl EbpfContext for RawTracePointContext {
|
||||
fn as_ptr(&self) -> *mut c_void {
|
||||
self.ctx
|
||||
self.ctx as *mut c_void
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use aya_ebpf::{
|
||||
macros::{map, raw_tracepoint},
|
||||
maps::Array,
|
||||
programs::RawTracePointContext,
|
||||
};
|
||||
use integration_common::raw_tracepoint::SysEnterEvent;
|
||||
|
||||
#[map]
|
||||
static RESULT: Array<SysEnterEvent> = Array::with_max_entries(1, 0);
|
||||
|
||||
#[raw_tracepoint(tracepoint = "sys_enter")]
|
||||
pub fn sys_enter(ctx: RawTracePointContext) -> i32 {
|
||||
let common_type: u16 = unsafe { ctx.arg(0) };
|
||||
let common_flags: u8 = unsafe { ctx.arg(1) };
|
||||
|
||||
if let Some(ptr) = RESULT.get_ptr_mut(0) {
|
||||
unsafe {
|
||||
(*ptr).common_type = common_type;
|
||||
(*ptr).common_flags = common_flags;
|
||||
}
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
use aya::{maps::Array, programs::RawTracePoint, Ebpf};
|
||||
use integration_common::raw_tracepoint::SysEnterEvent;
|
||||
|
||||
fn get_event(bpf: &mut Ebpf) -> SysEnterEvent {
|
||||
let map: Array<_, SysEnterEvent> = Array::try_from(bpf.map_mut("RESULT").unwrap()).unwrap();
|
||||
map.get(&0, 0).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn raw_tracepoint() {
|
||||
let mut bpf = Ebpf::load(crate::RAW_TRACEPOINT).unwrap();
|
||||
|
||||
// Check start condition.
|
||||
{
|
||||
let SysEnterEvent {
|
||||
common_type,
|
||||
common_flags,
|
||||
..
|
||||
} = get_event(&mut bpf);
|
||||
assert_eq!(common_type, 0);
|
||||
assert_eq!(common_flags, 0);
|
||||
}
|
||||
|
||||
// NB: we cannot fetch `map` just once above because both `Ebpf::map_mut` and
|
||||
// `Ebpf::program_mut` take &mut self, resulting in overlapping mutable borrows.
|
||||
let prog: &mut RawTracePoint = bpf.program_mut("sys_enter").unwrap().try_into().unwrap();
|
||||
prog.load().unwrap();
|
||||
prog.attach("sys_enter").unwrap();
|
||||
|
||||
// Check that a syscall was traced.
|
||||
{
|
||||
let SysEnterEvent {
|
||||
common_type,
|
||||
common_flags,
|
||||
..
|
||||
} = get_event(&mut bpf);
|
||||
assert_ne!(common_type, 0);
|
||||
assert_ne!(common_flags, 0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue