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?
This is not unexpected, what you are seeing are the arguments from userspace that are passed to the kernel via a syscall. The buffer is empty since the kernel is supposed to write packet contents into it after this tracepoint has been ran. The address is an optional field, and is allowed to be empty according to the man page of
recvfrom:I recommend using TC programs to inspect traffic