aya-rs/book

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