Skip to content

Commit

Permalink
new: extend WRITE_X/PWRITE_X
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 committed Dec 17, 2024
1 parent 9ee57c8 commit ffd8678
Show file tree
Hide file tree
Showing 22 changed files with 664 additions and 56 deletions.
2 changes: 1 addition & 1 deletion driver/SCHEMA_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.0
4.0.0
48 changes: 45 additions & 3 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,19 @@ FILLER(sys_write_x, true) {
/* 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.
*/
unsigned long bytes_to_read = retval > 0 ? retval : bpf_syscall_get_argument(data, 2);
size_t size = bpf_syscall_get_argument(data, 2);
unsigned long bytes_to_read = retval > 0 ? retval : size;
unsigned long sent_data_pointer = bpf_syscall_get_argument(data, 1);
data->fd = bpf_syscall_get_argument(data, 0);
return __bpf_val_to_ring(data, sent_data_pointer, bytes_to_read, PT_BYTEBUF, -1, true, USER);
data->fd = (int32_t)bpf_syscall_get_argument(data, 0);
res = __bpf_val_to_ring(data, sent_data_pointer, bytes_to_read, PT_BYTEBUF, -1, true, USER);
CHECK_RES(res);

/* Parameter 3: fd (type: PT_FD) */
res = bpf_push_s64_to_ring(data, (int64_t)data->fd);
CHECK_RES(res);

/* Parameter 4: size (type: PT_UINT32) */
return bpf_push_u32_to_ring(data, (uint32_t)size);
}

#define POLL_MAXFDS 16
Expand Down Expand Up @@ -4819,6 +4828,39 @@ FILLER(sys_pwrite64_e, true) {
return bpf_push_u64_to_ring(data, pos);
}

FILLER(sys_pwrite64_x, true) {
#ifndef CAPTURE_64BIT_ARGS_SINGLE_REGISTER
#error Implement this
#endif
/* Parameter 1: res (type: PT_ERRNO) */
long retval = bpf_syscall_get_retval(data->ctx);
int res = bpf_push_s64_to_ring(data, retval);
CHECK_RES(res);

/* Parameter 2: data (type: PT_BYTEBUF) */
/* 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.
*/
size_t size = bpf_syscall_get_argument(data, 2);
unsigned long bytes_to_read = retval > 0 ? retval : size;
unsigned long sent_data_pointer = bpf_syscall_get_argument(data, 1);
data->fd = (int32_t)bpf_syscall_get_argument(data, 0);
res = __bpf_val_to_ring(data, sent_data_pointer, bytes_to_read, PT_BYTEBUF, -1, true, USER);
CHECK_RES(res);

/* Parameter 3: fd (type: PT_FD) */
res = bpf_push_s64_to_ring(data, (int64_t)data->fd);
CHECK_RES(res);

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

/* Parameter 3: pos (type: PT_UINT64) */
uint64_t pos = (uint64_t)bpf_syscall_get_argument(data, 3);
return bpf_push_u64_to_ring(data, pos);
}

FILLER(sys_renameat_x, true) {
unsigned long val;
long retval;
Expand Down
23 changes: 15 additions & 8 deletions driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,17 @@ const struct ppm_event_info g_event_info[] = {
{"size", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_WRITE_E] = {"write",
EC_IO_WRITE | EC_SYSCALL,
EF_USES_FD | EF_WRITES_TO_FD,
EF_USES_FD | EF_WRITES_TO_FD | EF_TMP_CONVERTER_MANAGED,
2,
{{"fd", PT_FD, PF_DEC}, {"size", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_WRITE_X] = {"write",
EC_IO_WRITE | EC_SYSCALL,
EF_USES_FD | EF_WRITES_TO_FD,
2,
{{"res", PT_ERRNO, PF_DEC}, {"data", PT_BYTEBUF, PF_NA}}},
EF_USES_FD | EF_WRITES_TO_FD | EF_TMP_CONVERTER_MANAGED,
4,
{{"res", PT_ERRNO, PF_DEC},
{"data", PT_BYTEBUF, PF_NA},
{"fd", PT_FD, PF_DEC},
{"size", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_BRK_1_E] =
{"brk", EC_MEMORY | EC_SYSCALL, EF_OLD_VERSION, 1, {{"size", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_BRK_1_X] =
Expand Down Expand Up @@ -568,16 +571,20 @@ const struct ppm_event_info g_event_info[] = {
{"pos", PT_UINT64, PF_DEC}}},
[PPME_SYSCALL_PWRITE_E] = {"pwrite",
EC_IO_WRITE | EC_SYSCALL,
EF_USES_FD | EF_WRITES_TO_FD,
EF_USES_FD | EF_WRITES_TO_FD | EF_TMP_CONVERTER_MANAGED,
3,
{{"fd", PT_FD, PF_DEC},
{"size", PT_UINT32, PF_DEC},
{"pos", PT_UINT64, PF_DEC}}},
[PPME_SYSCALL_PWRITE_X] = {"pwrite",
EC_IO_WRITE | EC_SYSCALL,
EF_USES_FD | EF_WRITES_TO_FD,
2,
{{"res", PT_ERRNO, PF_DEC}, {"data", PT_BYTEBUF, PF_NA}}},
EF_USES_FD | EF_WRITES_TO_FD | EF_TMP_CONVERTER_MANAGED,
5,
{{"res", PT_ERRNO, PF_DEC},
{"data", PT_BYTEBUF, PF_NA},
{"fd", PT_FD, PF_DEC},
{"size", PT_UINT32, PF_DEC},
{"pos", PT_UINT64, PF_DEC}}},
[PPME_SYSCALL_READV_E] = {"readv",
EC_IO_READ | EC_SYSCALL,
EF_USES_FD | EF_READS_FROM_FD,
Expand Down
2 changes: 1 addition & 1 deletion driver/fillers_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
[PPME_SYSCALL_PREAD_E] = {FILLER_REF(sys_pread64_e)},
[PPME_SYSCALL_PREAD_X] = {FILLER_REF(sys_pread64_x)},
[PPME_SYSCALL_PWRITE_E] = {FILLER_REF(sys_pwrite64_e)},
[PPME_SYSCALL_PWRITE_X] = {FILLER_REF(sys_write_x)},
[PPME_SYSCALL_PWRITE_X] = {FILLER_REF(sys_pwrite64_x)},
[PPME_SYSCALL_READV_E] = {FILLER_REF(sys_readv_e)},
[PPME_SYSCALL_READV_X] = {FILLER_REF(sys_readv_preadv_x)},
[PPME_SYSCALL_WRITEV_E] = {FILLER_REF(sys_writev_e)},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ 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.
*/
int64_t bytes_to_read = ret > 0 ? ret : extract__syscall_argument(regs, 2);
size_t size = extract__syscall_argument(regs, 2);
int64_t bytes_to_read = ret > 0 ? ret : size;
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SYSCALL_PWRITE_X);
if((int64_t)snaplen > bytes_to_read) {
Expand All @@ -73,6 +74,17 @@ int BPF_PROG(pwrite64_x, struct pt_regs *regs, long ret) {
unsigned long data_pointer = extract__syscall_argument(regs, 1);
auxmap__store_bytebuf_param(auxmap, data_pointer, snaplen, USER);

/* Parameter 3: fd (type: PT_FD) */
int32_t fd = (int32_t)extract__syscall_argument(regs, 0);
auxmap__store_s64_param(auxmap, (int64_t)fd);

/* Parameter 4: size (type: PT_UINT32) */
auxmap__store_u32_param(auxmap, size);

/* Parameter 5: pos (type: PT_UINT64) */
uint64_t pos = (uint64_t)extract__syscall_argument(regs, 3);
auxmap__store_u64_param(auxmap, pos);

/*=============================== COLLECT PARAMETERS ===========================*/

auxmap__finalize_event_header(auxmap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ 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.
*/
int64_t bytes_to_read = ret > 0 ? ret : extract__syscall_argument(regs, 2);
size_t size = extract__syscall_argument(regs, 2);
int64_t bytes_to_read = ret > 0 ? ret : size;
uint16_t snaplen = maps__get_snaplen();
apply_dynamic_snaplen(regs, &snaplen, false, PPME_SYSCALL_WRITE_X);
if((int64_t)snaplen > bytes_to_read) {
Expand All @@ -69,6 +70,13 @@ int BPF_PROG(write_x, struct pt_regs *regs, long ret) {
unsigned long data_pointer = extract__syscall_argument(regs, 1);
auxmap__store_bytebuf_param(auxmap, data_pointer, snaplen, USER);

/* Parameter 3: fd (type: PT_FD) */
int32_t fd = (int32_t)extract__syscall_argument(regs, 0);
auxmap__store_s64_param(auxmap, (int64_t)fd);

/* Parameter 4: size (type: PT_UINT32) */
auxmap__store_u32_param(auxmap, size);

/*=============================== COLLECT PARAMETERS ===========================*/

auxmap__finalize_event_header(auxmap);
Expand Down
76 changes: 73 additions & 3 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ int f_sys_write_x(struct event_filler_arguments *args) {
int res;
int64_t retval;
unsigned long bufsize;
size_t size = 0;

/*
* Retrieve the FD. It will be used for dynamic snaplen calculation.
Expand All @@ -474,14 +475,21 @@ int f_sys_write_x(struct event_filler_arguments *args) {

/* Parameter 2: data (type: PT_BYTEBUF) */
/* Get the size from userspace paramater */
syscall_get_arguments_deprecated(args, 2, 1, &val);
bufsize = retval > 0 ? retval : val;

syscall_get_arguments_deprecated(args, 2, 1, &size);
bufsize = retval > 0 ? retval : size;
syscall_get_arguments_deprecated(args, 1, 1, &val);
args->enforce_snaplen = true;
res = val_to_ring(args, val, bufsize, true, 0);
CHECK_RES(res);

/* Parameter 3: fd (type: PT_FD) */
res = val_to_ring(args, (int64_t)args->fd, 0, false, 0);
CHECK_RES(res);

/* Parameter 4: size (type: PT_UINT32) */
res = val_to_ring(args, (uint32_t)size, 0, false, 0);
CHECK_RES(res);

return add_sentinel(args);
}

Expand Down Expand Up @@ -3799,6 +3807,68 @@ int f_sys_pwrite64_e(struct event_filler_arguments *args) {
return add_sentinel(args);
}

int f_sys_pwrite64_x(struct event_filler_arguments *args) {
unsigned long val;
int res;
int64_t retval;
unsigned long bufsize;
size_t size = 0;
unsigned long pos64 = 0;

/*
* Retrieve the FD. It will be used for dynamic snaplen calculation.
*/
syscall_get_arguments_deprecated(args, 0, 1, &val);
args->fd = (int)val;

/* Parameter 1: res (type: PT_ERRNO) */
retval = (int64_t)(long)syscall_get_return_value(current, args->regs);
res = val_to_ring(args, retval, 0, false, 0);
CHECK_RES(res);

/* Parameter 2: data (type: PT_BYTEBUF) */
/* Get the size from userspace paramater */
syscall_get_arguments_deprecated(args, 2, 1, &size);
bufsize = retval > 0 ? retval : size;
syscall_get_arguments_deprecated(args, 1, 1, &val);
args->enforce_snaplen = true;
res = val_to_ring(args, val, bufsize, true, 0);
CHECK_RES(res);

/* Parameter 3: fd (type: PT_FD) */
res = val_to_ring(args, (int64_t)args->fd, 0, false, 0);
CHECK_RES(res);

/* Parameter 4: size (type: PT_UINT32) */
res = val_to_ring(args, (uint32_t)size, 0, false, 0);
CHECK_RES(res);

/* Parameter 5: pos (type: PT_UINT64) */
#ifndef CAPTURE_64BIT_ARGS_SINGLE_REGISTER
{
unsigned long pos0 = 0;
unsigned long pos1 = 0;
#if defined CONFIG_X86
syscall_get_arguments_deprecated(args, 3, 1, &pos0);
syscall_get_arguments_deprecated(args, 4, 1, &pos1);
#elif defined CONFIG_ARM && CONFIG_AEABI
syscall_get_arguments_deprecated(args, 4, 1, &pos0);
syscall_get_arguments_deprecated(args, 5, 1, &pos1);
#else
#error This architecture/abi not yet supported
#endif
pos64 = merge_64(pos1, pos0);
}
#else
syscall_get_arguments_deprecated(args, 3, 1, &pos64);
#endif /* CAPTURE_64BIT_ARGS_SINGLE_REGISTER*/

res = val_to_ring(args, pos64, 0, false, 0);
CHECK_RES(res);

return add_sentinel(args);
}

int f_sys_preadv_e(struct event_filler_arguments *args) {
unsigned long val;
int res;
Expand Down
1 change: 1 addition & 0 deletions driver/ppm_fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ or GPL2.txt for full copies of the license.
FN(sys_process_vm_writev_x) \
FN(sys_delete_module_x) \
FN(sys_pread64_x) \
FN(sys_pwrite64_x) \
FN(terminate_filler)

#define FILLER_ENUM_FN(x) PPM_FILLER_##x,
Expand Down
4 changes: 2 additions & 2 deletions test/drivers/test_suites/actions_suite/dynamic_snaplen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ TEST(Actions, dynamic_snaplen_negative_fd) {

/*=============================== ASSERT PARAMETERS ===========================*/

evt_test->assert_num_params_pushed(2);
evt_test->assert_num_params_pushed(4);
}

TEST(Actions, dynamic_snaplen_no_socket) {
Expand Down Expand Up @@ -158,7 +158,7 @@ TEST(Actions, dynamic_snaplen_no_socket) {

/*=============================== ASSERT PARAMETERS ===========================*/

evt_test->assert_num_params_pushed(2);
evt_test->assert_num_params_pushed(4);
}

#if defined(__NR_sendto) && defined(__NR_socket) && defined(__NR_shutdown) && \
Expand Down
33 changes: 30 additions & 3 deletions test/drivers/test_suites/syscall_exit_suite/pwrite64_x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,18 @@ TEST(SyscallExit, pwrite64X_no_snaplen) {
/* Parameter 2: data (type: PT_BYTEBUF) */
evt_test->assert_bytebuf_param(2, buf, DEFAULT_SNAPLEN / 2);

/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)fd);

/* Parameter 4: size (type: PT_UINT32) */
evt_test->assert_numeric_param(4, (uint32_t)data_len);

/* Parameter 5: pos (type: PT_UINT64) */
evt_test->assert_numeric_param(5, (uint64_t)off);

/*=============================== ASSERT PARAMETERS ===========================*/

evt_test->assert_num_params_pushed(2);
evt_test->assert_num_params_pushed(5);
}

TEST(SyscallExit, pwrite64X_snaplen) {
Expand Down Expand Up @@ -90,9 +99,18 @@ TEST(SyscallExit, pwrite64X_snaplen) {
/* Parameter 2: data (type: PT_BYTEBUF) */
evt_test->assert_bytebuf_param(2, buf, DEFAULT_SNAPLEN);

/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)-1);

/* Parameter 4: size (type: PT_UINT32) */
evt_test->assert_numeric_param(4, (uint32_t)data_len);

/* Parameter 5: pos (type: PT_UINT64) */
evt_test->assert_numeric_param(5, (uint64_t)off);

/*=============================== ASSERT PARAMETERS ===========================*/

evt_test->assert_num_params_pushed(2);
evt_test->assert_num_params_pushed(5);
}

TEST(SyscallExit, pwrite64X_fail) {
Expand Down Expand Up @@ -133,9 +151,18 @@ TEST(SyscallExit, pwrite64X_fail) {
/* Parameter 2: data (type: PT_BYTEBUF) */
evt_test->assert_empty_param(2);

/* Parameter 3: fd (type: PT_FD) */
evt_test->assert_numeric_param(3, (int64_t)-1);

/* Parameter 4: size (type: PT_UINT32) */
evt_test->assert_numeric_param(4, (uint32_t)data_len);

/* Parameter 5: pos (type: PT_UINT64) */
evt_test->assert_numeric_param(5, (uint64_t)off);

/*=============================== ASSERT PARAMETERS ===========================*/

evt_test->assert_num_params_pushed(2);
evt_test->assert_num_params_pushed(5);
}

#endif
Expand Down
Loading

0 comments on commit ffd8678

Please sign in to comment.