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

Support pidfd_open syscall #1187

Merged
merged 6 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
23 changes: 23 additions & 0 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -7051,4 +7051,27 @@ FILLER(sys_pidfd_getfd_x, true)
return bpf_push_u32_to_ring(data, val);
}

FILLER(sys_pidfd_open_x, true)
{
int retval;
unsigned long val;
unsigned long res;
unsigned long flags;
Rohith-Raju marked this conversation as resolved.
Show resolved Hide resolved

/* Parameter 1: ret (type: PT_FD) */
retval = bpf_syscall_get_retval(data->ctx);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
retval = bpf_syscall_get_retval(data->ctx);
long retval = bpf_syscall_get_retval(data->ctx);

res = bpf_push_s64_to_ring(data, retval);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
res = bpf_push_s64_to_ring(data, retval);
int res = bpf_push_s64_to_ring(data, retval);

CHECK_RES(res);

/* Parameter 2: pid (type: PT_PID)*/
pid_t pid = (s32)bpf_syscall_get_argument(data, 0);
res = bpf_push_s64_to_ring(data, (s64)pid);
CHECK_RES(res);

/* Parameter 3: flags (type: PT_FLAGS32)*/
val = bpf_syscall_get_argument(data, 1);
flags = pidfd_open_flags_to_scap(val);
return bpf_push_u32_to_ring(data, flags);
Rohith-Raju marked this conversation as resolved.
Show resolved Hide resolved

}
#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 360
#define SYSCALL_EVENTS_NUM 362
#define TRACEPOINT_EVENTS_NUM 6
#define METAEVENTS_NUM 20
#define PLUGIN_EVENTS_NUM 1
Expand Down
6 changes: 4 additions & 2 deletions driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,11 @@ const struct ppm_event_info g_event_info[] = {
[PPME_ASYNCEVENT_E] = {"asyncevent", EC_OTHER | EC_METAEVENT, EF_LARGE_PAYLOAD, 3, {{"plugin_id", PT_UINT32, PF_DEC}, {"name", PT_CHARBUF, PF_NA}, {"data", PT_BYTEBUF, PF_NA} } },
[PPME_ASYNCEVENT_X] = {"NA", EC_UNKNOWN, EF_UNUSED, 0},
[PPME_SYSCALL_MEMFD_CREATE_E] = {"memfd_create", EC_MEMORY | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 0},
[PPME_SYSCALL_MEMFD_CREATE_X] = {"memfd_create", EC_MEMORY | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 3, {{"fd",PT_FD,PF_DEC},{"name", PT_CHARBUF, PF_NA},{"flags", PT_FLAGS32, PF_HEX, memfd_create_flags} } },
[PPME_SYSCALL_MEMFD_CREATE_X] = {"memfd_create", EC_MEMORY | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 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}}}
[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}}},
[PPME_SYSCALL_PIDFD_OPEN_E] = {"pidfd_open", EC_PROCESS | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 0},
[PPME_SYSCALL_PIDFD_OPEN_X] = {"pidfd_open", EC_PROCESS | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 3, {{"fd", PT_FD, PF_DEC}, {"pid", PT_PID, 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 @@ -341,5 +341,7 @@ const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
[PPME_SYSCALL_MEMFD_CREATE_E] = {FILLER_REF(sys_empty)},
[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)}
[PPME_SYSCALL_PIDFD_GETFD_X] = {FILLER_REF(sys_pidfd_getfd_x)},
[PPME_SYSCALL_PIDFD_OPEN_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_PIDFD_OPEN_X] = {FILLER_REF(sys_pidfd_open_x)}
};
5 changes: 5 additions & 0 deletions driver/flags_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -679,4 +679,9 @@ const struct ppm_name_value memfd_create_flags[] = {
{"MFD_ALLOW_SEALING",PPM_MFD_ALLOW_SEALING},
{"MFD_HUGETLB",PPM_MFD_HUGETLB},
{0,0},
};

const struct ppm_name_value pidfd_open_flags[] = {
{"PIDFD_NONBLOCK", PPM_PIDFD_NONBLOCK},
{0,0},
};
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 @@ -239,6 +239,8 @@
#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
#define PIDFD_OPEN_E_SIZE HEADER_LEN
#define PIDFD_OPEN_X_SIZE HEADER_LEN + sizeof(int64_t) * 2 + sizeof(uint32_t) + 3 * PARAM_LEN

/* Generic tracepoints events. */
#define SCHED_SWITCH_SIZE HEADER_LEN + sizeof(int64_t) + sizeof(uint64_t) * 2 + sizeof(uint32_t) * 3 + PARAM_LEN * 6
Expand Down
5 changes: 5 additions & 0 deletions driver/modern_bpf/definitions/missing_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,11 @@
# define MFD_ALLOW_SEALING 2U
# define MFD_HUGETLB 4U

//////////////////////////
// pidfd_open flags
//////////////////////////
# define PIDFD_NONBLOCK 1U
Copy link
Member

Choose a reason for hiding this comment

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

why do we use 1U here? In the kernel I found

#define PIDFD_NONBLOCK O_NONBLOCK


/*=============================== FLAGS ===========================*/

/*=============================== PROTOCOL/ADDRESS FAMILIES ===========================*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* 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_open_e,
struct pt_regs *regs,
long id)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, ctx, PIDFD_OPEN_E_SIZE, PPME_SYSCALL_PIDFD_OPEN_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_open_x,
struct pt_regs *regs,
long ret)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, ctx, PIDFD_OPEN_X_SIZE, PPME_SYSCALL_PIDFD_OPEN_X))
{
return 0;
}

ringbuf__store_event_header(&ringbuf);

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

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

/* Parameter 2: pid (type: PT_PID)*/
pid_t pid = (s32)extract__syscall_argument(regs, 0);
ringbuf__store_s64(&ringbuf, (s64)pid);

/* Parameter 3: pid (type: PT_FLAGS32)*/
u32 flags = (u32)extract__syscall_argument(regs, 1);
ringbuf__store_u32(&ringbuf, pidfd_open_flags_to_scap(flags));

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

ringbuf__submit_event(&ringbuf);

return 0;
}

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



11 changes: 10 additions & 1 deletion driver/ppm_events_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,11 @@ or GPL2.txt for full copies of the license.
#define PPM_PR_GET_SECUREBITS 27
#define PPM_PR_SET_SECUREBITS 28

/*
* pidfd_open flags
*/
#define PPM_PIDFD_NONBLOCK (1<<0)

/*
* Get/set the timerslack as used by poll/select/nanosleep
* A value of 0 means "use default"
Expand Down Expand Up @@ -1376,7 +1381,9 @@ typedef enum {
PPME_SYSCALL_MEMFD_CREATE_X = 405,
PPME_SYSCALL_PIDFD_GETFD_E = 406,
PPME_SYSCALL_PIDFD_GETFD_X = 407,
PPM_EVENT_MAX = 408
PPME_SYSCALL_PIDFD_OPEN_E = 408,
PPME_SYSCALL_PIDFD_OPEN_X = 409,
PPM_EVENT_MAX = 410
} ppm_event_code;
/*@}*/

Expand Down Expand Up @@ -2086,10 +2093,12 @@ 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_name_value pidfd_open_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[];


Copy link
Member

Choose a reason for hiding this comment

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

can we remove this?

/*!
\brief Process information as returned by the PPM_IOCTL_GET_PROCLIST IOCTL.
*/
Expand Down
29 changes: 28 additions & 1 deletion driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -8112,7 +8112,8 @@ int f_sys_memfd_create_x(struct event_filler_arguments *args)
return add_sentinel(args);
}

int f_sys_pidfd_getfd_x(struct event_filler_arguments *args){
int f_sys_pidfd_getfd_x(struct event_filler_arguments *args)
{
unsigned long val;
int res;
int retval;
Expand Down Expand Up @@ -8142,3 +8143,29 @@ int f_sys_pidfd_getfd_x(struct event_filler_arguments *args){

return add_sentinel(args);
}

int f_sys_pidfd_open_x(struct event_filler_arguments *args)
{
unsigned long val;
int res;
int retval;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int retval;
long retval;

Copy link
Member

Choose a reason for hiding this comment

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

we still need to address this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops forgot to commit 😅

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: pid (type: PT_PID) */
syscall_get_arguments_deprecated(args, 0, 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, 1, 1, &val);
res = val_to_ring(args, pidfd_open_flags_to_scap(val), 0, true, 0);
CHECK_RES(res)

return add_sentinel(args);
}
1 change: 1 addition & 0 deletions driver/ppm_fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ or GPL2.txt for full copies of the license.
FN(sys_prctl_x) \
FN(sys_memfd_create_x) \
FN(sys_pidfd_getfd_x) \
FN(sys_pidfd_open_x) \
FN(terminate_filler)

#define FILLER_ENUM_FN(x) PPM_FILLER_##x,
Expand Down
22 changes: 22 additions & 0 deletions driver/ppm_flag_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ or GPL2.txt for full copies of the license.
#include <linux/capability.h>
#include <linux/eventpoll.h>
#include <linux/prctl.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 10, 0))
#include <linux/pidfd.h>
#endif
Copy link
Member

Choose a reason for hiding this comment

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

if you accept the following suggestion we can remove this

#include "ppm.h"
#ifdef __NR_memfd_create
#include <uapi/linux/memfd.h>
Expand Down Expand Up @@ -2078,6 +2081,25 @@ static __always_inline uint32_t splice_flags_to_scap(uint32_t flags)
return res;
}

static __always_inline uint32_t pidfd_open_flags_to_scap(uint32_t flags)
{
uint32_t res = 0;
#ifdef PIDFD_NONBLOCK
if(flags & PIDFD_NONBLOCK) res |= PPM_PIDFD_NONBLOCK;
#endif

/*
PIDFD_NONBLOCK is available only on kernal versions > 5.10.00, hence used O_NONBLOCK
See https://elixir.bootlin.com/linux/v5.10.185/source/include/uapi/linux/pidfd.h#L10
*/

#ifdef O_NONBLOCK
if(flags & O_NONBLOCK) res |= PPM_PIDFD_NONBLOCK;
#endif

return res;
}
Copy link
Member

Choose a reason for hiding this comment

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

Since define PIDFD_NONBLOCK O_NONBLOCK what about doing something like this?

Suggested change
static __always_inline uint32_t pidfd_open_flags_to_scap(uint32_t flags)
{
uint32_t res = 0;
#ifdef PIDFD_NONBLOCK
if(flags & PIDFD_NONBLOCK) res |= PPM_PIDFD_NONBLOCK;
#endif
/*
PIDFD_NONBLOCK is available only on kernal versions > 5.10.00, hence used O_NONBLOCK
See https://elixir.bootlin.com/linux/v5.10.185/source/include/uapi/linux/pidfd.h#L10
*/
#ifdef O_NONBLOCK
if(flags & O_NONBLOCK) res |= PPM_PIDFD_NONBLOCK;
#endif
return res;
}
static __always_inline uint32_t pidfd_open_flags_to_scap(uint32_t flags)
{
uint32_t res = 0;
// See https://elixir.bootlin.com/linux/v5.10.185/source/include/uapi/linux/pidfd.h#L10
#ifdef O_NONBLOCK
if(flags & O_NONBLOCK) res |= PPM_PIDFD_NONBLOCK;
#endif
return res;
}

Copy link
Contributor Author

@Rohith-Raju Rohith-Raju Jul 18, 2023

Choose a reason for hiding this comment

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

Sure!! this makes sense. I thought I had to enforce pidfd_open flags


#ifdef OVERLAYFS_SUPER_MAGIC
#define PPM_OVERLAYFS_SUPER_MAGIC OVERLAYFS_SUPER_MAGIC
#else
Expand Down
2 changes: 1 addition & 1 deletion driver/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ This table represents the syscalls supported by our drivers.
| perf_event_open | 🟡 |
| personality | 🟡 |
| pidfd_getfd | 🟢 |
| pidfd_open | 🟡 |
| pidfd_open | 🟢 |
| pidfd_send_signal | 🟡 |
| pipe | 🟢 |
| pipe2 | 🟢 |
Expand Down
6 changes: 3 additions & 3 deletions driver/syscall_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,9 @@ const struct syscall_evt_pair g_syscall_table[SYSCALL_TABLE_SIZE] = {
#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_open
[__NR_pidfd_open - SYSCALL_TABLE_ID0] = {UF_USED, PPME_SYSCALL_PIDFD_OPEN_E, PPME_SYSCALL_PIDFD_OPEN_X, PPM_SC_PIDFD_OPEN},
#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
Expand Down Expand Up @@ -701,9 +704,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_open
[__NR_pidfd_open - SYSCALL_TABLE_ID0] = {.ppm_sc = PPM_SC_PIDFD_OPEN},
#endif
#ifdef __NR_pidfd_send_signal
[__NR_pidfd_send_signal - SYSCALL_TABLE_ID0] = {.ppm_sc = PPM_SC_PIDFD_SEND_SIGNAL},
#endif
Expand Down
39 changes: 39 additions & 0 deletions test/drivers/test_suites/syscall_enter_suite/pidfd_open_e.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "../../event_class/event_class.h"
#include <unistd.h>

#ifdef __NR_pidfd_open

TEST(SyscallEnter, pidfd_openE)
{
auto evt_test = get_syscall_event_test(__NR_pidfd_open, ENTER_EVENT);

evt_test->enable_capture();

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

int pid = 0;
int flags = 0;
assert_syscall_state(SYSCALL_FAILURE, "pidfd_open", syscall(__NR_pidfd_open, pid, 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
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ TEST(SyscallExit, memfd_createX_failure)

const char* name = "test";
int flags = -1;
assert_syscall_state(SYSCALL_FAILURE,"memfd_create",syscall(__NR_memfd_create,name,flags));
assert_syscall_state(SYSCALL_FAILURE, "memfd_create",syscall(__NR_memfd_create,name,flags));
int64_t errno_value = -errno;

/*=============================== TRIGGER SYSCALL ===========================*/
Expand Down
Loading
Loading