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(driver): add support for newfstatat syscall #1628

Merged
merged 6 commits into from
Jan 23, 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.
Jump to
Jump to file
Failed to load files.
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.14.0
2.15.0
26 changes: 26 additions & 0 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -7290,4 +7290,30 @@ FILLER(sys_mknodat_x, true)
uint32_t dev = bpf_syscall_get_argument(data, 3);
return bpf_push_u32_to_ring(data, bpf_encode_dev(dev));
}

FILLER(sys_newfstatat_x, true)
{
unsigned long val;

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

/* Parameter 2: fd (type: PT_FD) */
int32_t fd = (int32_t)bpf_syscall_get_argument(data, 0);
if (fd == AT_FDCWD)
fd = PPM_AT_FDCWD;
res = bpf_push_s64_to_ring(data, (int64_t)fd);
CHECK_RES(res);

/* Parameter 3: path (type: PT_RELPATH) */
val = bpf_syscall_get_argument(data, 1);
res = bpf_val_to_ring(data, val);
CHECK_RES(res);

/* Parameter 4: flags (type: PT_FLAGS32) */
uint32_t flags = bpf_syscall_get_argument(data, 3);
return bpf_push_u32_to_ring(data, newfstatat_flags_to_scap(flags));
}
#endif
2 changes: 1 addition & 1 deletion driver/event_stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ or GPL2.txt for full copies of the license.
#pragma once

/* These numbers must be updated when we add new events in the event table */
#define SYSCALL_EVENTS_NUM 370
#define SYSCALL_EVENTS_NUM 372
#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 @@ -470,6 +470,8 @@ const struct ppm_event_info g_event_info[] = {
[PPME_SYSCALL_MKNOD_X] = {"mknod", EC_OTHER | EC_SYSCALL, EF_NONE, 4, {{"res", PT_ERRNO, PF_DEC}, {"path", PT_FSPATH, PF_NA},{"mode", PT_MODE, PF_OCT, mknod_mode},{"dev", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_MKNODAT_E] = {"mknodat", EC_OTHER | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_MKNODAT_X] = {"mknodat", EC_OTHER | EC_SYSCALL, EF_USES_FD, 5, {{"res", PT_ERRNO, PF_DEC}, {"dirfd", PT_FD, PF_DEC}, {"path", PT_FSRELPATH, PF_NA, DIRFD_PARAM(1)},{"mode", PT_MODE, PF_OCT, mknod_mode},{"dev", PT_UINT32, PF_DEC}}},
[PPME_SYSCALL_NEWFSTATAT_E] = {"newfstatat", EC_FILE | EC_SYSCALL, EF_NONE, 0},
[PPME_SYSCALL_NEWFSTATAT_X] = {"newfstatat", EC_FILE | EC_SYSCALL, EF_USES_FD, 4, {{"res", PT_ERRNO, PF_DEC}, {"dirfd", PT_FD, PF_DEC}, {"path", PT_FSRELPATH, PF_NA, DIRFD_PARAM(1)}, {"flags", PT_FLAGS32, PF_HEX, newfstatat_flags}}},
};
#pragma GCC diagnostic pop

Expand Down
4 changes: 3 additions & 1 deletion driver/fillers_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
[PPME_SYSCALL_MKNOD_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_MKNOD_X] = {FILLER_REF(sys_mknod_x)},
[PPME_SYSCALL_MKNODAT_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_MKNODAT_X] = {FILLER_REF(sys_mknodat_x)}
[PPME_SYSCALL_MKNODAT_X] = {FILLER_REF(sys_mknodat_x)},
[PPME_SYSCALL_NEWFSTATAT_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_NEWFSTATAT_X] = {FILLER_REF(sys_newfstatat_x)}
};
#pragma GCC diagnostic pop
7 changes: 7 additions & 0 deletions driver/flags_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,13 @@ const struct ppm_name_value linkat_flags[] = {
{0, 0},
};

const struct ppm_name_value newfstatat_flags[] = {
{"AT_EMPTY_PATH", PPM_AT_EMPTY_PATH},
{"AT_NO_AUTOMOUNT", PPM_AT_NO_AUTOMOUNT},
{"AT_SYMLINK_NOFOLLOW", PPM_AT_SYMLINK_NOFOLLOW},
{0, 0},
};

const struct ppm_name_value chmod_mode[] = {
{"S_IXOTH", PPM_S_IXOTH},
{"S_IWOTH", PPM_S_IWOTH},
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 @@ -246,6 +246,7 @@
#define FINIT_MODULE_E_SIZE HEADER_LEN
#define MKNOD_E_SIZE HEADER_LEN
#define MKNODAT_E_SIZE HEADER_LEN
#define NEWFSTATAT_E_SIZE HEADER_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
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
/*
* 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/fixed_size_event.h>
#include <helpers/interfaces/variable_size_event.h>

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

SEC("tp_btf/sys_enter")
int BPF_PROG(newfstatat_e,
struct pt_regs *regs,
long id)
{
struct ringbuf_struct ringbuf;
if(!ringbuf__reserve_space(&ringbuf, ctx, NEWFSTATAT_E_SIZE, PPME_SYSCALL_NEWFSTATAT_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(newfstatat_x,
struct pt_regs *regs,
long ret)
{
struct auxiliary_map *auxmap = auxmap__get();
if(!auxmap)
{
return 0;
}

auxmap__preload_event_header(auxmap, PPME_SYSCALL_NEWFSTATAT_X);

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

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

/* Parameter 2: dirfd (type: PT_FD) */
int32_t dirfd = (int32_t)extract__syscall_argument(regs, 0);
if(dirfd == AT_FDCWD)
{
dirfd = PPM_AT_FDCWD;
}
auxmap__store_s64_param(auxmap, (int64_t)dirfd);

/* Parameter 3: path (type: PT_RELPATH) */
unsigned long path_pointer = extract__syscall_argument(regs, 1);
auxmap__store_charbuf_param(auxmap, path_pointer, MAX_PATH, USER);

/* Parameter 4: dev (type: PT_FLAGS32) */
uint32_t flags = (uint32_t)extract__syscall_argument(regs, 3);
auxmap__store_u32_param(auxmap, newfstatat_flags_to_scap(flags));


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

auxmap__finalize_event_header(auxmap);

auxmap__submit_event(auxmap, ctx);

return 0;
}

/*=============================== EXIT EVENT ===========================*/
12 changes: 11 additions & 1 deletion driver/ppm_events_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,13 @@ or GPL2.txt for full copies of the license.
#define PPM_AT_SYMLINK_FOLLOW 0x400
#define PPM_AT_EMPTY_PATH 0x1000

/*
* newfstatat() flags
*/
#define PPM_AT_NO_AUTOMOUNT 0x800
#define PPM_AT_SYMLINK_NOFOLLOW 0x100


/*
* rlimit resources
*/
Expand Down Expand Up @@ -1413,7 +1420,9 @@ typedef enum {
PPME_SYSCALL_MKNOD_X = 415,
PPME_SYSCALL_MKNODAT_E = 416,
PPME_SYSCALL_MKNODAT_X = 417,
PPM_EVENT_MAX = 418
PPME_SYSCALL_NEWFSTATAT_E = 418,
PPME_SYSCALL_NEWFSTATAT_X = 419,
PPM_EVENT_MAX = 420
} ppm_event_code;
/*@}*/

Expand Down Expand Up @@ -2136,6 +2145,7 @@ extern const struct ppm_name_value access_flags[];
extern const struct ppm_name_value pf_flags[];
extern const struct ppm_name_value unlinkat_flags[];
extern const struct ppm_name_value linkat_flags[];
extern const struct ppm_name_value newfstatat_flags[];
extern const struct ppm_name_value chmod_mode[];
extern const struct ppm_name_value mknod_mode[];
extern const struct ppm_name_value renameat2_flags[];
Expand Down
141 changes: 87 additions & 54 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -8011,67 +8011,100 @@ int f_sys_finit_module_x(struct event_filler_arguments *args)

int f_sys_mknod_x(struct event_filler_arguments *args)
{
unsigned long val;
int res;
long retval;
unsigned long val;
int res;
long retval;

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

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

/* Parameter 3: mode (type: PT_MODE) */
syscall_get_arguments_deprecated(args, 1, 1, &val);
res = val_to_ring(args, mknod_mode_to_scap(val), 0, false, 0);
CHECK_RES(res);
/* Parameter 3: mode (type: PT_MODE) */
syscall_get_arguments_deprecated(args, 1, 1, &val);
res = val_to_ring(args, mknod_mode_to_scap(val), 0, false, 0);
CHECK_RES(res);

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

return add_sentinel(args);
return add_sentinel(args);
}

int f_sys_mknodat_x(struct event_filler_arguments *args)
{
unsigned long val;
int res;
int32_t fd;
long retval;

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

/* Parameter 2: dirfd (type: PT_FD) */
syscall_get_arguments_deprecated(args, 0, 1, &val);
fd = (int32_t)val;
if (fd == AT_FDCWD)
fd = PPM_AT_FDCWD;
res = val_to_ring(args, (int64_t)fd, 0, true, 0);
CHECK_RES(res);

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

/* Parameter 3: mode (type: PT_MODE) */
syscall_get_arguments_deprecated(args, 2, 1, &val);
res = val_to_ring(args, mknod_mode_to_scap(val), 0, false, 0);
CHECK_RES(res);

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

return add_sentinel(args);
unsigned long val;
int res;
int32_t fd;
long retval;

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

/* Parameter 2: dirfd (type: PT_FD) */
syscall_get_arguments_deprecated(args, 0, 1, &val);
fd = (int32_t)val;
if (fd == AT_FDCWD)
fd = PPM_AT_FDCWD;
res = val_to_ring(args, (int64_t)fd, 0, true, 0);
CHECK_RES(res);

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

/* Parameter 3: mode (type: PT_MODE) */
syscall_get_arguments_deprecated(args, 2, 1, &val);
res = val_to_ring(args, mknod_mode_to_scap(val), 0, false, 0);
CHECK_RES(res);

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

return add_sentinel(args);
}

int f_sys_newfstatat_x(struct event_filler_arguments *args)
{
unsigned long val;
int res;
int32_t fd;
long retval;

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

/* Parameter 2: dirfd (type: PT_FD) */
syscall_get_arguments_deprecated(args, 0, 1, &val);
fd = (int32_t)val;
if (fd == AT_FDCWD)
fd = PPM_AT_FDCWD;
res = val_to_ring(args, (int64_t)fd, 0, true, 0);
CHECK_RES(res);

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

/* Parameter 4: flags (type: PT_FLAGS32) */
syscall_get_arguments_deprecated(args, 3, 1, &val);
res = val_to_ring(args, newfstatat_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 @@ -187,6 +187,7 @@ or GPL2.txt for full copies of the license.
FN(sys_finit_module_x) \
FN(sys_mknod_x) \
FN(sys_mknodat_x) \
FN(sys_newfstatat_x) \
FN(terminate_filler)

#define FILLER_ENUM_FN(x) PPM_FILLER_##x,
Expand Down
21 changes: 21 additions & 0 deletions driver/ppm_flag_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1781,6 +1781,27 @@ static __always_inline uint32_t linkat_flags_to_scap(int32_t flags)
return res;
}

static __always_inline uint32_t newfstatat_flags_to_scap(int32_t flags)
{
uint32_t res = 0;

mrgian marked this conversation as resolved.
Show resolved Hide resolved
/* AT_SYMLINK_NOFOLLOW was introduced in kernel 2.6.16, we don't need to check if it's defined */
if (flags & AT_SYMLINK_NOFOLLOW)
res |= PPM_AT_SYMLINK_NOFOLLOW;

#ifdef AT_EMPTY_PATH
if (flags & AT_EMPTY_PATH)
res |= PPM_AT_EMPTY_PATH;
#endif

#ifdef AT_NO_AUTOMOUNT
if (flags & AT_NO_AUTOMOUNT)
res |= PPM_AT_NO_AUTOMOUNT;
#endif

return res;
}

static __always_inline uint32_t chmod_mode_to_scap(unsigned long modes)
{
uint32_t res = 0;
Expand Down