Skip to content
1 change: 1 addition & 0 deletions driver/bpf/filler_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,7 @@ static __always_inline int __bpf_val_to_ring(struct filler_data *data,
len = sizeof(u16);
break;
case PT_FLAGS32:
case PT_MODE:
case PT_UINT32:
case PT_UID:
case PT_GID:
Expand Down
97 changes: 97 additions & 0 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -4178,4 +4178,101 @@ FILLER(sys_autofill, true)
return res;
}

FILLER(sys_fchmodat_x, true)
{
unsigned long val;
int res;
long retval;
unsigned int mode;

retval = bpf_syscall_get_retval(data->ctx);
res = bpf_val_to_ring(data, retval);
if (res != PPM_SUCCESS)
return res;

/*
* dirfd
*/
val = bpf_syscall_get_argument(data, 0);
if ((int)val == AT_FDCWD)
val = PPM_AT_FDCWD;

res = bpf_val_to_ring(data, val);
if (res != PPM_SUCCESS)
return res;

/*
* filename
*/
val = bpf_syscall_get_argument(data, 1);
res = bpf_val_to_ring(data, val);
if (res != PPM_SUCCESS)
return res;

/*
* mode
*/
mode = bpf_syscall_get_argument(data, 2);
mode = chmod_mode_to_scap(mode);
res = bpf_val_to_ring(data, mode);

return res;
}

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

retval = bpf_syscall_get_retval(data->ctx);
res = bpf_val_to_ring(data, retval);
if (res != PPM_SUCCESS)
return res;

/*
* filename
*/
val = bpf_syscall_get_argument(data, 0);
res = bpf_val_to_ring(data, val);
if (res != PPM_SUCCESS)
return res;

/*
* mode
*/
val = bpf_syscall_get_argument(data, 1);
res = bpf_val_to_ring(data, val);

return res;
}

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

retval = bpf_syscall_get_retval(data->ctx);
res = bpf_val_to_ring(data, retval);
if (res != PPM_SUCCESS)
return res;

/*
* fd
*/
val = bpf_syscall_get_argument(data, 0);
res = bpf_val_to_ring(data, val);
if (res != PPM_SUCCESS)
return res;

/*
* mode
*/
val = bpf_syscall_get_argument(data, 1);
res = bpf_val_to_ring(data, val);

return res;
}

#endif
9 changes: 8 additions & 1 deletion driver/event_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,14 @@ const struct ppm_event_info g_event_info[PPM_EVENT_MAX] = {
/* PPME_SYSCALL_LINK_2_E */{"link", EC_FILE, EF_NONE, 0},
/* PPME_SYSCALL_LINK_2_X */{"link", EC_FILE, EF_NONE, 3, {{"res", PT_ERRNO, PF_DEC}, {"oldpath", PT_FSPATH, PF_NA}, {"newpath", PT_FSPATH, PF_NA} } },
/* PPME_SYSCALL_LINKAT_2_E */{"linkat", EC_FILE, EF_NONE, 0},
/* PPME_SYSCALL_LINKAT_2_X */{"linkat", EC_FILE, EF_NONE, 6, {{"res", PT_ERRNO, PF_DEC}, {"olddir", PT_FD, PF_DEC}, {"oldpath", PT_CHARBUF, PF_NA}, {"newdir", PT_FD, PF_DEC}, {"newpath", PT_CHARBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, linkat_flags} } }
/* PPME_SYSCALL_LINKAT_2_X */{"linkat", EC_FILE, EF_NONE, 6, {{"res", PT_ERRNO, PF_DEC}, {"olddir", PT_FD, PF_DEC}, {"oldpath", PT_CHARBUF, PF_NA}, {"newdir", PT_FD, PF_DEC}, {"newpath", PT_CHARBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, linkat_flags} } },
/* PPME_SYSCALL_FCHMODAT_E */{"fchmodat", EC_FILE, EF_NONE, 0},
/* PPME_SYSCALL_FCHMODAT_X */{"fchmodat", EC_FILE, EF_NONE, 4, {{"res", PT_ERRNO, PF_DEC}, {"dirfd", PT_FD, PF_DEC}, {"filename", PT_FSPATH, PF_NA}, {"mode", PT_MODE, PF_OCT, chmod_mode} } },
/* PPME_SYSCALL_CHMOD_E */{"chmod", EC_FILE, EF_NONE, 0},
/* PPME_SYSCALL_CHMOD_X */{"chmod", EC_FILE, EF_NONE, 3, {{"res", PT_ERRNO, PF_DEC}, {"filename", PT_FSPATH, PF_NA}, {"mode", PT_MODE, PF_OCT, chmod_mode} } },
/* PPME_SYSCALL_FCHMOD_E */{"fchmod", EC_FILE, EF_NONE, 0},
/* PPME_SYSCALL_FCHMOD_X */{"fchmod", EC_FILE, EF_NONE, 3, {{"res", PT_ERRNO, PF_DEC}, {"fd", PT_FD, PF_DEC}, {"mode", PT_MODE, PF_OCT, chmod_mode} } }

/* NB: Starting from scap version 1.2, event types will no longer be changed when an event is modified, and the only kind of change permitted for pre-existent events is adding parameters.
* New event types are allowed only for new syscalls or new internal events.
* The number of parameters can be used to differentiate between event versions.
Expand Down
8 changes: 7 additions & 1 deletion driver/fillers_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,5 +284,11 @@ const struct ppm_event_entry g_ppm_events[PPM_EVENT_MAX] = {
[PPME_SYSCALL_LINK_2_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_LINK_2_X] = {FILLER_REF(sys_autofill), 3, APT_REG, {{AF_ID_RETVAL}, {0}, {1} } },
[PPME_SYSCALL_LINKAT_2_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_LINKAT_2_X] = {FILLER_REF(sys_linkat_x)}
[PPME_SYSCALL_LINKAT_2_X] = {FILLER_REF(sys_linkat_x)},
[PPME_SYSCALL_FCHMODAT_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_FCHMODAT_X] = {FILLER_REF(sys_fchmodat_x)},
[PPME_SYSCALL_CHMOD_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_CHMOD_X] = {FILLER_REF(sys_chmod_x)},
[PPME_SYSCALL_FCHMOD_E] = {FILLER_REF(sys_empty)},
[PPME_SYSCALL_FCHMOD_X] = {FILLER_REF(sys_fchmod_x)}
};
16 changes: 16 additions & 0 deletions driver/flags_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,19 @@ const struct ppm_name_value linkat_flags[] = {
{"AT_EMPTY_PATH", PPM_AT_EMPTY_PATH},
{0, 0},
};

const struct ppm_name_value chmod_mode[] = {
{"S_IXOTH", PPM_S_IXOTH},
{"S_IWOTH", PPM_S_IWOTH},
{"S_IROTH", PPM_S_IROTH},
{"S_IXGRP", PPM_S_IXGRP},
{"S_IWGRP", PPM_S_IWGRP},
{"S_IRGRP", PPM_S_IRGRP},
{"S_IXUSR", PPM_S_IXUSR},
{"S_IWUSR", PPM_S_IWUSR},
{"S_IRUSR", PPM_S_IRUSR},
{"S_ISVTX", PPM_S_ISVTX},
{"S_ISGID", PPM_S_ISGID},
{"S_ISUID", PPM_S_ISUID},
{0, 0},
};
1 change: 1 addition & 0 deletions driver/ppm_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ int val_to_ring(struct event_filler_arguments *args, uint64_t val, u32 val_len,
break;
case PT_FLAGS32:
case PT_UINT32:
case PT_MODE:
case PT_UID:
case PT_GID:
case PT_SIGSET:
Expand Down
12 changes: 10 additions & 2 deletions driver/ppm_events_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,13 @@ enum ppm_event_type {
PPME_SYSCALL_LINK_2_X = 309,
PPME_SYSCALL_LINKAT_2_E = 310,
PPME_SYSCALL_LINKAT_2_X = 311,
PPM_EVENT_MAX = 312
PPME_SYSCALL_FCHMODAT_E = 312,
PPME_SYSCALL_FCHMODAT_X = 313,
PPME_SYSCALL_CHMOD_E = 314,
PPME_SYSCALL_CHMOD_X = 315,
PPME_SYSCALL_FCHMOD_E = 316,
PPME_SYSCALL_FCHMOD_X = 317,
PPM_EVENT_MAX = 318
};
/*@}*/

Expand Down Expand Up @@ -1358,7 +1364,8 @@ enum ppm_param_type {
PT_IPV6NET = 39, /* An IPv6 network. */
PT_IPADDR = 40, /* Either an IPv4 or IPv6 address. The length indicates which one it is. */
PT_IPNET = 41, /* Either an IPv4 or IPv6 network. The length indicates which one it is. */
PT_MAX = 42 /* array size */
PT_MAX = 42, /* array size */
PT_MODE = 43 /* a 32 bit bitmask to represent file modes. */
};

enum ppm_print_format {
Expand Down Expand Up @@ -1488,6 +1495,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 chmod_mode[];

extern const struct ppm_param_info sockopt_dynamic_param[];
extern const struct ppm_param_info ptrace_dynamic_param[];
Expand Down
103 changes: 103 additions & 0 deletions driver/ppm_fillers.c
Original file line number Diff line number Diff line change
Expand Up @@ -4806,3 +4806,106 @@ int f_sys_mkdirat_x(struct event_filler_arguments *args)

return add_sentinel(args);
}

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

retval = (int64_t)syscall_get_return_value(current, args->regs);
res = val_to_ring(args, retval, 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* dirfd
*/
syscall_get_arguments_deprecated(current, args->regs, 0, 1, &val);

if ((int)val == AT_FDCWD)
val = PPM_AT_FDCWD;

res = val_to_ring(args, val, 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* filename
*/
syscall_get_arguments_deprecated(current, args->regs, 1, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* mode
*/
syscall_get_arguments_deprecated(current, args->regs, 2, 1, &val);
res = val_to_ring(args, chmod_mode_to_scap(val), 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

return add_sentinel(args);
}

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

retval = (int64_t)syscall_get_return_value(current, args->regs);
res = val_to_ring(args, retval, 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* filename
*/
syscall_get_arguments_deprecated(current, args->regs, 0, 1, &val);
res = val_to_ring(args, val, 0, true, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* mode
*/
syscall_get_arguments_deprecated(current, args->regs, 2, 1, &val);
res = val_to_ring(args, chmod_mode_to_scap(val), 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

return add_sentinel(args);
}

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

retval = (int64_t)syscall_get_return_value(current, args->regs);
res = val_to_ring(args, retval, 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* fd
*/
syscall_get_arguments_deprecated(current, args->regs, 0, 1, &val);

res = val_to_ring(args, val, 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

/*
* mode
*/
syscall_get_arguments_deprecated(current, args->regs, 2, 1, &val);
res = val_to_ring(args, chmod_mode_to_scap(val), 0, false, 0);
if (unlikely(res != PPM_SUCCESS))
return res;

return add_sentinel(args);
}
3 changes: 3 additions & 0 deletions driver/ppm_fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ or GPL2.txt for full copies of the license.
FN(sys_socket_x) \
FN(sys_bpf_x) \
FN(sys_unlinkat_x) \
FN(sys_fchmodat_x) \
FN(sys_chmod_x) \
FN(sys_fchmod_x) \
FN(sys_mkdirat_x) \
FN(sys_openat_x) \
FN(sys_linkat_x) \
Expand Down
54 changes: 54 additions & 0 deletions driver/ppm_flag_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1268,4 +1268,58 @@ static __always_inline u32 linkat_flags_to_scap(unsigned long flags)
return res;
}

static __always_inline u32 chmod_mode_to_scap(unsigned long modes)
{
u32 res = 0;
if (modes & S_IRUSR)
res |= PPM_S_IRUSR;

if (modes & S_IWUSR)
res |= PPM_S_IWUSR;

if (modes & S_IXUSR)
res |= PPM_S_IXUSR;

/*
* PPM_S_IRWXU == S_IRUSR | S_IWUSR | S_IXUSR
*/

if (modes & S_IRGRP)
res |= PPM_S_IRGRP;

if (modes & S_IWGRP)
res |= PPM_S_IWGRP;

if (modes & S_IXGRP)
res |= PPM_S_IXGRP;

/*
* PPM_S_IRWXG == S_IRGRP | S_IWGRP | S_IXGRP
*/

if (modes & S_IROTH)
res |= PPM_S_IROTH;

if (modes & S_IWOTH)
res |= PPM_S_IWOTH;

if (modes & S_IXOTH)
res |= PPM_S_IXOTH;

/*
* PPM_S_IRWXO == S_IROTH | S_IWOTH | S_IXOTH
*/

if (modes & S_ISUID)
res |= PPM_S_ISUID;

if (modes & S_ISGID)
res |= PPM_S_ISGID;

if (modes & S_ISVTX)
res |= PPM_S_ISVTX;

return res;
}

#endif /* PPM_FLAG_HELPERS_H_ */
Loading