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

new(driver): update exit events PPME_SOCKET_SOCKET_X with enter params #2206

Merged
merged 1 commit into from
Dec 18, 2024
Merged
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
2 changes: 1 addition & 1 deletion driver/SCHEMA_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.0
3.3.0
22 changes: 16 additions & 6 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4678,11 +4678,9 @@ FILLER(sys_semop_x, true) {
}

FILLER(sys_socket_x, true) {
long retval;
int res;

retval = bpf_syscall_get_retval(data->ctx);
res = bpf_push_s64_to_ring(data, retval);
/* Parameter 1: fd (type: PT_FD)*/
long retval = bpf_syscall_get_retval(data->ctx);
int res = bpf_push_s64_to_ring(data, retval);
CHECK_RES(res);

if(retval >= 0 && !data->settings->socket_file_ops) {
Expand All @@ -4695,7 +4693,19 @@ FILLER(sys_socket_x, true) {
}
}

return res;
/* Parameter 2: domain (type: PT_ENUMFLAGS32) */
uint8_t domain = (uint8_t)bpf_syscall_get_argument(data, 0);
res = bpf_push_u32_to_ring(data, domain);
CHECK_RES(res);

/* Parameter 3: type (type: PT_UINT32) */
uint32_t type = (uint32_t)bpf_syscall_get_argument(data, 1);
res = bpf_push_u32_to_ring(data, type);
CHECK_RES(res);

/* Parameter 4: proto (type: PT_UINT32) */
uint32_t proto = (uint32_t)bpf_syscall_get_argument(data, 2);
return bpf_push_u32_to_ring(data, proto);
}

FILLER(sys_flock_e, true) {
Expand Down
11 changes: 7 additions & 4 deletions driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,19 @@ const struct ppm_event_info g_event_info[] = {
[PPME_PROCEXIT_X] = {"NA", EC_UNKNOWN, EF_UNUSED | EF_OLD_VERSION, 0},
[PPME_SOCKET_SOCKET_E] = {"socket",
EC_NET | EC_SYSCALL,
EF_CREATES_FD | EF_MODIFIES_STATE,
EF_CREATES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
3,
{{"domain", PT_ENUMFLAGS32, PF_DEC, socket_families},
{"type", PT_UINT32, PF_DEC},
{"proto", PT_UINT32, PF_DEC}}},
[PPME_SOCKET_SOCKET_X] = {"socket",
EC_NET | EC_SYSCALL,
EF_CREATES_FD | EF_MODIFIES_STATE,
1,
{{"fd", PT_FD, PF_DEC}}},
EF_CREATES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
4,
{{"fd", PT_FD, PF_DEC},
{"domain", PT_ENUMFLAGS32, PF_DEC, socket_families},
{"type", PT_UINT32, PF_DEC},
{"proto", PT_UINT32, PF_DEC}}},
[PPME_SOCKET_BIND_E] = {"bind",
EC_NET | EC_SYSCALL,
EF_USES_FD | EF_MODIFIES_STATE | EF_TMP_CONVERTER_MANAGED,
Expand Down
2 changes: 0 additions & 2 deletions driver/fillers_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ or GPL2.txt for full copies of the license.
#define FILLER_REF(x) 0, PPM_FILLER_##x
#endif /* __KERNEL__ */

#define f_sys_socket_x f_sys_single_x

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
Expand Down
2 changes: 1 addition & 1 deletion driver/modern_bpf/definitions/events_dimensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
#define CAPSET_E_SIZE HEADER_LEN
#define CAPSET_X_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint64_t) * 3 + PARAM_LEN * 4
#define SOCKET_E_SIZE HEADER_LEN + sizeof(uint32_t) * 3 + PARAM_LEN * 3
#define SOCKET_X_SIZE HEADER_LEN + sizeof(int64_t) + PARAM_LEN
#define SOCKET_X_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint32_t) * 3 + PARAM_LEN * 4
Copy link
Contributor

Choose a reason for hiding this comment

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

I am still looking for a way to automatically declare these ones 🤣 perhaps some constexpr magic?

#define SOCKETPAIR_E_SIZE HEADER_LEN + sizeof(uint32_t) * 3 + PARAM_LEN * 3
#define SOCKETPAIR_X_SIZE HEADER_LEN + sizeof(int64_t) * 3 + sizeof(uint64_t) * 2 + PARAM_LEN * 5
#define ACCEPT_E_SIZE HEADER_LEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int BPF_PROG(socket_x, struct pt_regs *regs, long ret) {

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

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

/* Just called once by our scap process */
Expand All @@ -85,6 +85,22 @@ int BPF_PROG(socket_x, struct pt_regs *regs, long ret) {
}
}

/* Collect parameters at the beginning so we can easily manage socketcalls */
unsigned long args[3] = {0};
extract__network_args(args, 3, regs);

/* Parameter 2: domain (type: PT_ENUMFLAGS32) */
uint8_t domain = (uint8_t)args[0];
ringbuf__store_u32(&ringbuf, (uint32_t)socket_family_to_scap(domain));

/* Parameter 3: type (type: PT_UINT32) */
uint32_t type = (uint32_t)args[1];
ringbuf__store_u32(&ringbuf, type);

/* Parameter 4: proto (type: PT_UINT32) */
uint32_t proto = (uint32_t)args[2];
ringbuf__store_u32(&ringbuf, proto);

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

ringbuf__submit_event(&ringbuf);
Expand Down
28 changes: 28 additions & 0 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -6671,6 +6671,34 @@ int f_sys_close_x(struct event_filler_arguments *args) {
return add_sentinel(args);
}

int f_sys_socket_x(struct event_filler_arguments *args) {
int64_t res = 0;
int64_t retval = 0;
unsigned long val = 0;

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

/* Parameter 2: domain (type: PT_ENUMFLAGS32) */
syscall_get_arguments_deprecated(args, 0, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
CHECK_RES(res);

/* Parameter 3: type (type: PT_UINT32) */
syscall_get_arguments_deprecated(args, 1, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
CHECK_RES(res);

/* Parameter 4: proto (type: PT_UINT32) */
syscall_get_arguments_deprecated(args, 2, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
CHECK_RES(res);

return add_sentinel(args);
}

int f_sys_bpf_e(struct event_filler_arguments *args) {
int res = 0;
int32_t cmd = 0;
Expand Down
2 changes: 1 addition & 1 deletion driver/ppm_flag_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ or GPL2.txt for full copies of the license.
#define PPM_MS_MGC_MSK 0xffff0000
#define PPM_MS_MGC_VAL 0xC0ED0000

/* Check if the res is different from `PPM_SUCCCES` */
/* Check if the res is different from `PPM_SUCCESS` */
#define CHECK_RES(x) \
if(unlikely(x != PPM_SUCCESS)) { \
return x; \
Expand Down
19 changes: 14 additions & 5 deletions test/drivers/test_suites/syscall_exit_suite/socket_x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ TEST(SyscallExit, socketX) {

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

int domain = -1;
int type = -1;
int protocol = -1;
int domain = 0;
int type = SOCK_RAW;
int protocol = PF_INET;

/* Here we need to call the `socket` from a child because the main process throws a `socket`
* syscall to calibrate the socket file options if we are using the bpf probe.
Expand Down Expand Up @@ -48,7 +48,7 @@ TEST(SyscallExit, socketX) {
}

/* This is the errno value we expect from the `socket` call. */
int64_t errno_value = -EINVAL;
int64_t errno_value = -EAFNOSUPPORT;

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

Expand All @@ -69,8 +69,17 @@ TEST(SyscallExit, socketX) {
/* Parameter 1: res (type: PT_ERRNO)*/
evt_test->assert_numeric_param(1, (int64_t)errno_value);

/* Parameter 2: domain (type: PT_ENUMFLAGS32) */
evt_test->assert_numeric_param(2, (uint32_t)domain);

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

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

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

evt_test->assert_num_params_pushed(1);
evt_test->assert_num_params_pushed(4);
}
#endif
2 changes: 1 addition & 1 deletion test/e2e/tests/test_network/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def expected_events(origin: dict, destination: dict) -> list:
"proc.exe": "curl",
}, {
"container.id": origin['id'],
"evt.args": "fd=3(<4>)",
"evt.args": "fd=3(<4>) domain=2(AF_INET) type=1 proto=0",
"evt.category": "net",
"evt.type": "socket",
"fd.name": "",
Expand Down
48 changes: 48 additions & 0 deletions test/libscap/test_suites/engines/savefile/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,51 @@ TEST_F(convert_event_test, PPME_SOCKET_BIND_X_to_3_params_with_enter) {
scap_const_sized_buffer{&sockaddr, sizeof(sockaddr)},
fd));
}

////////////////////////////
// SOCKET
////////////////////////////

TEST_F(convert_event_test, PPME_SOCKET_SOCKET_E_store) {
uint64_t ts = 12;
int64_t tid = 25;
uint32_t domain = 89;
uint32_t type = 89;
uint32_t proto = 89;

auto evt = create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_E, 3, domain, type, proto);
assert_single_conversion_skip(evt);
assert_event_storage_presence(evt);
}

TEST_F(convert_event_test, PPME_SOCKET_SOCKET_X_to_4_params_no_enter) {
uint64_t ts = 12;
int64_t tid = 25;

int64_t fd = 23;
uint32_t domain = 0;
uint32_t type = 0;
uint32_t proto = 0;

assert_single_conversion_success(
conversion_result::CONVERSION_COMPLETED,
create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_X, 1, fd),
create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_X, 4, fd, domain, type, proto));
}

TEST_F(convert_event_test, PPME_SOCKET_SOCKET_X_to_4_params_with_enter) {
uint64_t ts = 12;
int64_t tid = 25;
int64_t fd = 23;
uint32_t domain = 89;
uint32_t type = 87;
uint32_t proto = 86;

auto evt = create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_E, 3, domain, type, proto);
assert_single_conversion_skip(evt);

assert_single_conversion_success(
conversion_result::CONVERSION_COMPLETED,
create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_X, 1, fd),
create_safe_scap_event(ts, tid, PPME_SOCKET_SOCKET_X, 4, fd, domain, type, proto));
}
15 changes: 13 additions & 2 deletions userspace/libscap/engine/gvisor/fillers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,19 @@ int32_t fill_event_socket_e(scap_sized_buffer scap_buf,
int32_t fill_event_socket_x(scap_sized_buffer scap_buf,
size_t* event_size,
char* scap_err,
int64_t fd) {
return scap_event_encode_params(scap_buf, event_size, scap_err, PPME_SOCKET_SOCKET_X, 1, fd);
int64_t fd,
uint32_t domain,
uint32_t type,
uint32_t protocol) {
return scap_event_encode_params(scap_buf,
event_size,
scap_err,
PPME_SOCKET_SOCKET_X,
4,
fd,
domain,
type,
protocol);
}

// PPME_SYSCALL_CHDIR_E
Expand Down
5 changes: 4 additions & 1 deletion userspace/libscap/engine/gvisor/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,10 @@ int32_t fill_event_socket_e(scap_sized_buffer scap_buf,
int32_t fill_event_socket_x(scap_sized_buffer scap_buf,
size_t* event_size,
char* scap_err,
int64_t fd);
int64_t fd,
uint32_t domain,
uint32_t type,
uint32_t protocol);

int32_t fill_event_chdir_e(scap_sized_buffer scap_buf, size_t* event_size, char* scap_err);

Expand Down
12 changes: 8 additions & 4 deletions userspace/libscap/engine/gvisor/parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,10 +743,14 @@ static parse_result parse_socket(uint32_t id,
}

if(gvisor_evt.has_exit()) {
ret.status = scap_gvisor::fillers::fill_event_socket_x(scap_buf,
&ret.size,
scap_err,
gvisor_evt.exit().result());
ret.status = scap_gvisor::fillers::fill_event_socket_x(
scap_buf,
&ret.size,
scap_err,
gvisor_evt.exit().result(),
socket_family_to_scap(gvisor_evt.domain()),
gvisor_evt.type(),
gvisor_evt.protocol());
} else {
ret.status = scap_gvisor::fillers::fill_event_socket_e(
scap_buf,
Expand Down
9 changes: 9 additions & 0 deletions userspace/libscap/engine/savefile/converter/table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,16 @@ const std::unordered_map<conversion_key, conversion_info> g_conversion_table = {
.instrs({{C_INSTR_FROM_ENTER, 0},
{C_INSTR_FROM_ENTER, 1},
{C_INSTR_FROM_ENTER, 2}})},
/*====================== BIND ======================*/
{conversion_key{PPME_SOCKET_BIND_E, 1}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SOCKET_BIND_X, 2},
conversion_info().action(C_ACTION_ADD_PARAMS).instrs({{C_INSTR_FROM_ENTER, 0}})},
/*====================== SOCKET ======================*/
{conversion_key{PPME_SOCKET_SOCKET_E, 3}, conversion_info().action(C_ACTION_STORE)},
{conversion_key{PPME_SOCKET_SOCKET_X, 1},
conversion_info()
.action(C_ACTION_ADD_PARAMS)
.instrs({{C_INSTR_FROM_ENTER, 0},
{C_INSTR_FROM_ENTER, 1},
{C_INSTR_FROM_ENTER, 2}})},
};
32 changes: 10 additions & 22 deletions userspace/libsinsp/parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ void sinsp_parser::process_event(sinsp_evt *evt) {
case PPME_SYSCALL_OPENAT_E:
case PPME_SYSCALL_OPENAT_2_E:
case PPME_SYSCALL_OPENAT2_E:
case PPME_SOCKET_SOCKET_E:
case PPME_SYSCALL_EVENTFD_E:
case PPME_SYSCALL_EVENTFD2_E:
case PPME_SYSCALL_CHDIR_E:
Expand Down Expand Up @@ -2592,10 +2591,12 @@ inline void sinsp_parser::add_socket(sinsp_evt *evt,
#endif
domain != 17) // AF_PACKET, used for packet capture
{
//
// IPv6 will go here
//
ASSERT(false);
// A possible case in which we enter here is when we reproduce an old scap-file like
// `scap_2013` in our tests. In this case, we have only the exit event of the socket
// `evt_num=5` because we have just started the capture so we lost the enter event. The
// result produced by our scap-file converter is a socket with (domain=0, type=0,
// protocol=0).
fdi->m_type = SCAP_FD_UNKNOWN;
}
}

Expand Down Expand Up @@ -2666,20 +2667,14 @@ inline void sinsp_parser::infer_sendto_fdinfo(sinsp_evt *const evt) {
}

void sinsp_parser::parse_socket_exit(sinsp_evt *evt) {
int64_t fd;
uint32_t domain;
uint32_t type;
uint32_t protocol;
sinsp_evt *enter_evt = &m_tmp_evt;

//
// NOTE: we don't check the return value of get_param() because we know the arguments we need
// are there.
// XXX this extraction would be much faster if we parsed the event manually to extract the
// parameters in one scan. We don't care too much because we assume that we get here
// seldom enough that saving few tens of CPU cycles is not important.
//
fd = evt->get_syscall_return_value();
int64_t fd = evt->get_syscall_return_value();

if(fd < 0) {
//
Expand All @@ -2692,19 +2687,12 @@ void sinsp_parser::parse_socket_exit(sinsp_evt *evt) {
return;
}

//
// Load the enter event so we can access its arguments
//
if(!retrieve_enter_event(enter_evt, evt)) {
return;
}

//
// Extract the arguments
//
domain = enter_evt->get_param(0)->as<uint32_t>();
type = enter_evt->get_param(1)->as<uint32_t>();
protocol = enter_evt->get_param(2)->as<uint32_t>();
uint32_t domain = evt->get_param(1)->as<uint32_t>();
uint32_t type = evt->get_param(2)->as<uint32_t>();
uint32_t protocol = evt->get_param(3)->as<uint32_t>();

//
// Allocate a new fd descriptor, populate it and add it to the thread fd table
Expand Down
Loading
Loading