Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add arguments for sendmmsg and recvmmsg #2027

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 230 additions & 0 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4253,6 +4253,143 @@ FILLER(sys_recvmsg_x_2, true) {
return res;
}

FILLER(sys_recvmmsg_x, true) {
const struct iovec *iov;
struct mmsghdr mmh;
unsigned long iovcnt;
unsigned long val;
int res;
int fd;

/* Parameter 1: res (type: PT_ERRNO) */
long retval = bpf_syscall_get_retval(data->ctx);

/* If the syscall fails we are not able to collect reliable params
* so we return empty ones.
*/
if(retval < 0) {
res = bpf_push_s64_to_ring(data, retval);
CHECK_RES(res);

/* Parameter 2: fd (type: PT_FD) */
res = bpf_push_empty_param(data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like in the other drivers we probably want to push the fd of the syscall here

CHECK_RES(res);

/* Parameter 3: size (type: PT_UINT32) */
res = bpf_push_u32_to_ring(data, 0);
CHECK_RES(res);

/* Parameter 4: data (type: PT_BYTEBUF) */
res = bpf_push_empty_param(data);
CHECK_RES(res);

/* Parameter 5: tuple (type: PT_SOCKTUPLE) */
res = bpf_push_empty_param(data);
CHECK_RES(res);

/* Parameter 6: msg_control (type: PT_BYTEBUF) */
return bpf_push_empty_param(data);
}

fd = bpf_syscall_get_argument(data, 0);

/*
* Retrieve the message header
*/
val = bpf_syscall_get_argument(data, 1);
if(bpf_probe_read_user(&mmh, sizeof(mmh), (void *)val))
return PPM_FAILURE_INVALID_USER_MEMORY;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use the usual comments like /* Parameter 1: res (type: PT_ERRNO) */ just to understand what we are pushing

res = bpf_push_s64_to_ring(data, mmh.msg_len);
CHECK_RES(res);

res = bpf_push_s64_to_ring(data, fd);
CHECK_RES(res);

/*
* data and size
*/
iov = (const struct iovec *)mmh.msg_hdr.msg_iov;
iovcnt = mmh.msg_hdr.msg_iovlen;

res = bpf_parse_readv_writev_bufs(data, iov, iovcnt, mmh.msg_len, PRB_FLAG_PUSH_ALL);
CHECK_RES(res);

bpf_tail_call(data->ctx, &tail_map, PPM_FILLER_sys_recvmmsg_x_2);
bpf_printk("Can't tail call f_sys_recvmsg_x_2 filler\n");
return PPM_FAILURE_BUG;
}

FILLER(sys_recvmmsg_x_2, true) {
struct sockaddr *usrsockaddr;
struct mmsghdr mmh;
unsigned long val;
uint16_t size = 0;
long retval;
int addrlen;
int res;
int fd;

retval = bpf_syscall_get_retval(data->ctx);

/*
* tuple and msg_control
*/

/*
* Retrieve the message header
*/
val = bpf_syscall_get_argument(data, 1);
if(bpf_probe_read_user(&mmh, sizeof(mmh), (void *)val))
return PPM_FAILURE_INVALID_USER_MEMORY;

/*
* Get the address
*/
usrsockaddr = (struct sockaddr *)mmh.msg_hdr.msg_name;
addrlen = mmh.msg_hdr.msg_namelen;

if(usrsockaddr && addrlen != 0) {
/*
* Copy the address
*/
res = bpf_addr_to_kernel(usrsockaddr, addrlen, (struct sockaddr *)data->tmp_scratch);

if(res >= 0) {
fd = bpf_syscall_get_argument(data, 0);

/*
* Convert the fd into socket endpoint information
*/
size = bpf_fd_to_socktuple(data,
fd,
(struct sockaddr *)data->tmp_scratch,
addrlen,
true,
true,
data->tmp_scratch + sizeof(struct sockaddr_storage));
}
}

data->curarg_already_on_frame = true;
res = __bpf_val_to_ring(data, 0, size, PT_SOCKTUPLE, -1, false, KERNEL);
CHECK_RES(res);

if(mmh.msg_hdr.msg_control != NULL) {
res = __bpf_val_to_ring(data,
(unsigned long)mmh.msg_hdr.msg_control,
mmh.msg_hdr.msg_controllen,
PT_BYTEBUF,
-1,
false,
USER);
} else {
res = bpf_push_empty_param(data);
}

return res;
}

FILLER(sys_sendmsg_e, true) {
struct sockaddr *usrsockaddr;
const struct iovec *iov;
Expand Down Expand Up @@ -4346,6 +4483,99 @@ FILLER(sys_sendmsg_x, true) {
return res;
}

FILLER(sys_sendmmsg_x, true) {
struct sockaddr *usrsockaddr;
struct mmsghdr mmh = {0};
struct mmsghdr *mmh_ptr;
unsigned long vlen;
unsigned long val;
uint16_t size = 0;
int addrlen;
int err = 0;
int res;
long retval = bpf_syscall_get_retval(data->ctx);
int fd;

if(retval < 0) {
/* Parameter 1: res (type: PT_ERRNO) */
res = bpf_push_s64_to_ring(data, retval);
CHECK_RES(res);

/* Parameter 2: fd (type: PT_BYTEBUF) */
bpf_push_empty_param(data);
CHECK_RES(res);

/* Parameter 3: size (type: PT_UINT32) */
bpf_push_u32_to_ring(data, 0);
CHECK_RES(res);

/* Parameter 4: data (type: PT_BYTEBUF) */
bpf_push_empty_param(data);
CHECK_RES(res);

/* Parameter 5: tuple (type: PT_SOCKTUPLE) */
return bpf_push_empty_param(data);
}

fd = bpf_syscall_get_argument(data, 0);
mmh_ptr = (struct mmsghdr *)bpf_syscall_get_argument(data, 1);
vlen = bpf_syscall_get_argument(data, 2);

/* Retrieve the message header */
if(bpf_probe_read_user(&mmh, sizeof(mmh), (void *)(mmh_ptr))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if mmh_ptr we rely on the fact that mmh is zeroed and we won't enter all the following branches, is it true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed this question the first time I went through the review, sorry.

mmh_ptr is read from the arguments, as such, I assume it will always be pointing to a valid position in memory because the syscall was successful here and we haven't returned control to userspace, so the memory must still be there. If, for whatever reason, the pointer was invalid or it was no longer readable due to a cache miss or such a situation, I would expect bpf_probe_read_user to fail and the event to be dropped altogether, (the if condition will be true).

Am I missing something here?

return PPM_FAILURE_INVALID_USER_MEMORY;
}

/* Parameter 1: res (type: PT_ERRNO) */
res = bpf_push_s64_to_ring(data, mmh.msg_len);
CHECK_RES(res);

/* Parameter 2: fd (type: PT_FD) */
res = bpf_push_s64_to_ring(data, fd);
CHECK_RES(res);

/* Parameter 3: size (type: PT_UINT32) */
/* Parameter 4: data (type: PT_BYTEBUF) */
const struct iovec *iov = (const struct iovec *)mmh.msg_hdr.msg_iov;
unsigned long iovcnt = mmh.msg_hdr.msg_iovlen;

res = bpf_parse_readv_writev_bufs(data,
iov,
iovcnt,
mmh.msg_len,
PRB_FLAG_PUSH_ALL | PRB_FLAG_IS_WRITE);
CHECK_RES(res);

/* Parameter 5: tuple (type: PT_SOCKTUPLE) */
usrsockaddr = (struct sockaddr *)mmh.msg_hdr.msg_name;
addrlen = mmh.msg_hdr.msg_namelen;

if(usrsockaddr && addrlen != 0) {
/*
* Copy the address
*/
err = bpf_addr_to_kernel(usrsockaddr, addrlen, (struct sockaddr *)data->tmp_scratch);

if(err >= 0) {
/*
* Convert the fd into socket endpoint information
*/
size = bpf_fd_to_socktuple(data,
fd,
(struct sockaddr *)data->tmp_scratch,
addrlen,
true,
false,
data->tmp_scratch + sizeof(struct sockaddr_storage));
}

data->curarg_already_on_frame = true;
res = __bpf_val_to_ring(data, 0, size, PT_SOCKTUPLE, -1, false, KERNEL);
}

return res;
}

FILLER(sys_creat_e, true) {
unsigned long val;
unsigned long mode;
Expand Down
21 changes: 19 additions & 2 deletions driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,15 @@ const struct ppm_event_info g_event_info[] = {
2,
{{"res", PT_ERRNO, PF_DEC}, {"data", PT_BYTEBUF, PF_NA}}},
[PPME_SOCKET_SENDMMSG_E] = {"sendmmsg", EC_IO_WRITE | EC_SYSCALL, EF_NONE, 0},
[PPME_SOCKET_SENDMMSG_X] = {"sendmmsg", EC_IO_WRITE | EC_SYSCALL, EF_NONE, 0},
[PPME_SOCKET_SENDMMSG_X] = {"sendmmsg",
EC_IO_WRITE | EC_SYSCALL,
EF_USES_FD | EF_WRITES_TO_FD | EF_MODIFIES_STATE,
5,
{{"res", PT_ERRNO, PF_DEC},
{"fd", PT_FD, PF_DEC},
{"size", PT_UINT32, PF_DEC},
{"data", PT_BYTEBUF, PF_NA},
{"tuple", PT_SOCKTUPLE, PF_NA}}},
[PPME_SOCKET_RECVMSG_E] = {"recvmsg",
EC_IO_READ | EC_SYSCALL,
EF_USES_FD | EF_READS_FROM_FD | EF_MODIFIES_STATE,
Expand All @@ -327,7 +335,16 @@ const struct ppm_event_info g_event_info[] = {
{"tuple", PT_SOCKTUPLE, PF_NA},
{"msgcontrol", PT_BYTEBUF, PF_NA}}},
[PPME_SOCKET_RECVMMSG_E] = {"recvmmsg", EC_IO_READ | EC_SYSCALL, EF_NONE, 0},
[PPME_SOCKET_RECVMMSG_X] = {"recvmmsg", EC_IO_READ | EC_SYSCALL, EF_NONE, 0},
[PPME_SOCKET_RECVMMSG_X] = {"recvmmsg",
EC_IO_READ | EC_SYSCALL,
EF_USES_FD | EF_READS_FROM_FD | EF_MODIFIES_STATE,
6,
{{"res", PT_ERRNO, PF_DEC},
{"fd", PT_FD, PF_DEC},
{"size", PT_UINT32, PF_DEC},
{"data", PT_BYTEBUF, PF_NA},
{"tuple", PT_SOCKTUPLE, PF_NA},
{"msgcontrol", PT_BYTEBUF, PF_NA}}},
[PPME_SOCKET_ACCEPT4_E] = {"accept",
EC_NET | EC_SYSCALL,
EF_CREATES_FD | EF_MODIFIES_STATE | EF_OLD_VERSION,
Expand Down
4 changes: 2 additions & 2 deletions driver/fillers_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
[PPME_SOCKET_SENDMSG_E] = {FILLER_REF(sys_sendmsg_e)},
[PPME_SOCKET_SENDMSG_X] = {FILLER_REF(sys_sendmsg_x)},
[PPME_SOCKET_SENDMMSG_E] = {FILLER_REF(sys_empty)},
[PPME_SOCKET_SENDMMSG_X] = {FILLER_REF(sys_empty)},
[PPME_SOCKET_SENDMMSG_X] = {FILLER_REF(sys_sendmmsg_x)},
[PPME_SOCKET_RECVMSG_E] = {FILLER_REF(sys_recvmsg_e)},
[PPME_SOCKET_RECVMSG_X] = {FILLER_REF(sys_recvmsg_x)},
[PPME_SOCKET_RECVMMSG_E] = {FILLER_REF(sys_empty)},
[PPME_SOCKET_RECVMMSG_X] = {FILLER_REF(sys_empty)},
[PPME_SOCKET_RECVMMSG_X] = {FILLER_REF(sys_recvmmsg_x)},
[PPME_SYSCALL_CREAT_E] = {FILLER_REF(sys_creat_e)},
[PPME_SYSCALL_CREAT_X] = {FILLER_REF(sys_creat_x)},
[PPME_SYSCALL_PIPE_E] = {FILLER_REF(sys_empty)},
Expand Down
33 changes: 32 additions & 1 deletion driver/modern_bpf/definitions/aarch64/vmlinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -7538,7 +7538,38 @@ enum bpf_func_id {
BPF_FUNC_ktime_get_coarse_ns = 160,
BPF_FUNC_ima_inode_hash = 161,
BPF_FUNC_sock_from_file = 162,
__BPF_FUNC_MAX_ID = 163,
BPF_FUNC_check_mtu = 163,
BPF_FUNC_for_each_map_elem = 164,
BPF_FUNC_snprintf = 165,
BPF_FUNC_sys_bpf = 166,
BPF_FUNC_btf_find_by_name_kind = 167,
BPF_FUNC_sys_close = 168,
BPF_FUNC_timer_init = 169,
BPF_FUNC_timer_set_callback = 170,
BPF_FUNC_timer_start = 171,
BPF_FUNC_timer_cancel = 172,
BPF_FUNC_get_func_ip = 173,
BPF_FUNC_get_attach_cookie = 174,
BPF_FUNC_task_pt_regs = 175,
BPF_FUNC_get_branch_snapshot = 176,
BPF_FUNC_trace_vprintk = 177,
BPF_FUNC_skc_to_unix_sock = 178,
BPF_FUNC_kallsyms_lookup_name = 179,
BPF_FUNC_find_vma = 180,
BPF_FUNC_loop = 181,
BPF_FUNC_strncmp = 182,
BPF_FUNC_get_func_arg = 183,
BPF_FUNC_get_func_ret = 184,
BPF_FUNC_get_func_arg_cnt = 185,
BPF_FUNC_get_retval = 186,
BPF_FUNC_set_retval = 187,
BPF_FUNC_xdp_get_buff_len = 188,
BPF_FUNC_xdp_load_bytes = 189,
BPF_FUNC_xdp_store_bytes = 190,
BPF_FUNC_copy_from_user_task = 191,
BPF_FUNC_skb_set_tstamp = 192,
BPF_FUNC_ima_file_hash = 193,
__BPF_FUNC_MAX_ID = 194,
};

struct bpf_func_info {
Expand Down
2 changes: 0 additions & 2 deletions driver/modern_bpf/definitions/events_dimensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,7 @@
HEADER_LEN + sizeof(int64_t) * 2 + sizeof(uint64_t) + sizeof(uint32_t) + PARAM_LEN * 4
#define SPLICE_X_SIZE HEADER_LEN + sizeof(int64_t) + PARAM_LEN
#define RECVMMSG_E_SIZE HEADER_LEN
#define RECVMMSG_X_SIZE HEADER_LEN
#define SENDMMSG_E_SIZE HEADER_LEN
#define SENDMMSG_X_SIZE HEADER_LEN
#define SEMOP_E_SIZE HEADER_LEN + sizeof(int32_t) + PARAM_LEN
#define SEMOP_X_SIZE \
HEADER_LEN + sizeof(int64_t) + sizeof(uint32_t) + sizeof(uint16_t) * 4 + sizeof(int16_t) * 2 + \
Expand Down
33 changes: 32 additions & 1 deletion driver/modern_bpf/definitions/x86_64/vmlinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -39754,7 +39754,38 @@ enum bpf_func_id {
BPF_FUNC_ktime_get_coarse_ns = 160,
BPF_FUNC_ima_inode_hash = 161,
BPF_FUNC_sock_from_file = 162,
__BPF_FUNC_MAX_ID = 163,
BPF_FUNC_check_mtu = 163,
BPF_FUNC_for_each_map_elem = 164,
BPF_FUNC_snprintf = 165,
BPF_FUNC_sys_bpf = 166,
BPF_FUNC_btf_find_by_name_kind = 167,
BPF_FUNC_sys_close = 168,
BPF_FUNC_timer_init = 169,
BPF_FUNC_timer_set_callback = 170,
BPF_FUNC_timer_start = 171,
BPF_FUNC_timer_cancel = 172,
BPF_FUNC_get_func_ip = 173,
BPF_FUNC_get_attach_cookie = 174,
BPF_FUNC_task_pt_regs = 175,
BPF_FUNC_get_branch_snapshot = 176,
BPF_FUNC_trace_vprintk = 177,
BPF_FUNC_skc_to_unix_sock = 178,
BPF_FUNC_kallsyms_lookup_name = 179,
BPF_FUNC_find_vma = 180,
BPF_FUNC_loop = 181,
BPF_FUNC_strncmp = 182,
BPF_FUNC_get_func_arg = 183,
BPF_FUNC_get_func_ret = 184,
BPF_FUNC_get_func_arg_cnt = 185,
BPF_FUNC_get_retval = 186,
BPF_FUNC_set_retval = 187,
BPF_FUNC_xdp_get_buff_len = 188,
BPF_FUNC_xdp_load_bytes = 189,
BPF_FUNC_xdp_store_bytes = 190,
BPF_FUNC_copy_from_user_task = 191,
BPF_FUNC_skb_set_tstamp = 192,
BPF_FUNC_ima_file_hash = 193,
__BPF_FUNC_MAX_ID = 194,
};

enum {
Expand Down
Loading
Loading