From 9066a9b45c78b215cf398727697ce23a51e2d430 Mon Sep 17 00:00:00 2001 From: Eddy Duer Date: Tue, 13 Aug 2024 12:09:35 +0300 Subject: [PATCH] Changes after code review #2 Signed-off-by: Eddy Duer --- driver/bpf/filler_helpers.h | 54 ++++++- driver/bpf/fillers.h | 152 ++++++------------ driver/event_table.c | 2 +- driver/flags_table.c | 16 +- .../syscall_dispatched_events/creat.bpf.c | 10 +- .../syscall_dispatched_events/open.bpf.c | 4 +- .../open_by_handle_at.bpf.c | 43 ++--- .../syscall_dispatched_events/openat.bpf.c | 4 +- .../syscall_dispatched_events/openat2.bpf.c | 4 +- driver/ppm_events_public.h | 21 ++- driver/ppm_fillers.c | 99 +++++++----- .../syscall_exit_suite/creat_x.cpp | 11 +- .../syscall_exit_suite/execve_x.cpp | 2 +- userspace/libsinsp/parsers.cpp | 16 +- userspace/libsinsp/test/filterchecks/evt.cpp | 54 +++++++ 15 files changed, 292 insertions(+), 200 deletions(-) diff --git a/driver/bpf/filler_helpers.h b/driver/bpf/filler_helpers.h index 6e217d5e9a..b4086a7aae 100644 --- a/driver/bpf/filler_helpers.h +++ b/driver/bpf/filler_helpers.h @@ -35,6 +35,14 @@ enum read_memory KERNEL = 1, }; +static __always_inline struct inode *get_file_inode(struct file *file) +{ + if (file) { + return _READ(file->f_inode); + } + return NULL; +} + static __always_inline bool in_port_range(uint16_t port, uint16_t min, uint16_t max) { return port >= min && port <= max; @@ -301,20 +309,58 @@ static __always_inline void bpf_get_ino_from_fd(int fd, unsigned long *ino) *ino = _READ(inode->i_ino); } -static __always_inline void bpf_get_dev_ino_file_from_fd(int fd, unsigned long *dev, unsigned long *ino, struct file **file) +static __always_inline enum ppm_overlay get_overlay_layer(struct file *file) +{ + if (!file) + { + return PPM_NOT_OVERLAY_FS; + } + struct dentry* dentry = NULL; + bpf_probe_read_kernel(&dentry, sizeof(dentry), &file->f_path.dentry); + struct super_block* sb = (struct super_block*)_READ(dentry->d_sb); + unsigned long sb_magic = _READ(sb->s_magic); + + if(sb_magic != PPM_OVERLAYFS_SUPER_MAGIC) + { + return PPM_NOT_OVERLAY_FS; + } + + char *vfs_inode = (char *)_READ(dentry->d_inode); + struct dentry *upper_dentry = NULL; + bpf_probe_read_kernel(&upper_dentry, sizeof(upper_dentry), (char *)vfs_inode + sizeof(struct inode)); + if(!upper_dentry) + { + return PPM_OVERLAY_LOWER; + } + + struct inode *upper_ino = _READ(upper_dentry->d_inode); + if(_READ(upper_ino->i_ino) != 0) + { + return PPM_OVERLAY_UPPER; + } + else + { + return PPM_OVERLAY_LOWER; + } +} + +static __always_inline void bpf_get_dev_ino_overlay_from_fd(int fd, unsigned long *dev, unsigned long *ino, enum ppm_overlay *ol) { struct super_block *sb; struct inode *inode; dev_t kdev; + struct file *file; if (fd < 0) return; - *file = bpf_fget(fd); - if (!*file) + file = bpf_fget(fd); + if (!file) return; - inode = _READ((*file)->f_inode); + *ol = get_overlay_layer(file); + + inode = _READ(file->f_inode); if (!inode) return; diff --git a/driver/bpf/fillers.h b/driver/bpf/fillers.h index 3009ac2082..611ad784f6 100644 --- a/driver/bpf/fillers.h +++ b/driver/bpf/fillers.h @@ -89,49 +89,6 @@ static __always_inline int bpf_##x(void *ctx) \ \ static __always_inline int __bpf_##x(struct filler_data *data) \ -static __always_inline struct inode *get_file_inode(struct file *file) -{ - if (file) { - return _READ(file->f_inode); - } - return NULL; -} - -static __always_inline enum ppm_overlay get_overlay_layer(struct file *file) -{ - if (!file) - { - return PPM_NOT_OVERLAY_FS; - } - struct dentry* dentry = NULL; - bpf_probe_read_kernel(&dentry, sizeof(dentry), &file->f_path.dentry); - struct super_block* sb = (struct super_block*)_READ(dentry->d_sb); - unsigned long sb_magic = _READ(sb->s_magic); - - if(sb_magic != PPM_OVERLAYFS_SUPER_MAGIC) - { - return PPM_NOT_OVERLAY_FS; - } - - char *vfs_inode = (char *)_READ(dentry->d_inode); - struct dentry *upper_dentry = NULL; - bpf_probe_read_kernel(&upper_dentry, sizeof(upper_dentry), (char *)vfs_inode + sizeof(struct inode)); - if(!upper_dentry) - { - return PPM_OVERLAY_LOWER; - } - - struct inode *upper_ino = _READ(upper_dentry->d_inode); - if(_READ(upper_ino->i_ino) != 0) - { - return PPM_OVERLAY_UPPER; - } - else - { - return PPM_OVERLAY_LOWER; - } -} - FILLER_RAW(terminate_filler) { struct scap_bpf_per_cpu_state *state; @@ -407,7 +364,7 @@ FILLER(sys_open_x, true) unsigned long ino = 0; long retval; int res; - struct file *file = NULL; + enum ppm_overlay ol = PPM_NOT_OVERLAY_FS; /* Parameter 1: ret (type: PT_FD) */ retval = bpf_syscall_get_retval(data->ctx); @@ -419,21 +376,20 @@ FILLER(sys_open_x, true) res = bpf_val_to_ring(data, val); CHECK_RES(res); - bpf_get_dev_ino_file_from_fd(retval, &dev, &ino, &file); + bpf_get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* Parameter 3: flags (type: PT_FLAGS32) */ val = bpf_syscall_get_argument(data, 1); flags = open_flags_to_scap(val); /* update flags if file is created*/ flags |= bpf_get_fd_fmode_created(retval); - enum ppm_overlay ol = get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - flags |= PPM_O_F_UPPER_LAYER; + flags |= PPM_FD_UPPER_LAYER; } else if (ol == PPM_OVERLAY_LOWER) { - flags |= PPM_O_F_LOWER_LAYER; + flags |= PPM_FD_LOWER_LAYER; } res = bpf_push_u32_to_ring(data, flags); CHECK_RES(res); @@ -3210,7 +3166,7 @@ FILLER(sys_openat_x, true) long retval; int32_t fd; int res; - struct file *file = NULL; + enum ppm_overlay ol = PPM_NOT_OVERLAY_FS; retval = bpf_syscall_get_retval(data->ctx); res = bpf_push_s64_to_ring(data, retval); @@ -3233,7 +3189,7 @@ FILLER(sys_openat_x, true) res = bpf_val_to_ring(data, val); CHECK_RES(res); - bpf_get_dev_ino_file_from_fd(retval, &dev, &ino, &file); + bpf_get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* * Flags @@ -3243,14 +3199,13 @@ FILLER(sys_openat_x, true) flags = open_flags_to_scap(val); /* update flags if file is created*/ flags |= bpf_get_fd_fmode_created(retval); - enum ppm_overlay ol = get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - flags |= PPM_O_F_UPPER_LAYER; + flags |= PPM_FD_UPPER_LAYER; } else if (ol == PPM_OVERLAY_LOWER) { - flags |= PPM_O_F_LOWER_LAYER; + flags |= PPM_FD_LOWER_LAYER; } res = bpf_push_u32_to_ring(data, flags); CHECK_RES(res); @@ -3353,7 +3308,7 @@ FILLER(sys_openat2_x, true) long retval; int32_t fd; int res; - struct file *file = NULL; + enum ppm_overlay ol = PPM_NOT_OVERLAY_FS; #ifdef __NR_openat2 struct open_how how; #endif @@ -3396,7 +3351,7 @@ FILLER(sys_openat2_x, true) resolve = 0; #endif - bpf_get_dev_ino_file_from_fd(retval, &dev, &ino, &file); + bpf_get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* * flags (extracted from open_how structure) @@ -3404,14 +3359,13 @@ FILLER(sys_openat2_x, true) */ /* update flags if file is created*/ flags |= bpf_get_fd_fmode_created(retval); - enum ppm_overlay ol = get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - flags |= PPM_O_F_UPPER_LAYER; + flags |= PPM_FD_UPPER_LAYER; } else if (ol == PPM_OVERLAY_LOWER) { - flags |= PPM_O_F_LOWER_LAYER; + flags |= PPM_FD_LOWER_LAYER; } res = bpf_push_u32_to_ring(data, flags); CHECK_RES(res); @@ -3445,7 +3399,6 @@ FILLER(sys_openat2_x, true) FILLER(sys_open_by_handle_at_x, true) { long retval = bpf_syscall_get_retval(data->ctx); - struct file *file = bpf_fget(retval); /* Parameter 1: ret (type: PT_FD) */ int res = bpf_push_s64_to_ring(data, retval); @@ -3460,26 +3413,6 @@ FILLER(sys_open_by_handle_at_x, true) res = bpf_push_s64_to_ring(data, (int64_t)mountfd); CHECK_RES(res); - /* Parameter 3: flags (type: PT_FLAGS32) */ - /* Here we need to use `bpf_val_to_ring` to - * fix verifier issues on Amazolinux2 (Kernel 4.14.309-231.529.amzn2.x86_64) - */ - uint32_t flags = (uint32_t)bpf_syscall_get_argument(data, 2); - flags = (uint32_t)open_flags_to_scap(flags); - /* update flags if file is created*/ - flags |= bpf_get_fd_fmode_created(retval); - enum ppm_overlay ol = get_overlay_layer(file); - if (ol == PPM_OVERLAY_UPPER) - { - flags |= PPM_O_F_UPPER_LAYER; - } - else if (ol == PPM_OVERLAY_LOWER) - { - flags |= PPM_O_F_LOWER_LAYER; - } - res = bpf_val_to_ring(data, flags); - CHECK_RES(res); - if(retval > 0) { bpf_tail_call(data->ctx, &tail_map, PPM_FILLER_open_by_handle_at_x_extra_tail_1); @@ -3487,6 +3420,12 @@ FILLER(sys_open_by_handle_at_x, true) return PPM_FAILURE_BUG; } + /* Parameter 3: flags (type: PT_FLAGS32) */ + uint32_t flags = (uint32_t)bpf_syscall_get_argument(data, 2); + flags = (uint32_t)open_flags_to_scap(flags); + res = bpf_val_to_ring(data, flags); + CHECK_RES(res); + /* Parameter 4: path (type: PT_FSPATH) */ res = bpf_push_empty_param(data); CHECK_RES(res); @@ -3502,12 +3441,10 @@ FILLER(sys_open_by_handle_at_x, true) FILLER(open_by_handle_at_x_extra_tail_1, true) { long retval = bpf_syscall_get_retval(data->ctx); - struct file *f = NULL; + struct file *f = bpf_fget(retval); unsigned long dev = 0; unsigned long ino = 0; - unsigned short fd_flags = 0; - - bpf_get_dev_ino_file_from_fd(retval, &dev, &ino, &f); + enum ppm_overlay ol = PPM_NOT_OVERLAY_FS; if(f == NULL) { @@ -3521,9 +3458,30 @@ FILLER(open_by_handle_at_x_extra_tail_1, true) return PPM_FAILURE_BUG; } + bpf_get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); + + /* Parameter 3: flags (type: PT_FLAGS32) */ + /* Here we need to use `bpf_val_to_ring` to + * fix verifier issues on Amazolinux2 (Kernel 4.14.309-231.529.amzn2.x86_64) + */ + uint32_t flags = (uint32_t)bpf_syscall_get_argument(data, 2); + flags = (uint32_t)open_flags_to_scap(flags); + /* update flags if file is created*/ + flags |= bpf_get_fd_fmode_created(retval); + if (ol == PPM_OVERLAY_UPPER) + { + flags |= PPM_FD_UPPER_LAYER; + } + else if (ol == PPM_OVERLAY_LOWER) + { + flags |= PPM_FD_LOWER_LAYER; + } + int res = bpf_val_to_ring(data, flags); + CHECK_RES(res); + /* Parameter 4: path (type: PT_FSPATH) */ char* filepath = bpf_d_path_approx(data, &(f->f_path)); - int res = bpf_val_to_ring_mem(data,(unsigned long)filepath, KERNEL); + res = bpf_val_to_ring_mem(data,(unsigned long)filepath, KERNEL); /* Parameter 5: dev (type: PT_UINT32) */ res = bpf_push_u32_to_ring(data, dev); @@ -4611,8 +4569,8 @@ FILLER(sys_creat_x, true) unsigned long mode; long retval; int res; - struct file *file = NULL; - unsigned short fd_flags = 0; + enum ppm_overlay ol = PPM_NOT_OVERLAY_FS; + unsigned short creat_flags = 0; retval = bpf_syscall_get_retval(data->ctx); res = bpf_push_s64_to_ring(data, retval); @@ -4633,7 +4591,7 @@ FILLER(sys_creat_x, true) res = bpf_push_u32_to_ring(data, mode); CHECK_RES(res); - bpf_get_dev_ino_file_from_fd(retval, &dev, &ino, &file); + bpf_get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* * Device @@ -4648,21 +4606,17 @@ FILLER(sys_creat_x, true) CHECK_RES(res); /* - * fd_flags + * creat_flags */ - if (likely(file)) + if (ol == PPM_OVERLAY_UPPER) { - enum ppm_overlay ol = get_overlay_layer(file); - if (ol == PPM_OVERLAY_UPPER) - { - fd_flags |= PPM_FD_UPPER_LAYER; - } - else if (ol == PPM_OVERLAY_LOWER) - { - fd_flags |= PPM_FD_LOWER_LAYER; - } + creat_flags |= PPM_FD_UPPER_LAYER_CREAT; + } + else if (ol == PPM_OVERLAY_LOWER) + { + creat_flags |= PPM_FD_LOWER_LAYER_CREAT; } - return bpf_push_u16_to_ring(data, (uint16_t)fd_flags); + return bpf_push_u16_to_ring(data, (uint16_t)creat_flags); } FILLER(sys_pipe_x, true) diff --git a/driver/event_table.c b/driver/event_table.c index 1e8cf966fc..b530a70bf7 100644 --- a/driver/event_table.c +++ b/driver/event_table.c @@ -109,7 +109,7 @@ const struct ppm_event_info g_event_info[] = { [PPME_SOCKET_ACCEPT4_E] = {"accept", EC_NET | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE | EF_OLD_VERSION, 1, {{"flags", PT_INT32, PF_HEX} } }, [PPME_SOCKET_ACCEPT4_X] = {"accept", EC_NET | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE | EF_OLD_VERSION, 3, {{"fd", PT_FD, PF_DEC}, {"tuple", PT_SOCKTUPLE, PF_NA}, {"queuepct", PT_UINT8, PF_DEC} } }, [PPME_SYSCALL_CREAT_E] = {"creat", EC_FILE | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 2, {{"name", PT_FSPATH, PF_NA}, {"mode", PT_UINT32, PF_OCT} } }, - [PPME_SYSCALL_CREAT_X] = {"creat", EC_FILE | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 6, {{"fd", PT_FD, PF_DEC}, {"name", PT_FSPATH, PF_NA}, {"mode", PT_UINT32, PF_OCT}, {"dev", PT_UINT32, PF_HEX}, {"ino", PT_UINT64, PF_DEC}, {"fd_flags", PT_FLAGS16, PF_HEX} } }, + [PPME_SYSCALL_CREAT_X] = {"creat", EC_FILE | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 6, {{"fd", PT_FD, PF_DEC}, {"name", PT_FSPATH, PF_NA}, {"mode", PT_UINT32, PF_OCT}, {"dev", PT_UINT32, PF_HEX}, {"ino", PT_UINT64, PF_DEC}, {"creat_flags", PT_FLAGS16, PF_HEX, creat_flags} } }, [PPME_SYSCALL_PIPE_E] = {"pipe", EC_IPC | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 0}, [PPME_SYSCALL_PIPE_X] = {"pipe", EC_IPC | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"res", PT_ERRNO, PF_DEC}, {"fd1", PT_FD, PF_DEC}, {"fd2", PT_FD, PF_DEC}, {"ino", PT_UINT64, PF_DEC} } }, [PPME_SYSCALL_EVENTFD_E] = {"eventfd", EC_IPC | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 2, {{"initval", PT_UINT64, PF_DEC}, {"flags", PT_UINT32, PF_HEX} } }, diff --git a/driver/flags_table.c b/driver/flags_table.c index c91248b636..a187059f24 100644 --- a/driver/flags_table.c +++ b/driver/flags_table.c @@ -72,8 +72,14 @@ const struct ppm_name_value file_flags[] = { {"O_NONE", PPM_O_NONE}, {"O_TMPFILE", PPM_O_TMPFILE}, {"O_F_CREATED", PPM_O_F_CREATED}, - {"O_F_UPPER_LAYER", PPM_O_F_UPPER_LAYER}, - {"O_F_LOWER_LAYER", PPM_O_F_LOWER_LAYER}, + {"FD_UPPER_LAYER", PPM_FD_UPPER_LAYER}, + {"FD_LOWER_LAYER", PPM_FD_LOWER_LAYER}, + {0, 0}, +}; + +const struct ppm_name_value creat_flags[] = { + {"FD_UPPER_LAYER_CREAT", PPM_FD_UPPER_LAYER_CREAT}, + {"FD_LOWER_LAYER_CREAT", PPM_FD_LOWER_LAYER_CREAT}, {0, 0}, }; @@ -773,9 +779,3 @@ const struct ppm_name_value finit_module_flags[] = { {"MODULE_INIT_COMPRESSED_FILE", PPM_MODULE_INIT_COMPRESSED_FILE}, {0, 0}, }; - -const struct ppm_name_value fd_flags[] = { - {"FD_UPPER_LAYER", PPM_FD_UPPER_LAYER}, - {"FD_LOWER_LAYER", PPM_FD_LOWER_LAYER}, - {0, 0}, -}; diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/creat.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/creat.bpf.c index 72748bef88..2801504810 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/creat.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/creat.bpf.c @@ -75,7 +75,7 @@ int BPF_PROG(creat_x, dev_t dev = 0; uint64_t ino = 0; enum ppm_overlay ol = PPM_NOT_OVERLAY_FS; - uint16_t fd_flags = 0; + uint16_t creat_flags = 0; if(ret > 0) { @@ -88,16 +88,16 @@ int BPF_PROG(creat_x, /* Parameter 5: ino (type: PT_UINT64) */ auxmap__store_u64_param(auxmap, ino); - /* Parameter 6: fd_flags (type: PT_FLAGS16) */ + /* Parameter 6: creat_flags (type: PT_FLAGS16) */ if(ol == PPM_OVERLAY_UPPER) { - fd_flags |= PPM_FD_UPPER_LAYER; + creat_flags |= PPM_FD_UPPER_LAYER_CREAT; } else if(ol == PPM_OVERLAY_LOWER) { - fd_flags |= PPM_FD_LOWER_LAYER; + creat_flags |= PPM_FD_LOWER_LAYER_CREAT; } - auxmap__store_u16_param(auxmap, fd_flags); + auxmap__store_u16_param(auxmap, creat_flags); /*=============================== COLLECT PARAMETERS ===========================*/ auxmap__finalize_event_header(auxmap); diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open.bpf.c index 74767c16e4..756911ff94 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open.bpf.c @@ -88,11 +88,11 @@ int BPF_PROG(open_x, scap_flags |= extract__fmode_created_from_fd(ret); if(ol == PPM_OVERLAY_UPPER) { - scap_flags |= PPM_O_F_UPPER_LAYER; + scap_flags |= PPM_FD_UPPER_LAYER; } else if(ol == PPM_OVERLAY_LOWER) { - scap_flags |= PPM_O_F_LOWER_LAYER; + scap_flags |= PPM_FD_LOWER_LAYER; } auxmap__store_u32_param(auxmap, scap_flags); diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c index 5bf33b7a60..e3eadab08b 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/open_by_handle_at.bpf.c @@ -65,23 +65,6 @@ int BPF_PROG(open_by_handle_at_x, } auxmap__store_s64_param(auxmap, (int64_t)mountfd); - /* Parameter 3: flags (type: PT_FLAGS32) */ - uint32_t flags = (uint32_t)extract__syscall_argument(regs, 2); - flags = (uint32_t)open_flags_to_scap(flags); - /* update flags if file is created */ - flags |= extract__fmode_created_from_fd(ret); - struct file *f = extract__file_struct_from_fd(ret); - enum ppm_overlay ol = extract__overlay_layer(f); - if(ol == PPM_OVERLAY_UPPER) - { - flags |= PPM_O_F_UPPER_LAYER; - } - else if(ol == PPM_OVERLAY_LOWER) - { - flags |= PPM_O_F_LOWER_LAYER; - } - auxmap__store_u32_param(auxmap, flags); - /*=============================== COLLECT PARAMETERS ===========================*/ bpf_tail_call(ctx, &extra_event_prog_tail_table, T1_OPEN_BY_HANDLE_AT_X); @@ -94,7 +77,6 @@ int BPF_PROG(t1_open_by_handle_at_x, struct pt_regs *regs, long ret) dev_t dev = 0; uint64_t ino = 0; enum ppm_overlay ol = PPM_NOT_OVERLAY_FS; - uint16_t fd_flags = 0; struct auxiliary_map *auxmap = auxmap__get(); if(!auxmap) @@ -104,7 +86,28 @@ int BPF_PROG(t1_open_by_handle_at_x, struct pt_regs *regs, long ret) /*=============================== COLLECT PARAMETERS ===========================*/ - /* We collect the file path, dev and ino from the file descriptor only if it is valid */ + uint32_t flags = (uint32_t)extract__syscall_argument(regs, 2); + flags = (uint32_t)open_flags_to_scap(flags); + /* We collect dev, ino and overlay from the file descriptor only if it is valid */ + if(ret > 0) + { + extract__dev_ino_overlay_from_fd(ret, &dev, &ino, &ol); + + /* Parameter 3: flags (type: PT_FLAGS32) */ + /* update flags if file is created */ + flags |= extract__fmode_created_from_fd(ret); + if(ol == PPM_OVERLAY_UPPER) + { + flags |= PPM_FD_UPPER_LAYER; + } + else if(ol == PPM_OVERLAY_LOWER) + { + flags |= PPM_FD_LOWER_LAYER; + } + } + auxmap__store_u32_param(auxmap, flags); + + /* We collect the file path from the file descriptor only if it is valid */ if(ret > 0) { /* Parameter 4: path (type: PT_FSPATH) */ @@ -117,8 +120,6 @@ int BPF_PROG(t1_open_by_handle_at_x, struct pt_regs *regs, long ret) { auxmap__store_empty_param(auxmap); } - - extract__dev_ino_overlay_from_fd(ret, &dev, &ino, &ol); } else { diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat.bpf.c index 7738143c70..b9e400b9ac 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat.bpf.c @@ -104,11 +104,11 @@ int BPF_PROG(openat_x, scap_flags |= extract__fmode_created_from_fd(ret); if(ol == PPM_OVERLAY_UPPER) { - scap_flags |= PPM_O_F_UPPER_LAYER; + scap_flags |= PPM_FD_UPPER_LAYER; } else if(ol == PPM_OVERLAY_LOWER) { - scap_flags |= PPM_O_F_LOWER_LAYER; + scap_flags |= PPM_FD_LOWER_LAYER; } auxmap__store_u32_param(auxmap, scap_flags); diff --git a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat2.bpf.c b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat2.bpf.c index af14ab7a53..ab33ece2ef 100644 --- a/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat2.bpf.c +++ b/driver/modern_bpf/programs/tail_called/events/syscall_dispatched_events/openat2.bpf.c @@ -114,11 +114,11 @@ int BPF_PROG(openat2_x, flags |= extract__fmode_created_from_fd(ret); if(ol == PPM_OVERLAY_UPPER) { - flags |= PPM_O_F_UPPER_LAYER; + flags |= PPM_FD_UPPER_LAYER; } else if(ol == PPM_OVERLAY_LOWER) { - flags |= PPM_O_F_LOWER_LAYER; + flags |= PPM_FD_LOWER_LAYER; } auxmap__store_u32_param(auxmap, flags); diff --git a/driver/ppm_events_public.h b/driver/ppm_events_public.h index 980b66bcf2..03bcfddb8f 100644 --- a/driver/ppm_events_public.h +++ b/driver/ppm_events_public.h @@ -105,8 +105,18 @@ or GPL2.txt for full copies of the license. #define PPM_O_TMPFILE (1 << 13) /* Flags added by syscall probe: */ #define PPM_O_F_CREATED (1 << 14) /* file created during the syscall */ -#define PPM_O_F_UPPER_LAYER (1 << 15) /* file is from upper layer */ -#define PPM_O_F_LOWER_LAYER (1 << 16) /* file is from upper layer */ +#define PPM_FD_UPPER_LAYER (1 << 15) /* file is from upper layer */ +#define PPM_FD_LOWER_LAYER (1 << 16) /* file is from upper layer */ + +/* + * creat flags + */ +/* These flags serve the same puropse as the flags PPM_FD_UPPER_LAYER and PPM_FD_LOWER_LAYER in the 'File flags' section. + * They are used in creat system call because it doesn't have a 'flags' parameter that can be used. + * This redifintion is needed because this 'creat_flags' parameter is 16 bits and the aforementioned flags are over 16 bits. + */ +#define PPM_FD_UPPER_LAYER_CREAT (1 << 0) /* file is from upper layer. Equivalent to PPM_FD_UPPER_LAYER */ +#define PPM_FD_LOWER_LAYER_CREAT (1 << 1) /* file is from upper layer. Equivalent to PPM_FD_LOWER_LAYER */ /* * File modes @@ -815,12 +825,6 @@ or GPL2.txt for full copies of the license. #define PPM_DELETE_MODULE_O_TRUNC (1 << 0) #define PPM_DELETE_MODULE_O_NONBLOCK (1 << 1) -/* - * FD flags - */ -#define PPM_FD_UPPER_LAYER (1 << 0) -#define PPM_FD_LOWER_LAYER (1 << 1) - /* * bpf_commands */ @@ -2196,6 +2200,7 @@ struct ppm_evt_hdr { extern const struct ppm_name_value socket_families[]; extern const struct ppm_name_value file_flags[]; +extern const struct ppm_name_value creat_flags[]; extern const struct ppm_name_value flock_flags[]; extern const struct ppm_name_value clone_flags[]; extern const struct ppm_name_value futex_operations[]; diff --git a/driver/ppm_fillers.c b/driver/ppm_fillers.c index 51d9a4893b..7490851aae 100644 --- a/driver/ppm_fillers.c +++ b/driver/ppm_fillers.c @@ -183,12 +183,47 @@ int f_sys_fstat_e(struct event_filler_arguments *args) return add_sentinel(args); } -static inline void get_fd_dev_ino_file(int64_t fd, uint32_t* dev, uint64_t* ino, struct file **file) +static inline void get_ino_from_fd(int64_t fd, uint64_t* ino) +{ + struct files_struct *files; + struct fdtable *fdt; + struct inode *inode; + struct file *file; + + if (fd < 0) + return; + + files = current->files; + if (unlikely(!files)) + return; + + spin_lock(&files->file_lock); + fdt = files_fdtable(files); + if (unlikely(fd > fdt->max_fds)) + goto out_unlock; + + file = fdt->fd[fd]; + if (unlikely(!file)) + goto out_unlock; + + inode = file_inode(file); + if (unlikely(!inode)) + goto out_unlock; + + *ino = inode->i_ino; + +out_unlock: + spin_unlock(&files->file_lock); + return; +} + +static inline void get_dev_ino_overlay_from_fd(int64_t fd, uint32_t* dev, uint64_t* ino, enum ppm_overlay *ol) { struct files_struct *files; struct fdtable *fdt; struct inode *inode; struct super_block *sb; + struct file *file; if (fd < 0) return; @@ -202,11 +237,13 @@ static inline void get_fd_dev_ino_file(int64_t fd, uint32_t* dev, uint64_t* ino, if (unlikely(fd > fdt->max_fds)) goto out_unlock; - *file = fdt->fd[fd]; - if (unlikely(!*file)) + file = fdt->fd[fd]; + if (unlikely(!file)) goto out_unlock; - inode = file_inode(*file); + *ol = ppm_get_overlay_layer(file); + + inode = file_inode(file); if (unlikely(!inode)) goto out_unlock; @@ -298,7 +335,6 @@ int f_sys_open_x(struct event_filler_arguments *args) uint64_t ino = 0; int res; int64_t retval; - struct file *file = NULL; enum ppm_overlay ol; /* @@ -316,7 +352,7 @@ int f_sys_open_x(struct event_filler_arguments *args) res = val_to_ring(args, val, 0, true, 0); CHECK_RES(res); - get_fd_dev_ino_file(retval, &dev, &ino, &file); + get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* * Flags @@ -326,14 +362,13 @@ int f_sys_open_x(struct event_filler_arguments *args) scap_flags = open_flags_to_scap(flags); /* update scap flags if file is created */ get_fd_fmode_created(retval, &scap_flags); - ol = ppm_get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - scap_flags |= PPM_O_F_UPPER_LAYER; + scap_flags |= PPM_FD_UPPER_LAYER; } else if (ol == PPM_OVERLAY_LOWER) { - scap_flags |= PPM_O_F_LOWER_LAYER; + scap_flags |= PPM_FD_LOWER_LAYER; } res = val_to_ring(args, scap_flags, 0, false, 0); CHECK_RES(res); @@ -2980,9 +3015,8 @@ int f_sys_creat_x(struct event_filler_arguments *args) uint64_t ino = 0; int res; int64_t retval; - struct file *file = NULL; enum ppm_overlay ol; - int16_t fd_flags = 0; + int16_t creat_flags = 0; /* * fd @@ -3004,7 +3038,7 @@ int f_sys_creat_x(struct event_filler_arguments *args) res = val_to_ring(args, open_modes_to_scap(O_CREAT, modes), 0, false, 0); CHECK_RES(res); - get_fd_dev_ino_file(retval, &dev, &ino, &file); + get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* * dev @@ -3019,18 +3053,17 @@ int f_sys_creat_x(struct event_filler_arguments *args) CHECK_RES(res); /* - * fd_flags + * creat_flags */ - ol = ppm_get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - fd_flags |= PPM_FD_UPPER_LAYER; + creat_flags |= PPM_FD_UPPER_LAYER_CREAT; } else if (ol == PPM_OVERLAY_LOWER) { - fd_flags |= PPM_FD_LOWER_LAYER; + creat_flags |= PPM_FD_LOWER_LAYER_CREAT; } - res = val_to_ring(args, fd_flags, 0, false, 0); + res = val_to_ring(args, creat_flags, 0, false, 0); CHECK_RES(res); return add_sentinel(args); @@ -3042,9 +3075,7 @@ int f_sys_pipe_x(struct event_filler_arguments *args) int64_t retval = 0; unsigned long val = 0; int pipefd[2] = {-1, -1}; - uint32_t dev = 0; uint64_t ino = 0; - struct file *file = NULL; /* Parameter 1: res (type: PT_ERRNO) */ retval = (int64_t)syscall_get_return_value(current, args->regs); @@ -3083,7 +3114,7 @@ int f_sys_pipe_x(struct event_filler_arguments *args) /* On success, pipe returns `0` */ if(retval == 0) { - get_fd_dev_ino_file(pipefd[0], &dev, &ino, &file); + get_ino_from_fd(pipefd[0], &ino); } /* Parameter 4: ino (type: PT_UINT64) */ @@ -3099,9 +3130,7 @@ int f_sys_pipe2_x(struct event_filler_arguments *args) int64_t retval = 0; unsigned long val = 0; int pipefd[2] = {-1, -1}; - uint32_t dev = 0; uint64_t ino = 0; - struct file *file = NULL; /* Parameter 1: res (type: PT_ERRNO) */ retval = (int64_t)syscall_get_return_value(current, args->regs); @@ -3140,7 +3169,7 @@ int f_sys_pipe2_x(struct event_filler_arguments *args) /* On success, pipe returns `0` */ if(retval == 0) { - get_fd_dev_ino_file(pipefd[0], &dev, &ino, &file); + get_ino_from_fd(pipefd[0], &ino); } /* Parameter 4: ino (type: PT_UINT64) */ @@ -3569,7 +3598,6 @@ int f_sys_openat_x(struct event_filler_arguments *args) int res; int32_t fd; int64_t retval; - struct file *file = NULL; enum ppm_overlay ol; retval = (int64_t)syscall_get_return_value(current, args->regs); @@ -3594,7 +3622,7 @@ int f_sys_openat_x(struct event_filler_arguments *args) res = val_to_ring(args, val, 0, true, 0); CHECK_RES(res); - get_fd_dev_ino_file(retval, &dev, &ino, &file); + get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* * Flags * Note that we convert them into the ppm portable representation before pushing them to the ring @@ -3603,14 +3631,13 @@ int f_sys_openat_x(struct event_filler_arguments *args) scap_flags = open_flags_to_scap(flags); /* update scap flags if file is created */ get_fd_fmode_created(retval, &scap_flags); - ol = ppm_get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - scap_flags |= PPM_O_F_UPPER_LAYER; + scap_flags |= PPM_FD_UPPER_LAYER; } else if (ol == PPM_OVERLAY_LOWER) { - scap_flags |= PPM_O_F_LOWER_LAYER; + scap_flags |= PPM_FD_LOWER_LAYER; } res = val_to_ring(args, scap_flags, 0, false, 0); CHECK_RES(res); @@ -5003,7 +5030,6 @@ int f_sys_openat2_x(struct event_filler_arguments *args) int res; int32_t fd; int64_t retval; - struct file *file = NULL; enum ppm_overlay ol; #ifdef __NR_openat2 struct open_how how; @@ -5050,7 +5076,7 @@ int f_sys_openat2_x(struct event_filler_arguments *args) resolve = 0; #endif - get_fd_dev_ino_file(retval, &dev, &ino, &file); + get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* * flags (extracted from open_how structure) @@ -5058,14 +5084,13 @@ int f_sys_openat2_x(struct event_filler_arguments *args) */ /* update flags if file is created */ get_fd_fmode_created(retval, &flags); - ol = ppm_get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - flags |= PPM_O_F_UPPER_LAYER; + flags |= PPM_FD_UPPER_LAYER; } else if (ol == PPM_OVERLAY_LOWER) { - flags |= PPM_O_F_LOWER_LAYER; + flags |= PPM_FD_LOWER_LAYER; } res = val_to_ring(args, flags, 0, true, 0); CHECK_RES(res); @@ -5167,7 +5192,6 @@ int f_sys_open_by_handle_at_x(struct event_filler_arguments *args) long retval = 0; char *pathname = NULL; int32_t mountfd = 0; - struct file *file = NULL; enum ppm_overlay ol; /* Parameter 1: ret (type: PT_FD) */ @@ -5185,21 +5209,20 @@ int f_sys_open_by_handle_at_x(struct event_filler_arguments *args) res = val_to_ring(args, (int64_t)mountfd, 0, false, 0); CHECK_RES(res); - get_fd_dev_ino_file(retval, &dev, &ino, &file); + get_dev_ino_overlay_from_fd(retval, &dev, &ino, &ol); /* Parameter 3: flags (type: PT_FLAGS32) */ syscall_get_arguments_deprecated(args, 2, 1, &val); flags = open_flags_to_scap(val); /* update flags if file is created */ get_fd_fmode_created(retval, &flags); - ol = ppm_get_overlay_layer(file); if (ol == PPM_OVERLAY_UPPER) { - flags |= PPM_O_F_UPPER_LAYER; + flags |= PPM_FD_UPPER_LAYER; } else if (ol == PPM_OVERLAY_LOWER) { - flags |= PPM_O_F_LOWER_LAYER; + flags |= PPM_FD_LOWER_LAYER; } res = val_to_ring(args, flags, 0, false, 0); CHECK_RES(res); diff --git a/test/drivers/test_suites/syscall_exit_suite/creat_x.cpp b/test/drivers/test_suites/syscall_exit_suite/creat_x.cpp index ef2cb176eb..2334aeab87 100644 --- a/test/drivers/test_suites/syscall_exit_suite/creat_x.cpp +++ b/test/drivers/test_suites/syscall_exit_suite/creat_x.cpp @@ -22,6 +22,7 @@ TEST(SyscallExit, creatX_success) uint32_t dev = (uint32_t)file_stat.st_dev; uint64_t inode = file_stat.st_ino; const bool is_ext4 = event_test::is_ext4_fs(fd); + uint16_t creat_flags = 0; /* Remove the file. */ syscall(__NR_close, fd); @@ -62,9 +63,12 @@ TEST(SyscallExit, creatX_success) /* Parameter 5: ino (type: PT_UINT64) */ evt_test->assert_numeric_param(5, (uint64_t)inode); + /* Parameter 6: creat_flags (type: PT_FLAGS16) */ + evt_test->assert_numeric_param(6, (uint16_t)creat_flags); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(5); + evt_test->assert_num_params_pushed(6); } #endif /* defined(__NR_fstat) && defined(__NR_unlinkat) && defined(__NR_close) */ @@ -113,8 +117,11 @@ TEST(SyscallExit, creatX_failure) /* Parameter 5: ino (type: PT_UINT64) */ evt_test->assert_numeric_param(5, (uint64_t)0); + /* Parameter 6: creat_flags (type: PT_FLAGS16) */ + evt_test->assert_numeric_param(6, (uint16_t)0); + /*=============================== ASSERT PARAMETERS ===========================*/ - evt_test->assert_num_params_pushed(5); + evt_test->assert_num_params_pushed(6); } #endif diff --git a/test/drivers/test_suites/syscall_exit_suite/execve_x.cpp b/test/drivers/test_suites/syscall_exit_suite/execve_x.cpp index a8429d28a4..e3e07adb96 100644 --- a/test/drivers/test_suites/syscall_exit_suite/execve_x.cpp +++ b/test/drivers/test_suites/syscall_exit_suite/execve_x.cpp @@ -649,7 +649,7 @@ TEST(SyscallExit, execveX_not_upperlayer) /* PPM_EXE_WRITABLE is set when the user that executed a process can also write to the executable * file that is used to spawn it or is its owner or otherwise capable. */ - evt_test->assert_numeric_param(20, (uint32_t)PPM_EXE_WRITABLE, EQUAL); + evt_test->assert_numeric_param(20, (uint32_t)PPM_EXE_WRITABLE | PPM_EXE_LOWER_LAYER, EQUAL); /* Parameter 24: exe_file ino (type: PT_UINT64) */ evt_test->assert_numeric_param(24, (uint64_t)1, GREATER_EQUAL); diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index c8982154e6..589315c51f 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -2641,14 +2641,16 @@ void sinsp_parser::parse_open_openat_creat_exit(sinsp_evt *evt) ino = evt->get_param(4)->as(); if (evt->get_num_params() > 5) { - uint16_t fd_flags = evt->get_param(5)->as(); - if (fd_flags & PPM_FD_UPPER_LAYER) + uint16_t creat_flags = evt->get_param(5)->as(); + // creat is a special case becuase it has no flags parameter, so the layer info bits arrive from probe + // in a separate creat_flags parameter and flags need to be constructed from it + if (creat_flags & PPM_FD_UPPER_LAYER_CREAT) { - flags |= PPM_O_F_UPPER_LAYER; + flags |= PPM_FD_UPPER_LAYER; } - else if (fd_flags & PPM_FD_LOWER_LAYER) + else if (creat_flags & PPM_FD_LOWER_LAYER_CREAT) { - flags |= PPM_O_F_LOWER_LAYER; + flags |= PPM_FD_LOWER_LAYER; } } } @@ -2780,11 +2782,11 @@ void sinsp_parser::parse_open_openat_creat_exit(sinsp_evt *evt) fdi->m_ino = ino; fdi->add_filename_raw(name); fdi->add_filename(fullpath); - if(flags & PPM_O_F_UPPER_LAYER) + if(flags & PPM_FD_UPPER_LAYER) { fdi->set_overlay_upper(); } - if(flags & PPM_O_F_LOWER_LAYER) + if(flags & PPM_FD_LOWER_LAYER) { fdi->set_overlay_lower(); } diff --git a/userspace/libsinsp/test/filterchecks/evt.cpp b/userspace/libsinsp/test/filterchecks/evt.cpp index c462bf6d6e..8cafa278fd 100644 --- a/userspace/libsinsp/test/filterchecks/evt.cpp +++ b/userspace/libsinsp/test/filterchecks/evt.cpp @@ -44,6 +44,60 @@ TEST_F(sinsp_with_test_input, EVT_FILTER_is_open_create) ASSERT_EQ(evt->get_fd_info()->m_openflags, PPM_O_RDWR | PPM_O_CREAT | PPM_O_F_CREATED); } +TEST_F(sinsp_with_test_input, EVT_FILTER_is_lower_layer) +{ + add_default_init_thread(); + + open_inspector(); + + std::string path = "/home/file.txt"; + int64_t fd = 3; + + // In the enter event we don't send the `PPM_O_F_CREATED` + sinsp_evt* evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_E, 3, path.c_str(), + (uint32_t)PPM_O_RDONLY, (uint32_t)0); + + // The `fdinfo` is not populated in the enter event + ASSERT_FALSE(evt->get_fd_info()); + + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_X, 6, fd, path.c_str(), + (uint32_t)PPM_O_RDONLY | PPM_FD_LOWER_LAYER, (uint32_t)0, (uint32_t)5, + (uint64_t)123); + ASSERT_EQ(get_field_as_string(evt, "fd.is_lower_layer"), "true"); + ASSERT_EQ(get_field_as_string(evt, "fd.is_upper_layer"), "false"); + ASSERT_TRUE(evt->get_fd_info()); + + ASSERT_EQ(evt->get_fd_info()->is_overlay_lower(), true); + ASSERT_EQ(evt->get_fd_info()->is_overlay_upper(), false); +} + +TEST_F(sinsp_with_test_input, EVT_FILTER_is_upper_layer) +{ + add_default_init_thread(); + + open_inspector(); + + std::string path = "/home/file.txt"; + int64_t fd = 3; + + // In the enter event we don't send the `PPM_O_F_CREATED` + sinsp_evt* evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_E, 3, path.c_str(), + (uint32_t)PPM_O_RDONLY, (uint32_t)0); + + // The `fdinfo` is not populated in the enter event + ASSERT_FALSE(evt->get_fd_info()); + + evt = add_event_advance_ts(increasing_ts(), 1, PPME_SYSCALL_OPEN_X, 6, fd, path.c_str(), + (uint32_t)PPM_O_RDONLY | PPM_FD_UPPER_LAYER, (uint32_t)0, (uint32_t)5, + (uint64_t)123); + ASSERT_EQ(get_field_as_string(evt, "fd.is_lower_layer"), "false"); + ASSERT_EQ(get_field_as_string(evt, "fd.is_upper_layer"), "true"); + ASSERT_TRUE(evt->get_fd_info()); + + ASSERT_EQ(evt->get_fd_info()->is_overlay_lower(), false); + ASSERT_EQ(evt->get_fd_info()->is_overlay_upper(), true); +} + TEST_F(sinsp_with_test_input, EVT_FILTER_rawarg_int) { add_default_init_thread();