Document kprobes attached to syscalls
vadorovsky opened this issue · 2 comments
Handling arguments in syscall functions (like __x64_sys_execve
) works a bit different than for the most of kernel functions. All syscalls are wrapped in macros which wrap all the arguments in struct pt_regs *regs
.
For example, this definition of the execve
syscall:
SYSCALL_DEFINE3(execve,
const char __user *, filename,
const char __user *const __user *, argv,
const char __user *const __user *, envp)
{
return do_execve(getname(filename), argv, envp);
}
https://elixir.bootlin.com/linux/latest/source/fs/exec.c#L2101
gets preprocessed to a signature like int __x64_sys_execve(struct pt_regs *regs)
(not literally, but the struct pt_regs *regs
argument is imporant here!).
All the arguments like const char __user *, filename
are inside *regs
, they are not the part of the signature of __x64_sys_execve
directly.
Unwrapping those syscall arguments in Rust in Aya looks like:
fn try_execsnoop(ctx: ProbeContext) -> Result<u32, u32> {
let regs = PtRegs::new(ctx.arg(0).ok_or(1u32)?);
let task: *const task_struct = regs.arg(0).ok_or(1u32)?;
let fp: *const u8 = regs.arg(1).ok_or(1u32)?;
let argp: *const usize = regs.arg(2).ok_or(1u32)?;
// Do something with those args.
Ok(0)
}
This might be very confusing for people, so we should definitely make a separate doc section about syscalls.
Preferably after aya-rs/aya#534 is done - syscall function names depend on architecture.
This example is very likely to fail because bpf_probe_read_kernel
call is missing, making the verifier tripping up
let regs = PtRegs::new(ctx.arg(0).ok_or(1u32)?);
// bpf_probe_read_kernel call must be inserted here to read the pt_regs
let task: *const task_struct = regs.arg(0).ok_or(1u32)?;
We came to conclusion that we don't want to document it. We should encourage people to use tracepoint instead.
See: https://discord.com/channels/855676609003651072/855676609003651075/1158678307328499782