From 4df75cff77cf78e0888b140d9c181bce3b43a426 Mon Sep 17 00:00:00 2001 From: Melissa Kilby Date: Sun, 18 Sep 2022 22:48:02 -0700 Subject: [PATCH] new(driver-bpf, libscap): extract pidns start ts + cleanup Signed-off-by: Melissa Kilby --- driver/bpf/fillers.h | 59 ++++++++++++++++++++++++++++++++-------- driver/event_table.c | 8 +++--- userspace/libscap/scap.h | 2 ++ 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/driver/bpf/fillers.h b/driver/bpf/fillers.h index 354df247cf..cd5cc33b16 100644 --- a/driver/bpf/fillers.h +++ b/driver/bpf/fillers.h @@ -2169,6 +2169,17 @@ static __always_inline struct inode *bpf_exe_inode(struct task_struct *task) return _READ(exe_file->f_inode); } +static __always_inline unsigned long long bpf_ctime_mtime_ns(struct timespec64 time) +{ + unsigned long long epoch; + time64_t tv_sec = time.tv_sec; + if (tv_sec > 0) + { + epoch = tv_sec * (uint64_t) 1000000000 + time.tv_nsec; + } + return epoch; +} + static __always_inline bool get_exe_writable(struct inode *inode, struct cred *cred) { if (!inode || !cred) @@ -2551,6 +2562,7 @@ FILLER(proc_startupdate_3, true) pid_t vpid; struct pid_namespace *pidns = bpf_task_active_pid_ns(task); int pidns_level = _READ(pidns->level); + unsigned long long pidns_init_start_time; /* * flags @@ -2637,6 +2649,21 @@ FILLER(proc_startupdate_3, true) vpid = bpf_task_tgid_vnr(task); res = bpf_val_to_ring_type(data, vpid, PT_PID); + /* Parameter 21: pid_namespace init task start_time monotonic time in ns (type: PT_UINT64) */ + if (pidns) + { + struct task_struct *child_reaper = (struct task_struct *)_READ(pidns->child_reaper); + if (child_reaper) + { + pidns_init_start_time = _READ(child_reaper->start_time); + } + } + res = bpf_val_to_ring_type(data, pidns_init_start_time, PT_UINT64); + if (res != PPM_SUCCESS) + { + return res; + } + } else if (data->state->tail_ctx.evt_type == PPME_SYSCALL_EXECVE_19_X || data->state->tail_ctx.evt_type == PPME_SYSCALL_EXECVEAT_X) { /* @@ -2767,6 +2794,8 @@ FILLER(execve_family_flags, true) struct task_struct *task = (struct task_struct *)bpf_get_current_task(); struct cred *cred = (struct cred *)_READ(task->cred); struct inode *inode = (struct inode *)bpf_exe_inode(task); + unsigned long long epoch; + struct timespec64 time; /* * `exe_writable` flag logic @@ -2812,24 +2841,26 @@ FILLER(execve_family_flags, true) return res; /* Parameter 24: exe_file ino (type: PT_UINT64) */ - unsigned long i_ino = _READ(inode->i_ino); - res = bpf_val_to_ring_type(data, i_ino, PT_UINT64); + val = _READ(inode->i_ino); + res = bpf_val_to_ring_type(data, val, PT_UINT64); if (res != PPM_SUCCESS) { return res; } /* Parameter 25: exe_file ctime (last status change time, epoch value in nanoseconds) (type: PT_ABSTIME) */ - struct timespec64 i_ctime = _READ(inode->i_ctime); - res = bpf_val_to_ring_type(data, i_ctime.tv_sec * 1000000000 + i_ctime.tv_nsec, PT_ABSTIME); + time = _READ(inode->i_ctime); + epoch = bpf_ctime_mtime_ns(time); + res = bpf_val_to_ring_type(data, epoch, PT_ABSTIME); if (res != PPM_SUCCESS) { return res; } /* Parameter 26: exe_file mtime (last modification time, epoch value in nanoseconds) (type: PT_ABSTIME) */ - struct timespec64 i_mtime = _READ(inode->i_mtime); - res = bpf_val_to_ring_type(data, i_mtime.tv_sec * 1000000000 + i_mtime.tv_nsec, PT_ABSTIME); + time = _READ(inode->i_mtime); + epoch = bpf_ctime_mtime_ns(time); + res = bpf_val_to_ring_type(data, epoch, PT_ABSTIME); if (res != PPM_SUCCESS) { return res; @@ -6416,6 +6447,8 @@ FILLER(sched_prog_exec_4, false) struct task_struct *task = (struct task_struct *)bpf_get_current_task(); struct cred *cred = (struct cred *)_READ(task->cred); struct inode *inode = (struct inode *)bpf_exe_inode(task); + unsigned long long epoch; + struct timespec64 time; /* `exe_writable` flag logic */ exe_writable = get_exe_writable(inode, cred); @@ -6461,24 +6494,26 @@ FILLER(sched_prog_exec_4, false) } /* Parameter 24: exe_file ino (type: PT_UINT64) */ - unsigned long i_ino = _READ(inode->i_ino); - res = bpf_val_to_ring_type(data, i_ino, PT_UINT64); + val = _READ(inode->i_ino); + res = bpf_val_to_ring_type(data, val, PT_UINT64); if (res != PPM_SUCCESS) { return res; } /* Parameter 25: exe_file ctime (last status change time, epoch value in nanoseconds) (type: PT_ABSTIME) */ - struct timespec64 i_ctime = _READ(inode->i_ctime); - res = bpf_val_to_ring_type(data, i_ctime.tv_sec * 1000000000 + i_ctime.tv_nsec, PT_ABSTIME); + time = _READ(inode->i_ctime); + epoch = bpf_ctime_mtime_ns(time); + res = bpf_val_to_ring_type(data, epoch, PT_ABSTIME); if (res != PPM_SUCCESS) { return res; } /* Parameter 26: exe_file mtime (last modification time, epoch value in nanoseconds) (type: PT_ABSTIME) */ - struct timespec64 i_mtime = _READ(inode->i_mtime); - res = bpf_val_to_ring_type(data, i_mtime.tv_sec * 1000000000 + i_mtime.tv_nsec, PT_ABSTIME); + time = _READ(inode->i_mtime); + epoch = bpf_ctime_mtime_ns(time); + res = bpf_val_to_ring_type(data, epoch, PT_ABSTIME); if (res != PPM_SUCCESS) { return res; diff --git a/driver/event_table.c b/driver/event_table.c index be1c945956..d48a8ba893 100644 --- a/driver/event_table.c +++ b/driver/event_table.c @@ -235,11 +235,11 @@ const struct ppm_event_info g_event_info[PPM_EVENT_MAX] = { /* PPME_SYSCALL_VFORK_17_E */{"vfork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE | EF_OLD_VERSION, 0}, /* PPME_SYSCALL_VFORK_17_X */{"vfork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE | EF_OLD_VERSION, 17, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC} } }, /* PPME_SYSCALL_CLONE_20_E */{"clone", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0}, - /* PPME_SYSCALL_CLONE_20_X */{"clone", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 20, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC} } }, + /* PPME_SYSCALL_CLONE_20_X */{"clone", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 21, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC}, {"pidns_init_start_ts", PT_UINT64, PF_DEC} } }, /* PPME_SYSCALL_FORK_20_E */{"fork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0}, - /* PPME_SYSCALL_FORK_20_X */{"fork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 20, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC} } }, + /* PPME_SYSCALL_FORK_20_X */{"fork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 21, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC}, {"pidns_init_start_ts", PT_UINT64, PF_DEC} } }, /* PPME_SYSCALL_VFORK_20_E */{"vfork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0}, - /* PPME_SYSCALL_VFORK_20_X */{"vfork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 20, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC} } }, + /* PPME_SYSCALL_VFORK_20_X */{"vfork", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 21, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC}, {"pidns_init_start_ts", PT_UINT64, PF_DEC} } }, /* PPME_CONTAINER_E */{"container", EC_INTERNAL, EF_SKIPPARSERESET | EF_MODIFIES_STATE | EF_OLD_VERSION, 4, {{"id", PT_CHARBUF, PF_NA}, {"type", PT_UINT32, PF_DEC}, {"name", PT_CHARBUF, PF_NA}, {"image", PT_CHARBUF, PF_NA} } }, /* PPME_CONTAINER_X */{"container", EC_UNKNOWN, EF_UNUSED | EF_OLD_VERSION, 0}, /* PPME_SYSCALL_EXECVE_16_E */{"execve", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE | EF_OLD_VERSION, 0}, @@ -347,7 +347,7 @@ const struct ppm_event_info g_event_info[PPM_EVENT_MAX] = { /* PPME_SYSCALL_COPY_FILE_RANGE_E */{"copy_file_range", EC_FILE | EC_SYSCALL, EF_USES_FD | EF_READS_FROM_FD | EF_WRITES_TO_FD, 3, {{"fdin", PT_FD, PF_DEC}, {"offin", PT_UINT64, PF_DEC}, {"len", PT_UINT64, PF_DEC} } }, /* PPME_SYSCALL_COPY_FILE_RANGE_X */{"copy_file_range", EC_FILE | EC_SYSCALL, EF_USES_FD | EF_READS_FROM_FD | EF_WRITES_TO_FD, 3, {{"res", PT_ERRNO, PF_DEC}, {"fdout", PT_FD, PF_DEC}, {"offout", PT_UINT64, PF_DEC} } }, /* PPME_SYSCALL_CLONE3_E */{"clone3", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 0}, - /* PPME_SYSCALL_CLONE3_X */{"clone3", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 20, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC} } }, + /* PPME_SYSCALL_CLONE3_X */{"clone3", EC_PROCESS | EC_SYSCALL, EF_MODIFIES_STATE, 21, {{"res", PT_PID, PF_DEC}, {"exe", PT_CHARBUF, PF_NA}, {"args", PT_BYTEBUF, PF_NA}, {"tid", PT_PID, PF_DEC}, {"pid", PT_PID, PF_DEC}, {"ptid", PT_PID, PF_DEC}, {"cwd", PT_CHARBUF, PF_NA}, {"fdlimit", PT_INT64, PF_DEC}, {"pgft_maj", PT_UINT64, PF_DEC}, {"pgft_min", PT_UINT64, PF_DEC}, {"vm_size", PT_UINT32, PF_DEC}, {"vm_rss", PT_UINT32, PF_DEC}, {"vm_swap", PT_UINT32, PF_DEC}, {"comm", PT_CHARBUF, PF_NA}, {"cgroups", PT_BYTEBUF, PF_NA}, {"flags", PT_FLAGS32, PF_HEX, clone_flags}, {"uid", PT_UINT32, PF_DEC}, {"gid", PT_UINT32, PF_DEC}, {"vtid", PT_PID, PF_DEC}, {"vpid", PT_PID, PF_DEC}, {"pidns_init_start_ts", PT_UINT64, PF_DEC} } }, /* PPME_SYSCALL_OPEN_BY_HANDLE_AT_E */{"open_by_handle_at", EC_FILE | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 0}, /* PPME_SYSCALL_OPEN_BY_HANDLE_AT_X */{"open_by_handle_at", EC_FILE | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 4, {{"fd", PT_FD, PF_DEC}, {"mountfd", PT_FD, PF_DEC}, {"flags", PT_FLAGS32, PF_HEX, file_flags}, {"path", PT_FSPATH, PF_NA} } }, /* PPME_SYSCALL_IO_URING_SETUP_E */ {"io_uring_setup", EC_IO_OTHER | EC_SYSCALL, EF_CREATES_FD | EF_MODIFIES_STATE, 0}, diff --git a/userspace/libscap/scap.h b/userspace/libscap/scap.h index a5df36e23b..8135c2c7c9 100644 --- a/userspace/libscap/scap.h +++ b/userspace/libscap/scap.h @@ -292,6 +292,7 @@ typedef struct scap_threadinfo uint64_t exe_ino_ctime; ///< executable inode ctime (last status change time) uint64_t exe_ino_mtime; ///< executable inode mtime (last modification time) uint64_t exe_ino_ctime_duration_clone_ts; ///< duration in ns between executable inode ctime (last status change time) and clone_ts + uint64_t exe_ino_ctime_duration_pidns_start; ///< duration in ns between pidns start ts and executable inode ctime (last status change time) if pidns start predates ctime uint32_t vmsize_kb; ///< total virtual memory (as kb) uint32_t vmrss_kb; ///< resident non-swapped memory (as kb) uint32_t vmswap_kb; ///< swapped memory (as kb) @@ -299,6 +300,7 @@ typedef struct scap_threadinfo uint64_t pfminor; ///< number of minor page faults since start int64_t vtid; ///< The virtual id of this thread. int64_t vpid; ///< The virtual id of the process containing this thread. In single thread threads, this is equal to vtid. + uint64_t pidns_init_start_ts; ///