Skip to content

Commit

Permalink
new: extend SOCKET_X
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 authored and poiana committed Dec 18, 2024
1 parent 199a439 commit b15675b
Show file tree
Hide file tree
Showing 26 changed files with 357 additions and 275 deletions.
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
#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

0 comments on commit b15675b

Please sign in to comment.