Skip to content

Commit

Permalink
new: support send syscall
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
  • Loading branch information
Andreagit97 authored and poiana committed Mar 13, 2023
1 parent 9f791d5 commit 94b7f87
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 72 deletions.
45 changes: 11 additions & 34 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1603,7 +1603,7 @@ static __always_inline int f_sys_send_e_common(struct filler_data *data, int fd)
/*
* fd
*/
res = bpf_val_to_ring(data, fd);
res = bpf_val_to_ring(data, (s64)fd);
if (res != PPM_SUCCESS)
return res;

Expand Down Expand Up @@ -1689,42 +1689,19 @@ FILLER(sys_sendto_e, true)

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

/*
* res
*/
retval = bpf_syscall_get_retval(data->ctx);
res = bpf_val_to_ring_type(data, retval, PT_ERRNO);
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_type(data, retval, PT_ERRNO);
CHECK_RES(res);

/*
* data
/* 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.
*/
if (retval < 0) {
/*
* The operation failed, return an empty buffer
*/
val = 0;
bufsize = 0;
} else {
val = bpf_syscall_get_argument(data, 1);

/*
* The return value can be lower than the value provided by the user,
* and we take that into account.
*/
bufsize = retval;
}

unsigned long bytes_to_read = retval > 0 ? retval : bpf_syscall_get_argument(data, 2);
unsigned long sent_data_pointer = bpf_syscall_get_argument(data, 1);
data->fd = bpf_syscall_get_argument(data, 0);
res = __bpf_val_to_ring(data, val, bufsize, PT_BYTEBUF, -1, true, USER);

return res;
return __bpf_val_to_ring(data, sent_data_pointer, bytes_to_read, PT_BYTEBUF, -1, true, USER);
}

FILLER(sys_execve_e, true)
Expand Down
1 change: 1 addition & 0 deletions driver/modern_bpf/definitions/events_dimensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@
#define BRK_X_SIZE HEADER_LEN + sizeof(uint64_t) + sizeof(uint32_t) * 3 + PARAM_LEN * 4
#define GETRLIMIT_E_SIZE HEADER_LEN + sizeof(uint8_t) + PARAM_LEN
#define GETRLIMIT_X_SIZE HEADER_LEN + sizeof(int64_t) * 3 + PARAM_LEN * 3
#define SEND_E_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint32_t) + PARAM_LEN * 2
#define NANOSLEEP_E_SIZE HEADER_LEN + sizeof(uint64_t) + PARAM_LEN
#define NANOSLEEP_X_SIZE HEADER_LEN + sizeof(int64_t) + PARAM_LEN

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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/variable_size_event.h>
#include <helpers/interfaces/fixed_size_event.h>

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

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

ringbuf__store_event_header(&ringbuf, PPME_SOCKET_SEND_E);

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

/* Collect parameters at the beginning to manage socketcalls */
unsigned long args[3];
extract__network_args(args, 3, regs);

/* Parameter 1: fd (type: PT_FD) */
s32 fd = (s32)args[0];
ringbuf__store_s64(&ringbuf, (s64)fd);

/* Parameter 2: size (type: PT_UINT32) */
u32 size = (u32)args[2];
ringbuf__store_u32(&ringbuf, size);

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

ringbuf__submit_event(&ringbuf);

return 0;
}

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

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

SEC("tp_btf/sys_exit")
int BPF_PROG(send_x,
struct pt_regs *regs,
long ret)
{
struct auxiliary_map *auxmap = auxmap__get();
if(!auxmap)
{
return 0;
}

auxmap__preload_event_header(auxmap, PPME_SOCKET_SEND_X);

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

/* Parameter 1: res (type: PT_ERRNO) */
auxmap__store_s64_param(auxmap, ret);

/* Collect parameters at the beginning to manage socketcalls */
unsigned long args[3];
extract__network_args(args, 3, regs);

unsigned long bytes_to_read = ret > 0 ? ret : args[2];
unsigned long snaplen = maps__get_snaplen();
if(bytes_to_read > snaplen)
{
bytes_to_read = snaplen;
}

/* Parameter 2: data (type: PT_BYTEBUF) */
unsigned long sent_data_pointer = args[1];
auxmap__store_bytebuf_param(auxmap, sent_data_pointer, bytes_to_read, USER);

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

auxmap__finalize_event_header(auxmap);

auxmap__submit_event(auxmap);

return 0;
}

/*=============================== EXIT EVENT ===========================*/
48 changes: 20 additions & 28 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -2411,6 +2411,7 @@ int f_sys_send_x(struct event_filler_arguments *args)
int res;
int64_t retval;
unsigned long bufsize;
unsigned long sent_data_pointer;

/*
* Retrieve the FD. It will be used for dynamic snaplen calculation.
Expand All @@ -2424,42 +2425,33 @@ int f_sys_send_x(struct event_filler_arguments *args)

args->fd = (int)val;

/*
* res
*/
/* 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);
if (unlikely(res != PPM_SUCCESS))
return res;
CHECK_RES(res);

/*
* data
/* 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.
*/
if (retval < 0) {
/*
* The operation failed, return an empty buffer
*/
val = 0;
bufsize = 0;
} else {
if (!args->is_socketcall)
syscall_get_arguments_deprecated(current, args->regs, 1, 1, &val);
if (!args->is_socketcall)
syscall_get_arguments_deprecated(current, args->regs, 1, 1, &val);
#ifndef UDIG
else
val = args->socketcall_args[1];
else
val = args->socketcall_args[1];
#endif

/*
* The return value can be lower than the value provided by the user,
* and we take that into account.
*/
bufsize = retval;
}
sent_data_pointer = val;

if (!args->is_socketcall)
syscall_get_arguments_deprecated(current, args->regs, 2, 1, &val);
#ifndef UDIG
else
val = args->socketcall_args[2];
#endif
bufsize = retval > 0 ? retval : val;

args->enforce_snaplen = true;
res = val_to_ring(args, val, bufsize, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;
res = val_to_ring(args, sent_data_pointer, bufsize, true, 0);
CHECK_RES(res);

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

#ifdef __NR_send
TEST(SyscallEnter, sendE)
{
auto evt_test = get_syscall_event_test(__NR_send, ENTER_EVENT);

evt_test->enable_capture();

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

int32_t mock_fd = -1;
char mock_buf[8];
size_t mock_count = 4096;
int flags = 0;
assert_syscall_state(SYSCALL_FAILURE, "send", syscall(__NR_send, mock_fd, (void *)(mock_buf), mock_count, flags));

/*=============================== 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: fd (type: PT_FD) */
evt_test->assert_numeric_param(1, (int64_t)mock_fd);

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

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

evt_test->assert_num_params_pushed(2);
}
#endif
58 changes: 54 additions & 4 deletions test/drivers/test_suites/syscall_enter_suite/socketcall_e.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,6 @@ TEST(SyscallEnter, socketcall_acceptE)

#endif /* __NR_accept || __s390x__ */


#ifdef __NR_accept4

TEST(SyscallEnter, socketcall_accept4E)
Expand Down Expand Up @@ -553,7 +552,7 @@ TEST(SyscallEnter, socketcall_socketpairE)
int domain = PF_LOCAL;
int type = SOCK_STREAM;
int protocol = 0;
int32_t* fds = NULL;
int32_t *fds = NULL;

unsigned long args[4] = {0};
args[0] = domain;
Expand Down Expand Up @@ -683,7 +682,7 @@ TEST(SyscallEnter, socketcall_sendmsgE)
struct iovec iov[3];
memset(&send_msg, 0, sizeof(send_msg));
memset(iov, 0, sizeof(iov));
send_msg.msg_name = (struct sockaddr*)&server_addr;
send_msg.msg_name = (struct sockaddr *)&server_addr;
send_msg.msg_namelen = sizeof(server_addr);
char sent_data_1[FIRST_MESSAGE_LEN] = "hey! there is a first message here.";
char sent_data_2[SECOND_MESSAGE_LEN] = "hey! there is a second message here.";
Expand Down Expand Up @@ -854,7 +853,7 @@ TEST(SyscallEnter, socketcall_setsockoptE)
int socket_fd = 0;
int level = 0;
int option_name = 0;
const void* option_value = NULL;
const void *option_value = NULL;
socklen_t option_len = 0;

unsigned long args[5] = {0};
Expand Down Expand Up @@ -890,4 +889,55 @@ TEST(SyscallEnter, socketcall_setsockoptE)
}
#endif

#ifdef __NR_send

TEST(SyscallEnter, socketcall_sendE)
{
auto evt_test = get_syscall_event_test(__NR_send, ENTER_EVENT);

evt_test->enable_capture();

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

int32_t mock_fd = -1;
char mock_buf[8];
size_t mock_count = 4096;
int flags = 0;

unsigned long args[4] = {0};
args[0] = mock_fd;
args[1] = (unsigned long)mock_buf;
args[2] = mock_count;
args[3] = (unsigned long)flags;
assert_syscall_state(SYSCALL_FAILURE, "send", syscall(__NR_socketcall, SYS_SEND, args));

/*=============================== 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: fd (type: PT_FD) */
evt_test->assert_numeric_param(1, (int64_t)mock_fd);

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

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

evt_test->assert_num_params_pushed(2);
}
#endif

#endif /* __NR_socketcall */
Loading

0 comments on commit 94b7f87

Please sign in to comment.