Skip to content

Commit

Permalink
new: support io_uring_enter syscall
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 committed Jan 24, 2023
1 parent 48d74fa commit 24403b5
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 64 deletions.
67 changes: 25 additions & 42 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3387,54 +3387,37 @@ FILLER(sys_io_uring_setup_x, true)

FILLER(sys_io_uring_enter_x, true)
{
long retval;
int res;
unsigned long val;

retval = bpf_syscall_get_retval(data->ctx);
res = bpf_val_to_ring(data, retval);
if (res != PPM_SUCCESS)
return res;
/* Parameter 1: res (type: PT_ERRNO) */
long retval = bpf_syscall_get_retval(data->ctx);
int res = bpf_val_to_ring(data, retval);
CHECK_RES(res);

/*
* fd
*/
val = bpf_syscall_get_argument(data, 0);
res = bpf_val_to_ring(data, val);
if (res != PPM_SUCCESS)
return res;
/* Parameter 2: fd (type: PT_FD) */
s32 fd = (s32)bpf_syscall_get_argument(data, 0);
res = bpf_val_to_ring(data, (s64)fd);
CHECK_RES(res);

/*
* to_submit
*/
val = bpf_syscall_get_argument(data, 1);
res = bpf_val_to_ring(data, val);
if (res != PPM_SUCCESS)
return res;
/* Parameter 3: to_submit (type: PT_UINT32) */
u32 to_submit = (u32)bpf_syscall_get_argument(data, 1);
res = bpf_val_to_ring(data, to_submit);
CHECK_RES(res);

/*
* min_complete
*/
val = bpf_syscall_get_argument(data, 2);
res = bpf_val_to_ring(data, val);
if (res != PPM_SUCCESS)
return res;
/* Parameter 4: min_complete (type: PT_UINT32) */
u32 min_complete = (u32)bpf_syscall_get_argument(data, 2);
res = bpf_val_to_ring(data, min_complete);
CHECK_RES(res);

/*
* flags
*/
val = bpf_syscall_get_argument(data, 3);
res = bpf_val_to_ring(data, io_uring_enter_flags_to_scap(val));
if (res != PPM_SUCCESS)
return res;
/* Parameter 5: flags (type: PT_FLAGS32) */
u32 flags = (u32)bpf_syscall_get_argument(data, 3);
res = bpf_val_to_ring(data, io_uring_enter_flags_to_scap(flags));
CHECK_RES(res);

/*
* min_complete
*/
val = bpf_syscall_get_argument(data, 4);
res = bpf_val_to_ring(data, val);
/* Parameter 6: sig (type: PT_SIGSET) */
u32 sig = (u32)bpf_syscall_get_argument(data, 4);
return bpf_val_to_ring(data, sig);

return res;
/// TODO: We miss the last parameter `size_t argsz`
/// we need to implement it in all our drivers
}

FILLER(sys_io_uring_register_x, true)
Expand Down
2 changes: 2 additions & 0 deletions driver/modern_bpf/definitions/events_dimensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
#define MLOCKALL_X_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint32_t) + PARAM_LEN * 2
#define MUNLOCKALL_E_SIZE HEADER_LEN
#define MUNLOCKALL_X_SIZE HEADER_LEN + sizeof(int64_t) + PARAM_LEN
#define IO_URING_ENTER_E_SIZE HEADER_LEN
#define IO_URING_ENTER_X_SIZE HEADER_LEN + sizeof(int64_t) * 2 + sizeof(uint32_t) * 4 + PARAM_LEN * 6

/* Generic tracepoints events. */
#define PROC_EXIT_SIZE HEADER_LEN + sizeof(int64_t) * 2 + sizeof(uint8_t) * 2 + PARAM_LEN * 4
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (C) 2023 The Falco Authors.
*
* This file is dual licensed under either the MIT or GPL 2. See MIT.txt
* or GPL2.txt for full copies of the license.
*/

#include <helpers/interfaces/fixed_size_event.h>

/*=============================== ENTER EVENT ===========================*/

SEC("tp_btf/sys_enter")
int BPF_PROG(io_uring_enter_e,
struct pt_regs *regs,
long id)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, IO_URING_ENTER_E_SIZE))
{
return 0;
}

ringbuf__store_event_header(&ringbuf, PPME_SYSCALL_IO_URING_ENTER_E);

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

// Here we have no parameters to collect.

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

ringbuf__submit_event(&ringbuf);

return 0;
}

/*=============================== ENTER EVENT ===========================*/

/*=============================== EXIT EVENT ===========================*/

SEC("tp_btf/sys_exit")
int BPF_PROG(io_uring_enter_x,
struct pt_regs *regs,
long ret)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, IO_URING_ENTER_X_SIZE))
{
return 0;
}

ringbuf__store_event_header(&ringbuf, PPME_SYSCALL_IO_URING_ENTER_X);

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

/* Parameter 1: res (type: PT_ERRNO) */
ringbuf__store_s64(&ringbuf, ret);

/* Parameter 2: fd (type: PT_FD) */
s32 fd = (s32)extract__syscall_argument(regs, 0);
ringbuf__store_s64(&ringbuf, (s64)fd);

/* Parameter 3: to_submit (type: PT_UINT32) */
u32 to_submit = (u32)extract__syscall_argument(regs, 1);
ringbuf__store_u32(&ringbuf, to_submit);

/* Parameter 4: min_complete (type: PT_UINT32) */
u32 min_complete = (u32)extract__syscall_argument(regs, 2);
ringbuf__store_u32(&ringbuf, min_complete);

/* Parameter 5: flags (type: PT_FLAGS32) */
u32 flags = (u32)extract__syscall_argument(regs, 3);
ringbuf__store_u32(&ringbuf, io_uring_enter_flags_to_scap(flags));

/* Parameter 6: sig (type: PT_SIGSET) */
/* This is unclear, why we store only the first 32 bit? this is a pointer!
* It could be also a pointer to a `struct io_uring_getevents_args`.
*/
u32 sig = (u32)extract__syscall_argument(regs, 4);
ringbuf__store_u32(&ringbuf, sig);

/// TODO: We miss the last parameter `size_t argsz`
/// we need to implement it in all our drivers

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

ringbuf__submit_event(&ringbuf);

return 0;
}

/*=============================== EXIT EVENT ===========================*/
44 changes: 22 additions & 22 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -5175,45 +5175,45 @@ int f_sys_io_uring_setup_x (struct event_filler_arguments *args)
return add_sentinel(args);
}

int f_sys_io_uring_enter_x (struct event_filler_arguments *args)
int f_sys_io_uring_enter_x(struct event_filler_arguments *args)
{
int res;
unsigned long val;
int res = 0;
int32_t fd = 0;
unsigned long val = 0;

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

/* fd */
/* Parameter 2: fd (type: PT_FD) */
syscall_get_arguments_deprecated(current, args->regs, 0, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;
fd = (s32)val;
res = val_to_ring(args, (s64)fd, 0, true, 0);
CHECK_RES(res);

/* to_submit */
/* Parameter 3: to_submit (type: PT_UINT32) */
syscall_get_arguments_deprecated(current, args->regs, 1, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;
CHECK_RES(res);

/* min_complete */
/* Parameter 4: min_complete (type: PT_UINT32) */
syscall_get_arguments_deprecated(current, args->regs, 2, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;
CHECK_RES(res);

/* flags */
/* Parameter 5: flags (type: PT_FLAGS32) */
syscall_get_arguments_deprecated(current, args->regs, 3, 1, &val);
res = val_to_ring(args, io_uring_enter_flags_to_scap(val), 0, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;
CHECK_RES(res);

/* sig */
/* Parameter 6: sig (type: PT_SIGSET) */
syscall_get_arguments_deprecated(current, args->regs, 4, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;
CHECK_RES(res);

/// TODO: We miss the last parameter `size_t argsz`
/// we need to implement it in all our drivers

return add_sentinel(args);
}
Expand Down
46 changes: 46 additions & 0 deletions test/drivers/test_suites/syscall_enter_suite/io_uring_enter_e.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "../../event_class/event_class.h"

#if defined(__NR_io_uring_enter)

#include <linux/io_uring.h>

TEST(SyscallEnter, io_uring_enterE)
{
auto evt_test = get_syscall_event_test(__NR_io_uring_enter, ENTER_EVENT);

evt_test->enable_capture();

/*=============================== TRIGGER SYSCALL ===========================*/

int32_t fd = -1;
uint32_t to_submit = 10;
uint32_t min_complete = 20;
uint32_t flags = IORING_ENTER_EXT_ARG;
const void* argp = NULL;
size_t argsz = 7;
assert_syscall_state(SYSCALL_FAILURE, "io_uring_enter", syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, argp, argsz));

/*=============================== TRIGGER SYSCALL ===========================*/

evt_test->disable_capture();

evt_test->assert_event_presence();

if(HasFatalFailure())
{
return;
}

evt_test->parse_event();

evt_test->assert_header();

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

// Here we have no parameters to assert.

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

evt_test->assert_num_params_pushed(0);
}
#endif
64 changes: 64 additions & 0 deletions test/drivers/test_suites/syscall_exit_suite/io_uring_enter_x.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "../../event_class/event_class.h"

#if defined(__NR_io_uring_enter) && defined(__NR_close)

#include <linux/io_uring.h>

TEST(SyscallExit, io_uring_enterX)
{
auto evt_test = get_syscall_event_test(__NR_io_uring_enter, EXIT_EVENT);

evt_test->enable_capture();

/*=============================== TRIGGER SYSCALL ===========================*/

int32_t fd = -1;
uint32_t to_submit = 10;
uint32_t min_complete = 20;
uint32_t flags = IORING_ENTER_EXT_ARG;
const void* argp = NULL;
size_t argsz = 7;
assert_syscall_state(SYSCALL_FAILURE, "io_uring_enter", syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags, argp, argsz));
int64_t errno_value = -errno;

/*=============================== TRIGGER SYSCALL ===========================*/

evt_test->disable_capture();

evt_test->assert_event_presence();

if(HasFatalFailure())
{
return;
}

evt_test->parse_event();

evt_test->assert_header();

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

/* Parameter 1: res (type: PT_ERRNO) */
evt_test->assert_numeric_param(1, (int64_t)errno_value);

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

/* Parameter 3: to_submit (type: PT_UINT32) */
evt_test->assert_numeric_param(3, (uint32_t)to_submit);

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

/* Parameter 5: flags (type: PT_FLAGS32) */
evt_test->assert_numeric_param(5, (uint32_t)PPM_IORING_ENTER_EXT_ARG);

/* Parameter 6: sig (type: PT_SIGSET) */
/* These are the first 32 bit of a pointer so in this case all zeros */
evt_test->assert_numeric_param(6, (uint32_t)0);

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

evt_test->assert_num_params_pushed(6);
}
#endif
2 changes: 2 additions & 0 deletions userspace/libpman/src/events_prog_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,8 @@ static const char* event_prog_names[PPM_EVENT_MAX] = {
[PPME_SYSCALL_MLOCKALL_X] = "mlockall_x",
[PPME_SYSCALL_MUNLOCKALL_E] = "munlockall_e",
[PPME_SYSCALL_MUNLOCKALL_X] = "munlockall_x",
[PPME_SYSCALL_IO_URING_ENTER_E] = "io_uring_enter_e",
[PPME_SYSCALL_IO_URING_ENTER_X] = "io_uring_enter_x",
};

/* Some events can require more than one bpf program to collect all the data. */
Expand Down

0 comments on commit 24403b5

Please sign in to comment.