Skip to content

Commit

Permalink
feature(modern_bpf): add dynamic snaplen handling for recvmmsg/sendmmsg
Browse files Browse the repository at this point in the history
A new argument had to be added to the apply_dynamic_snaplen function, I
opted for using an auxiliar struct and pass a single pointer to it to
the function. I think this is a bit cleaner, since removing or adding
other arguments can be done by simply adding it to the struct, keeping
the function signature unchanged.

Signed-off-by: Mauro Ezequiel Moltrasio <[email protected]>
  • Loading branch information
Molter73 committed Nov 26, 2024
1 parent b94a5e3 commit 171e35b
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 22 deletions.
41 changes: 37 additions & 4 deletions driver/modern_bpf/helpers/store/auxmap_store_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -1499,10 +1499,15 @@ static __always_inline void auxmap__store_fdlist_param(struct auxiliary_map *aux
sizeof(uint16_t) + (num_pairs * (sizeof(int64_t) + sizeof(int16_t))));
}

typedef struct {
bool only_port_range;
ppm_event_code evt_type;
long mmsg_index;
} dynamic_snaplen_args;

static __always_inline void apply_dynamic_snaplen(struct pt_regs *regs,
uint16_t *snaplen,
bool only_port_range,
ppm_event_code evt_type) {
dynamic_snaplen_args *input_args) {
if(!maps__get_do_dynamic_snaplen()) {
return;
}
Expand All @@ -1519,7 +1524,9 @@ static __always_inline void apply_dynamic_snaplen(struct pt_regs *regs,
* - writev
* - pwritev
* - recvmsg
* - recvmmsg
* - sendmsg
* - sendmmsg
* - send
* - recv
* - recvfrom
Expand All @@ -1539,12 +1546,14 @@ static __always_inline void apply_dynamic_snaplen(struct pt_regs *regs,
* - writev
* - pwritev
* - recvmsg
* - recvmmsg
* - sendmsg
* - sendmmsg
*/
unsigned long args[5] = {0};
struct sockaddr *sockaddr = NULL;

switch(evt_type) {
switch(input_args->evt_type) {
case PPME_SOCKET_SENDTO_X:
case PPME_SOCKET_RECVFROM_X:
extract__network_args(args, 5, regs);
Expand All @@ -1571,6 +1580,30 @@ static __always_inline void apply_dynamic_snaplen(struct pt_regs *regs,
}
} break;

case PPME_SOCKET_RECVMMSG_X:
case PPME_SOCKET_SENDMMSG_X: {
extract__network_args(args, 3, regs);
if(bpf_in_ia32_syscall()) {
struct compat_mmsghdr compat_mmh = {};
struct compat_mmsghdr *mmh_ptr = (struct compat_mmsghdr *)args[1];
if(likely(bpf_probe_read_user(&compat_mmh,
bpf_core_type_size(struct compat_mmsghdr),
(void *)(mmh_ptr + input_args->mmsg_index)) == 0)) {
sockaddr = (struct sockaddr *)(unsigned long)(compat_mmh.msg_hdr.msg_name);
}
// in any case we break the switch.
break;
}

struct mmsghdr mmh = {};
struct mmsghdr *mmh_ptr = (struct mmsghdr *)args[1];
if(bpf_probe_read_user(&mmh,
bpf_core_type_size(struct mmsghdr),
(void *)(mmh_ptr + input_args->mmsg_index)) == 0) {
sockaddr = (struct sockaddr *)mmh.msg_hdr.msg_name;
}
} break;

default:
extract__network_args(args, 3, regs);
break;
Expand Down Expand Up @@ -1639,7 +1672,7 @@ static __always_inline void apply_dynamic_snaplen(struct pt_regs *regs,
}

/* If we check only port range without reading syscall data we can stop here */
if(only_port_range) {
if(input_args->only_port_range) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ int BPF_PROG(pread64_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.mmsg_index = PPME_SYSCALL_PREAD_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SYSCALL_PREAD_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ int BPF_PROG(preadv_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.mmsg_index = PPME_SYSCALL_PREADV_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SYSCALL_PREADV_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ int BPF_PROG(process_vm_readv_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.mmsg_index = PPME_SYSCALL_PROCESS_VM_READV_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SYSCALL_PROCESS_VM_READV_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ int BPF_PROG(process_vm_writev_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.mmsg_index = PPME_SYSCALL_PROCESS_VM_WRITEV_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SYSCALL_PROCESS_VM_WRITEV_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,13 @@ int BPF_PROG(pwrite64_x, struct pt_regs *regs, long ret) {
/* If the syscall doesn't fail we use the return value as `size`
* otherwise we need to rely on the syscall parameter provided by the user.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.mmsg_index = PPME_SYSCALL_PWRITE_X,
};
int64_t bytes_to_read = ret > 0 ? ret : extract__syscall_argument(regs, 2);
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SYSCALL_PWRITE_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if((int64_t)snaplen > bytes_to_read) {
snaplen = bytes_to_read;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,12 @@ int BPF_PROG(pwritev_x, struct pt_regs *regs, long ret) {
* otherwise we need to extract it now and it has a cost. Here we check just
* the return value if the syscall is successful.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.mmsg_index = PPME_SYSCALL_PWRITEV_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SYSCALL_PWRITEV_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(ret > 0 && snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,12 @@ int BPF_PROG(read_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.mmsg_index = PPME_SYSCALL_READ_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SYSCALL_READ_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,12 @@ int BPF_PROG(readv_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.mmsg_index = PPME_SYSCALL_READV_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SYSCALL_READV_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ int BPF_PROG(recv_x, struct pt_regs *regs, long ret) {
unsigned long args[2] = {0};
extract__network_args(args, 2, regs);

dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.mmsg_index = PPME_SOCKET_RECV_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SOCKET_RECV_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ int BPF_PROG(recvfrom_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.mmsg_index = PPME_SOCKET_RECVFROM_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SOCKET_RECVFROM_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,13 @@ static long handle_exit(uint32_t index, void *ctx) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.evt_type = PPME_SOCKET_RECVMMSG_X,
.mmsg_index = index,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(data->regs, &snaplen, true, PPME_SOCKET_RECVMMSG_X);
apply_dynamic_snaplen(data->regs, &snaplen, &snaplen_args);
if(snaplen > mmh.msg_len) {
snaplen = mmh.msg_len;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ int BPF_PROG(recvmsg_x, struct pt_regs *regs, long ret) {
/* We read the minimum between `snaplen` and what we really
* have in the buffer.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.mmsg_index = PPME_SOCKET_RECVMSG_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SOCKET_RECVMSG_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ int BPF_PROG(send_x, struct pt_regs *regs, long ret) {
unsigned long args[3] = {0};
extract__network_args(args, 3, regs);

dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.mmsg_index = PPME_SOCKET_SEND_X,
};
int64_t bytes_to_read = ret > 0 ? ret : args[2];
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SOCKET_SEND_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if((int64_t)snaplen > bytes_to_read) {
snaplen = bytes_to_read;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,13 @@ static long handle_exit(uint32_t index, void *ctx) {
* otherwise we need to extract it now and it has a cost. Here we check just
* the return value if the syscall is successful.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.evt_type = PPME_SOCKET_SENDMMSG_X,
.mmsg_index = index,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(data->regs, &snaplen, true, PPME_SOCKET_SENDMMSG_X);
apply_dynamic_snaplen(data->regs, &snaplen, &snaplen_args);
if(mmh.msg_len > 0 && snaplen > mmh.msg_len) {
snaplen = mmh.msg_len;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ int BPF_PROG(sendmsg_x, struct pt_regs *regs, long ret) {
* the return value if the syscall is successful.
*/
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SOCKET_SENDMSG_X);
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.mmsg_index = PPME_SOCKET_SENDMSG_X,
};
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(ret > 0 && snaplen > ret) {
snaplen = ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,13 @@ int BPF_PROG(sendto_x, struct pt_regs *regs, long ret) {
/* If the syscall doesn't fail we use the return value as `size`
* otherwise we need to rely on the syscall parameter provided by the user.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.evt_type = PPME_SOCKET_SENDTO_X,
};
int64_t bytes_to_read = ret > 0 ? ret : args[2];
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SOCKET_SENDTO_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if((int64_t)snaplen > bytes_to_read) {
snaplen = bytes_to_read;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,13 @@ int BPF_PROG(write_x, struct pt_regs *regs, long ret) {
/* If the syscall doesn't fail we use the return value as `size`
* otherwise we need to rely on the syscall parameter provided by the user.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = false,
.evt_type = PPME_SYSCALL_WRITE_X,
};
int64_t bytes_to_read = ret > 0 ? ret : extract__syscall_argument(regs, 2);
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SYSCALL_WRITE_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if((int64_t)snaplen > bytes_to_read) {
snaplen = bytes_to_read;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ int BPF_PROG(writev_x, struct pt_regs *regs, long ret) {
* otherwise we need to extract it now and it has a cost. Here we check just
* the return value if the syscall is successful.
*/
dynamic_snaplen_args snaplen_args = {
.only_port_range = true,
.evt_type = PPME_SYSCALL_WRITEV_X,
};
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, true, PPME_SYSCALL_WRITEV_X);
apply_dynamic_snaplen(regs, &snaplen, &snaplen_args);
if(ret > 0 && snaplen > ret) {
snaplen = ret;
}
Expand Down

0 comments on commit 171e35b

Please sign in to comment.