marosoaie
marosoaie

Reputation: 2381

Get a probed function's arguments in the entry_handler of a kretprobe

I'm trying to intercept the kmalloc using a kretprobe void *__kmalloc(size_t size, gfp_t flags); I can find out the return value of kmalloc using the handler member of the kretprobe structure.

static struct kretprobe kmalloc_probe = {
    .handler = kmalloc_ret_handler,
    .entry_handler = kmalloc_entry_handler,
    .data_size = sizeof(struct kmalloc_read_args),
    .maxactive = 20,
};

But I need a way to find the arguments the function was called with in the entry_handler. This is my entry_handler function:

static int kmalloc_entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)

I tried searching in all the registers of the regs struct argument, but no luck. The architecture I'm using using is i686. I know jprobes would be a better match for solving this type of problem but I need to solve it using only kretprobes. Can you please give me a hint of how I could use the registers, or the stack to find the function call arguments?

A link to the pt_regs structure: http://lxr.free-electrons.com/source/arch/x86/include/asm/ptrace.h#L11

Upvotes: 4

Views: 2838

Answers (1)

Eugene
Eugene

Reputation: 6097

The conventions for argument passing in the kernel on x86 are described in the comments in asm/calling.h.

On 32-bit x86 systems, the first parameters of the functions in the Linux kernel (except system calls and some other stuff) are usually passed in %eax, %edx, %ecx, in order. This is because the sources are compiled with '-mregparm=3' GCC option, set by default. This is the case since kernel 2.6.32 at least, or may be from even earlier.

The remaining parameters are passed on stack.

If the function had a variable argument list (like sprintf()), all parameters were passed on stack, as far as I had seen.

So, in your case, size should be in %eax and flags - in %edx on entry to the function. If these registers are not clobbered somehow by the kretprobe, you should be able to find them in pt_regs.

On 64-bit x86 systems, the convention is simpler and more in line with x86-64 ABI. The first arguments of the kernel functions (again, except system calls and some special functions) are passed in %rdi, %rsi, %rdx, %rcx, %r8, %r9, in order, the remaining ones are on stack.

Upvotes: 2

Related Questions