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

Feat: Support for pidfd_getfd syscall #1145

Merged
merged 5 commits into from
Jun 22, 2023
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 @@
2.4.1
2.5.0
31 changes: 31 additions & 0 deletions driver/bpf/fillers.h
Rohith-Raju marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6762,4 +6762,35 @@ FILLER(sys_memfd_create_x,true)
return bpf_push_u32_to_ring(data, flags);
}

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

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

/* Parameter 2: pidfd (type: PT_FD) */
s32 pidfd = (s32)bpf_syscall_get_argument(data, 0);
res = bpf_push_s64_to_ring(data, (s64)pidfd);
CHECK_RES(res);

/* Parameter 3: targetfd (type: PT_FD) */
s32 targetfd = bpf_syscall_get_argument(data, 1);
res = bpf_push_s64_to_ring(data, (s64)targetfd);
CHECK_RES(res);

/* Parameter 4: flags (type: PT_FLAGS32) */
val = bpf_syscall_get_argument(data,2);
/*
The flags argument is reserved for future use. Currently, it must be specified as 0.
See https://elixir.bootlin.com/linux/latest/source/kernel/pid.c#L709
*/
return bpf_push_u32_to_ring(data, val);
}

#endif
2 changes: 1 addition & 1 deletion driver/event_stats.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

/* These numbers must be updated when we add new events in the event table */
#define SYSCALL_EVENTS_NUM 358
#define SYSCALL_EVENTS_NUM 360
#define TRACEPOINT_EVENTS_NUM 6
#define METAEVENTS_NUM 20
#define PLUGIN_EVENTS_NUM 1
Expand Down
2 changes: 2 additions & 0 deletions driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ const struct ppm_event_info g_event_info[] = {
[PPME_ASYNCEVENT_X] = {"NA", EC_UNKNOWN, EF_UNUSED, 0},
[PPME_SYSCALL_MEMFD_CREATE_E] = {"memfd_create", EC_MEMORY | EC_SYSCALL, EF_CREATES_FD, 0},
[PPME_SYSCALL_MEMFD_CREATE_X] = {"memfd_create", EC_MEMORY | EC_SYSCALL, EF_CREATES_FD, 3, {{"fd",PT_FD,PF_DEC},{"name", PT_CHARBUF, PF_NA},{"flags", PT_FLAGS32, PF_HEX, memfd_create_flags} } },
[PPME_SYSCALL_PIDFD_GETFD_E] = {"pidfd_getfd", EC_PROCESS | EC_SYSCALL, EF_CREATES_FD , 0},
[PPME_SYSCALL_PIDFD_GETFD_X] = {"pidfd_getfd", EC_PROCESS | EC_SYSCALL, EF_CREATES_FD , 4, {{"fd", PT_FD, PF_DEC}, {"pid_fd", PT_FD, PF_DEC}, {"target_fd", PT_FD, PF_DEC}, {"flags", PT_FLAGS32, PF_HEX}}}
};

// We don't need this check in kmod (this source file is included during kmod compilation!)
Expand Down
4 changes: 3 additions & 1 deletion driver/fillers_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,5 +339,7 @@ const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
[PPME_SYSCALL_PRCTL_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_PRCTL_X] = {FILLER_REF(sys_prctl_x)},
[PPME_SYSCALL_MEMFD_CREATE_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_MEMFD_CREATE_X] = {FILLER_REF(sys_memfd_create_x)}
[PPME_SYSCALL_MEMFD_CREATE_X] = {FILLER_REF(sys_memfd_create_x)},
[PPME_SYSCALL_PIDFD_GETFD_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_PIDFD_GETFD_X] = {FILLER_REF(sys_pidfd_getfd_x)}
};
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 @@ -237,6 +237,8 @@
#define SIGNALFD4_X_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint16_t) + 2 * PARAM_LEN
#define PRCTL_E_SIZE HEADER_LEN
#define MEMFD_CREATE_E_SIZE HEADER_LEN
#define PIDFD_GETFD_E_SIZE HEADER_LEN
#define PIDFD_GETFD_X_SIZE HEADER_LEN + sizeof(int64_t) * 3 + sizeof(uint32_t) + 4 * PARAM_LEN

/* 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,79 @@
/*
* Copyright (C) 2022 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(pidfd_getfd_e,
struct pt_regs *regs,
long id)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, ctx, PIDFD_GETFD_E_SIZE, PPME_SYSCALL_PIDFD_GETFD_E))
{
return 0;
}

ringbuf__store_event_header(&ringbuf);

/*=============================== 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(pidfd_getfd_x,
struct pt_regs *regs,
long ret)

{

struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, ctx, PIDFD_GETFD_X_SIZE, PPME_SYSCALL_PIDFD_GETFD_X))
{
return 0;
}

ringbuf__store_event_header(&ringbuf);

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

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

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

/* Parameter 3: targetfd (type: PT_FD) */
s32 targetfd = (s32)extract__syscall_argument(regs, 1);
ringbuf__store_s64(&ringbuf, (s64)targetfd);

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

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

ringbuf__submit_event(&ringbuf);

return 0;
}

/*=============================== EXIT EVENT ===========================*/
5 changes: 3 additions & 2 deletions driver/ppm_events_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,9 @@ typedef enum {
PPME_ASYNCEVENT_X = 403,
PPME_SYSCALL_MEMFD_CREATE_E = 404,
PPME_SYSCALL_MEMFD_CREATE_X = 405,
PPM_EVENT_MAX = 406
PPME_SYSCALL_PIDFD_GETFD_E = 406,
PPME_SYSCALL_PIDFD_GETFD_X = 407,
PPM_EVENT_MAX = 408
} ppm_event_code;
/*@}*/

Expand Down Expand Up @@ -2093,7 +2095,6 @@ extern const struct ppm_name_value epoll_create1_flags[];
extern const struct ppm_name_value fchownat_flags[];
extern const struct ppm_name_value prctl_options[];
extern const struct ppm_name_value memfd_create_flags[];

extern const struct ppm_param_info sockopt_dynamic_param[];
extern const struct ppm_param_info ptrace_dynamic_param[];
extern const struct ppm_param_info bpf_dynamic_param[];
Expand Down
31 changes: 31 additions & 0 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -7951,5 +7951,36 @@ int f_sys_memfd_create_x(struct event_filler_arguments *args)
res = val_to_ring(args, memfd_create_flags_to_scap(val), 0, true, 0);
CHECK_RES(res);

return add_sentinel(args);
}

int f_sys_pidfd_getfd_x(struct event_filler_arguments *args){
Rohith-Raju marked this conversation as resolved.
Show resolved Hide resolved
unsigned long val;
int res;
int retval;
s32 fd;

/* Parameter 1: ret (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: pidfd (type: PT_FD) */
syscall_get_arguments_deprecated(args, 0, 1, &val);
Rohith-Raju marked this conversation as resolved.
Show resolved Hide resolved
fd = (s32)val;
res = val_to_ring(args, (s64)fd, 0, true, 0);
CHECK_RES(res)

/* Parameter 3: targetfd (type: PT_FD) */
syscall_get_arguments_deprecated(args, 1, 1, &val);
fd = (s32)val;
res = val_to_ring(args, (s64)fd, 0, true, 0);
CHECK_RES(res)

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

return add_sentinel(args);
}
3 changes: 2 additions & 1 deletion driver/ppm_fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ or GPL2.txt for full copies of the license.
FN(sys_eventfd2_x) \
FN(sys_signalfd4_e) \
FN(sys_signalfd4_x) \
FN(sys_prctl_x) \
FN(sys_prctl_x) \
FN(sys_memfd_create_x) \
FN(sys_pidfd_getfd_x) \
FN(terminate_filler)

#define FILLER_ENUM_FN(x) PPM_FILLER_##x,
Expand Down
2 changes: 1 addition & 1 deletion driver/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ This table represents the syscalls supported by our drivers.
| pause | 🟡 |
| perf_event_open | 🟡 |
| personality | 🟡 |
| pidfd_getfd | 🟡 |
| pidfd_getfd | 🟢 |
| pidfd_open | 🟡 |
| pidfd_send_signal | 🟡 |
| pipe | 🟢 |
Expand Down
6 changes: 3 additions & 3 deletions driver/syscall_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,9 @@ const struct syscall_evt_pair g_syscall_table[SYSCALL_TABLE_SIZE] = {
#endif
#ifdef __NR_memfd_create
[__NR_memfd_create - SYSCALL_TABLE_ID0] = {UF_USED, PPME_SYSCALL_MEMFD_CREATE_E, PPME_SYSCALL_MEMFD_CREATE_X, PPM_SC_MEMFD_CREATE},
#endif
#ifdef __NR_pidfd_getfd
[__NR_pidfd_getfd - SYSCALL_TABLE_ID0] = {UF_USED, PPME_SYSCALL_PIDFD_GETFD_E, PPME_SYSCALL_PIDFD_GETFD_X, PPM_SC_PIDFD_GETFD},
#endif
[__NR_restart_syscall - SYSCALL_TABLE_ID0] = { .ppm_sc = PPM_SC_RESTART_SYSCALL },
[__NR_exit - SYSCALL_TABLE_ID0] = {.ppm_sc = PPM_SC_EXIT},
Expand Down Expand Up @@ -698,9 +701,6 @@ const struct syscall_evt_pair g_syscall_table[SYSCALL_TABLE_SIZE] = {
#ifdef __NR_kexec_file_load
[__NR_kexec_file_load - SYSCALL_TABLE_ID0] = {.ppm_sc = PPM_SC_KEXEC_FILE_LOAD},
#endif
#ifdef __NR_pidfd_getfd
[__NR_pidfd_getfd - SYSCALL_TABLE_ID0] = {.ppm_sc = PPM_SC_PIDFD_GETFD},
#endif
#ifdef __NR_pidfd_open
[__NR_pidfd_open - SYSCALL_TABLE_ID0] = {.ppm_sc = PPM_SC_PIDFD_OPEN},
#endif
Expand Down
39 changes: 39 additions & 0 deletions test/drivers/test_suites/syscall_enter_suite/pidfd_getfd_e.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "../../event_class/event_class.h"

#ifdef __NR_pidfd_getfd

TEST(SyscallEnter, pidfd_getfdE)
{
auto evt_test = get_syscall_event_test(__NR_pidfd_getfd, ENTER_EVENT);

evt_test->enable_capture();

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

int pidfd = 0;
int targetfd = 0;
int flags = 0;
assert_syscall_state(SYSCALL_FAILURE, "pidfd_getfd", syscall(__NR_pidfd_getfd, pidfd, targetfd, 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 ===========================*/

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

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

#ifdef __NR_pidfd_getfd

TEST(SyscallExit, pidfd_getfdX)
{
auto evt_test = get_syscall_event_test(__NR_pidfd_getfd, EXIT_EVENT);

evt_test->enable_capture();


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

int pid_fd = -1;
int target_fd = -1;
uint32_t flags = 1;
int64_t errno_value = -EINVAL;

/*
The syscall should fail when flag is not equal to zero
See https://elixir.bootlin.com/linux/latest/source/kernel/pid.c#L731
*/

assert_syscall_state(SYSCALL_FAILURE, "pidfd_getfd", syscall(__NR_pidfd_getfd, pid_fd, target_fd, 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: res (type: PT_ERRNO)*/
evt_test->assert_numeric_param(1, (int64_t)errno_value);

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

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

/* Parameter 4: flags (type: PT_FLAGS32)*/
evt_test->assert_numeric_param(4, flags);

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

evt_test->assert_num_params_pushed(4);

}
#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 @@ -314,6 +314,8 @@ static const char* event_prog_names[PPM_EVENT_MAX] = {
[PPME_SYSCALL_PRCTL_X] = "prctl_x",
[PPME_SYSCALL_MEMFD_CREATE_E] = "memfd_create_e",
[PPME_SYSCALL_MEMFD_CREATE_X] = "memfd_create_x",
[PPME_SYSCALL_PIDFD_GETFD_E] = "pidfd_getfd_e",
[PPME_SYSCALL_PIDFD_GETFD_X] = "pidfd_getfd_x",
};

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