So I have these macros
#define PT_REGS_PARM1(x) ((x)->di)
#define PT_REGS_PARM2(x) ((x)->si)
#define PT_REGS_PARM3(x) ((x)->dx)
#define PT_REGS_PARM4(x) ((x)->cx)
#define PT_REGS_PARM5(x) ((x)->r8)
#define PT_REGS_RET(x) ((x)->sp)
#define PT_REGS_FP(x) ((x)->bp)
#define PT_REGS_RC(x) ((x)->ax)
#define PT_REGS_SP(x) ((x)->sp)
#define PT_REGS_IP(x) ((x)->ip)
But the above does not say how to get specific parameter from function say `__sys_write
consider sys_write as
long sys_write(unsigned int fd, const char __user *buf,
size_t count);
so I need buffer, I have been trying different macros but not really sure which one giving me what?
So can anyone please clearify it
If will also read buffer if I am reading buffer then count needed too so my ebpf program get loaded and not give out of bounds access error. can anyone tell
PT_REGS_PARM*(x)
macrosPARM
in PT_REGS_PARM1(x)
stands for “parameter”. These macros give you access to the parameters of the function on which your kprobe or tracepoint is hooking to. So for example, PT_REGS_PARM1(ctx)
, where ctx
is the struct pt_regs *ctx
context passed as an argument to your eBPF program, will give you access to the first parameter, which is the file descriptor fd
. Similarly, PT_REGS_PARM3(ctx)
will give you the count
, as you can confirm by looking at this kernel sample (write_size
).
bpf_probe_read_*()
to stay safe with kernel memorySimilarly, you can point to the buffer buf
with PT_REGS_PARM2(ctx)
. However, this one is a pointer; if you want to manipulate the data contained in this buffer, you need another step, or the kernel may reject your program as unsafe. To read and copy some or all of the data from this buffer, you should use one of the eBPF helpers bpf_probe_read_*(void *dst, u32 size, const void *unsafe_ptr)
(see relevant documentation). In your case, the data contained in that buffer comes from user space, so you want bpf_probe_read_user()
.
This does not really apply to your example, because your pointer is just a buffer. But if one of your arguments were a pointer to a struct, you would need similar precautions to dereference it and access its fields.
And in such case you might want to leverage CO-RE, to make sure that you would access the correct offsets when reading the fields. If you have CO-RE support, libbpf also provides bpf_core_read*()
wrappers around the eBPF helpers, which make access relocatable. See the BPF CO-RE reference guide for more information.
Also with CO-RE (technically, just BTF this time), certain types for tracing programs, in particular BPF_PROG_TYPE_TRACING
, allow you to access struct fields without any helper (See the initial CO-RE article).