I am trying to write a small program that leverages Linux's tracepoints sys_enter_recvfrom
and sys_enter_sendto
to display the pairs of HTTP requests and responses that occur on the system.
First of all, I defined the following C structure that can hold an HTTP Object, so either a request or a response:
struct http_obj {
char comm[TASK_COMM_LEN];
int fd;
char *buff;
char *addr_data;
int size;
};
Following are my tracepoints:
TRACEPOINT_PROBE(syscalls, sys_enter_recvfrom) {
return do_trace(args, args->fd, args->ubuf, args->addr);
}
TRACEPOINT_PROBE(syscalls, sys_enter_sendto){
return do_trace(args, args->fd, args->buff, args->addr);
}
Following is the function that gets the args
of the sys_enter_<syscall>
tracepoint:
static inline int do_trace(void* ctx, int fd, char *ubuf, struct sockaddr *addr)
{
// Built event for userland
struct http_obj evt = {};
bpf_get_current_comm(evt.comm, TASK_COMM_LEN);
evt.fd = fd;
evt.buff = (char *) ubuf;
evt.size = sizeof(ubuf);
evt.addr_data = (char *) addr->sa_data;
// send to userland
http_obj.perf_submit(ctx, &evt, sizeof(evt));
return 0;
}
Using the bcc
library in python, I am simply printing the values of the fields that are sent to userland. The problem is that the buffer and the address of the event are always empty. Note that the fields exist, if we do a cat
on /sys/kernel/debug/tracing/events/syscalls/sys_enter_recvfrom
, we get:
field:int __syscall_nr; offset:8; size:4; signed:1;
field:int fd; offset:16; size:8; signed:0;
field:void __attribute__((user)) * buff; offset:24; size:8; signed:0;
field:size_t len; offset:32; size:8; signed:0;
field:unsigned int flags; offset:40; size:8; signed:0;
field:struct sockaddr __attribute__((user)) * addr; offset:48; size:8; signed:0;
field:int addr_len; offset:56; size:8; signed:0;
Any recommendations?