Search code examples
cbpfebpf

bpf_trace_printk format pointer


How is "%p" implemented in bpf_trace_printk? It seems very different with printf.

#include <uapi/linux/ptrace.h>

int print_args(struct pt_regs *ctx) {
    void *ptr = (void*)PT_REGS_PARM1(ctx);
    bpf_trace_printk("args: %lx %p %ld\n", ptr, ptr, ptr);
    return 0;
}

I use this eBPF program to trace argument to one function. The parameter's type is a pointer to some struct.

One output is: args: 7ffde047d6c4 00000000ec7e9023 140728366257860

We can notice that the output of "%p" is very strange. If we use a standard C program to check the output:

#include <stdio.h>

int main() {
    void *ptr = (void*)0x7ffde047d6c4;
    printf("args: %lx %p %ld\n", ptr, ptr, ptr);
    return 0;
}

We will get: args: 7ffde047d6c4 0x7ffde047d6c4 140728366257860


Solution

  • TL;DR. The value you're seeing is a hash of the actual address, computed by ptr_to_id(). The address is hashed to avoid pointer leaks while still being able to use this value as a unique identifier.


    Explanations. The implementation of the bpf_trace_printk helper can be found in kernel/trace/bpf_trace.c in the kernel sources. Most of the code is there to restrict what specifiers you can use, before calling __trace_printk(). You can follow the trail of functions to vsnprintf() which, for %p, calls pointer() whose default behavior is to hash the address to avoid pointer leaks.