162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2020 Facebook */ 362306a36Sopenharmony_ci#include <vmlinux.h> 462306a36Sopenharmony_ci#include <bpf/bpf_core_read.h> 562306a36Sopenharmony_ci#include <bpf/bpf_helpers.h> 662306a36Sopenharmony_ci#include <bpf/bpf_tracing.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "profiler.h" 962306a36Sopenharmony_ci#include "err.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#ifndef NULL 1262306a36Sopenharmony_ci#define NULL 0 1362306a36Sopenharmony_ci#endif 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define O_WRONLY 00000001 1662306a36Sopenharmony_ci#define O_RDWR 00000002 1762306a36Sopenharmony_ci#define O_DIRECTORY 00200000 1862306a36Sopenharmony_ci#define __O_TMPFILE 020000000 1962306a36Sopenharmony_ci#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) 2062306a36Sopenharmony_ci#define S_IFMT 00170000 2162306a36Sopenharmony_ci#define S_IFSOCK 0140000 2262306a36Sopenharmony_ci#define S_IFLNK 0120000 2362306a36Sopenharmony_ci#define S_IFREG 0100000 2462306a36Sopenharmony_ci#define S_IFBLK 0060000 2562306a36Sopenharmony_ci#define S_IFDIR 0040000 2662306a36Sopenharmony_ci#define S_IFCHR 0020000 2762306a36Sopenharmony_ci#define S_IFIFO 0010000 2862306a36Sopenharmony_ci#define S_ISUID 0004000 2962306a36Sopenharmony_ci#define S_ISGID 0002000 3062306a36Sopenharmony_ci#define S_ISVTX 0001000 3162306a36Sopenharmony_ci#define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK) 3262306a36Sopenharmony_ci#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) 3362306a36Sopenharmony_ci#define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR) 3462306a36Sopenharmony_ci#define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK) 3562306a36Sopenharmony_ci#define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO) 3662306a36Sopenharmony_ci#define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define KILL_DATA_ARRAY_SIZE 8 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct var_kill_data_arr_t { 4162306a36Sopenharmony_ci struct var_kill_data_t array[KILL_DATA_ARRAY_SIZE]; 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ciunion any_profiler_data_t { 4562306a36Sopenharmony_ci struct var_exec_data_t var_exec; 4662306a36Sopenharmony_ci struct var_kill_data_t var_kill; 4762306a36Sopenharmony_ci struct var_sysctl_data_t var_sysctl; 4862306a36Sopenharmony_ci struct var_filemod_data_t var_filemod; 4962306a36Sopenharmony_ci struct var_fork_data_t var_fork; 5062306a36Sopenharmony_ci struct var_kill_data_arr_t var_kill_data_arr; 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_civolatile struct profiler_config_struct bpf_config = {}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define FETCH_CGROUPS_FROM_BPF (bpf_config.fetch_cgroups_from_bpf) 5662306a36Sopenharmony_ci#define CGROUP_FS_INODE (bpf_config.cgroup_fs_inode) 5762306a36Sopenharmony_ci#define CGROUP_LOGIN_SESSION_INODE \ 5862306a36Sopenharmony_ci (bpf_config.cgroup_login_session_inode) 5962306a36Sopenharmony_ci#define KILL_SIGNALS (bpf_config.kill_signals_mask) 6062306a36Sopenharmony_ci#define STALE_INFO (bpf_config.stale_info_secs) 6162306a36Sopenharmony_ci#define INODE_FILTER (bpf_config.inode_filter) 6262306a36Sopenharmony_ci#define READ_ENVIRON_FROM_EXEC (bpf_config.read_environ_from_exec) 6362306a36Sopenharmony_ci#define ENABLE_CGROUP_V1_RESOLVER (bpf_config.enable_cgroup_v1_resolver) 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistruct kernfs_iattrs___52 { 6662306a36Sopenharmony_ci struct iattr ia_iattr; 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistruct kernfs_node___52 { 7062306a36Sopenharmony_ci union /* kernfs_node_id */ { 7162306a36Sopenharmony_ci struct { 7262306a36Sopenharmony_ci u32 ino; 7362306a36Sopenharmony_ci u32 generation; 7462306a36Sopenharmony_ci }; 7562306a36Sopenharmony_ci u64 id; 7662306a36Sopenharmony_ci } id; 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistruct { 8062306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 8162306a36Sopenharmony_ci __uint(max_entries, 1); 8262306a36Sopenharmony_ci __type(key, u32); 8362306a36Sopenharmony_ci __type(value, union any_profiler_data_t); 8462306a36Sopenharmony_ci} data_heap SEC(".maps"); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistruct { 8762306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 8862306a36Sopenharmony_ci __uint(key_size, sizeof(int)); 8962306a36Sopenharmony_ci __uint(value_size, sizeof(int)); 9062306a36Sopenharmony_ci} events SEC(".maps"); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistruct { 9362306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 9462306a36Sopenharmony_ci __uint(max_entries, KILL_DATA_ARRAY_SIZE); 9562306a36Sopenharmony_ci __type(key, u32); 9662306a36Sopenharmony_ci __type(value, struct var_kill_data_arr_t); 9762306a36Sopenharmony_ci} var_tpid_to_data SEC(".maps"); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct { 10062306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); 10162306a36Sopenharmony_ci __uint(max_entries, profiler_bpf_max_function_id); 10262306a36Sopenharmony_ci __type(key, u32); 10362306a36Sopenharmony_ci __type(value, struct bpf_func_stats_data); 10462306a36Sopenharmony_ci} bpf_func_stats SEC(".maps"); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistruct { 10762306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 10862306a36Sopenharmony_ci __type(key, u32); 10962306a36Sopenharmony_ci __type(value, bool); 11062306a36Sopenharmony_ci __uint(max_entries, 16); 11162306a36Sopenharmony_ci} allowed_devices SEC(".maps"); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistruct { 11462306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 11562306a36Sopenharmony_ci __type(key, u64); 11662306a36Sopenharmony_ci __type(value, bool); 11762306a36Sopenharmony_ci __uint(max_entries, 1024); 11862306a36Sopenharmony_ci} allowed_file_inodes SEC(".maps"); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistruct { 12162306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 12262306a36Sopenharmony_ci __type(key, u64); 12362306a36Sopenharmony_ci __type(value, bool); 12462306a36Sopenharmony_ci __uint(max_entries, 1024); 12562306a36Sopenharmony_ci} allowed_directory_inodes SEC(".maps"); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistruct { 12862306a36Sopenharmony_ci __uint(type, BPF_MAP_TYPE_HASH); 12962306a36Sopenharmony_ci __type(key, u32); 13062306a36Sopenharmony_ci __type(value, bool); 13162306a36Sopenharmony_ci __uint(max_entries, 16); 13262306a36Sopenharmony_ci} disallowed_exec_inodes SEC(".maps"); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#ifndef ARRAY_SIZE 13562306a36Sopenharmony_ci#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) 13662306a36Sopenharmony_ci#endif 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic INLINE bool IS_ERR(const void* ptr) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci return IS_ERR_VALUE((unsigned long)ptr); 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic INLINE u32 get_userspace_pid() 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci return bpf_get_current_pid_tgid() >> 32; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic INLINE bool is_init_process(u32 tgid) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci return tgid == 1 || tgid == 0; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_cistatic INLINE unsigned long 15462306a36Sopenharmony_ciprobe_read_lim(void* dst, void* src, unsigned long len, unsigned long max) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci len = len < max ? len : max; 15762306a36Sopenharmony_ci if (len > 1) { 15862306a36Sopenharmony_ci if (bpf_probe_read_kernel(dst, len, src)) 15962306a36Sopenharmony_ci return 0; 16062306a36Sopenharmony_ci } else if (len == 1) { 16162306a36Sopenharmony_ci if (bpf_probe_read_kernel(dst, 1, src)) 16262306a36Sopenharmony_ci return 0; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci return len; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic INLINE int get_var_spid_index(struct var_kill_data_arr_t* arr_struct, 16862306a36Sopenharmony_ci int spid) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci#ifdef UNROLL 17162306a36Sopenharmony_ci#pragma unroll 17262306a36Sopenharmony_ci#endif 17362306a36Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++) 17462306a36Sopenharmony_ci if (arr_struct->array[i].meta.pid == spid) 17562306a36Sopenharmony_ci return i; 17662306a36Sopenharmony_ci return -1; 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic INLINE void populate_ancestors(struct task_struct* task, 18062306a36Sopenharmony_ci struct ancestors_data_t* ancestors_data) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci struct task_struct* parent = task; 18362306a36Sopenharmony_ci u32 num_ancestors, ppid; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci ancestors_data->num_ancestors = 0; 18662306a36Sopenharmony_ci#ifdef UNROLL 18762306a36Sopenharmony_ci#pragma unroll 18862306a36Sopenharmony_ci#endif 18962306a36Sopenharmony_ci for (num_ancestors = 0; num_ancestors < MAX_ANCESTORS; num_ancestors++) { 19062306a36Sopenharmony_ci parent = BPF_CORE_READ(parent, real_parent); 19162306a36Sopenharmony_ci if (parent == NULL) 19262306a36Sopenharmony_ci break; 19362306a36Sopenharmony_ci ppid = BPF_CORE_READ(parent, tgid); 19462306a36Sopenharmony_ci if (is_init_process(ppid)) 19562306a36Sopenharmony_ci break; 19662306a36Sopenharmony_ci ancestors_data->ancestor_pids[num_ancestors] = ppid; 19762306a36Sopenharmony_ci ancestors_data->ancestor_exec_ids[num_ancestors] = 19862306a36Sopenharmony_ci BPF_CORE_READ(parent, self_exec_id); 19962306a36Sopenharmony_ci ancestors_data->ancestor_start_times[num_ancestors] = 20062306a36Sopenharmony_ci BPF_CORE_READ(parent, start_time); 20162306a36Sopenharmony_ci ancestors_data->num_ancestors = num_ancestors; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic INLINE void* read_full_cgroup_path(struct kernfs_node* cgroup_node, 20662306a36Sopenharmony_ci struct kernfs_node* cgroup_root_node, 20762306a36Sopenharmony_ci void* payload, 20862306a36Sopenharmony_ci int* root_pos) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci void* payload_start = payload; 21162306a36Sopenharmony_ci size_t filepart_length; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci#ifdef UNROLL 21462306a36Sopenharmony_ci#pragma unroll 21562306a36Sopenharmony_ci#endif 21662306a36Sopenharmony_ci for (int i = 0; i < MAX_CGROUPS_PATH_DEPTH; i++) { 21762306a36Sopenharmony_ci filepart_length = 21862306a36Sopenharmony_ci bpf_probe_read_kernel_str(payload, MAX_PATH, 21962306a36Sopenharmony_ci BPF_CORE_READ(cgroup_node, name)); 22062306a36Sopenharmony_ci if (!cgroup_node) 22162306a36Sopenharmony_ci return payload; 22262306a36Sopenharmony_ci if (cgroup_node == cgroup_root_node) 22362306a36Sopenharmony_ci *root_pos = payload - payload_start; 22462306a36Sopenharmony_ci if (filepart_length <= MAX_PATH) { 22562306a36Sopenharmony_ci barrier_var(filepart_length); 22662306a36Sopenharmony_ci payload += filepart_length; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci cgroup_node = BPF_CORE_READ(cgroup_node, parent); 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci return payload; 23162306a36Sopenharmony_ci} 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cistatic ino_t get_inode_from_kernfs(struct kernfs_node* node) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct kernfs_node___52* node52 = (void*)node; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci if (bpf_core_field_exists(node52->id.ino)) { 23862306a36Sopenharmony_ci barrier_var(node52); 23962306a36Sopenharmony_ci return BPF_CORE_READ(node52, id.ino); 24062306a36Sopenharmony_ci } else { 24162306a36Sopenharmony_ci barrier_var(node); 24262306a36Sopenharmony_ci return (u64)BPF_CORE_READ(node, id); 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ciextern bool CONFIG_CGROUP_PIDS __kconfig __weak; 24762306a36Sopenharmony_cienum cgroup_subsys_id___local { 24862306a36Sopenharmony_ci pids_cgrp_id___local = 123, /* value doesn't matter */ 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic INLINE void* populate_cgroup_info(struct cgroup_data_t* cgroup_data, 25262306a36Sopenharmony_ci struct task_struct* task, 25362306a36Sopenharmony_ci void* payload) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct kernfs_node* root_kernfs = 25662306a36Sopenharmony_ci BPF_CORE_READ(task, nsproxy, cgroup_ns, root_cset, dfl_cgrp, kn); 25762306a36Sopenharmony_ci struct kernfs_node* proc_kernfs = BPF_CORE_READ(task, cgroups, dfl_cgrp, kn); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci#if __has_builtin(__builtin_preserve_enum_value) 26062306a36Sopenharmony_ci if (ENABLE_CGROUP_V1_RESOLVER && CONFIG_CGROUP_PIDS) { 26162306a36Sopenharmony_ci int cgrp_id = bpf_core_enum_value(enum cgroup_subsys_id___local, 26262306a36Sopenharmony_ci pids_cgrp_id___local); 26362306a36Sopenharmony_ci#ifdef UNROLL 26462306a36Sopenharmony_ci#pragma unroll 26562306a36Sopenharmony_ci#endif 26662306a36Sopenharmony_ci for (int i = 0; i < CGROUP_SUBSYS_COUNT; i++) { 26762306a36Sopenharmony_ci struct cgroup_subsys_state* subsys = 26862306a36Sopenharmony_ci BPF_CORE_READ(task, cgroups, subsys[i]); 26962306a36Sopenharmony_ci if (subsys != NULL) { 27062306a36Sopenharmony_ci int subsys_id = BPF_CORE_READ(subsys, ss, id); 27162306a36Sopenharmony_ci if (subsys_id == cgrp_id) { 27262306a36Sopenharmony_ci proc_kernfs = BPF_CORE_READ(subsys, cgroup, kn); 27362306a36Sopenharmony_ci root_kernfs = BPF_CORE_READ(subsys, ss, root, kf_root, kn); 27462306a36Sopenharmony_ci break; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci#endif 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci cgroup_data->cgroup_root_inode = get_inode_from_kernfs(root_kernfs); 28262306a36Sopenharmony_ci cgroup_data->cgroup_proc_inode = get_inode_from_kernfs(proc_kernfs); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if (bpf_core_field_exists(root_kernfs->iattr->ia_mtime)) { 28562306a36Sopenharmony_ci cgroup_data->cgroup_root_mtime = 28662306a36Sopenharmony_ci BPF_CORE_READ(root_kernfs, iattr, ia_mtime.tv_nsec); 28762306a36Sopenharmony_ci cgroup_data->cgroup_proc_mtime = 28862306a36Sopenharmony_ci BPF_CORE_READ(proc_kernfs, iattr, ia_mtime.tv_nsec); 28962306a36Sopenharmony_ci } else { 29062306a36Sopenharmony_ci struct kernfs_iattrs___52* root_iattr = 29162306a36Sopenharmony_ci (struct kernfs_iattrs___52*)BPF_CORE_READ(root_kernfs, iattr); 29262306a36Sopenharmony_ci cgroup_data->cgroup_root_mtime = 29362306a36Sopenharmony_ci BPF_CORE_READ(root_iattr, ia_iattr.ia_mtime.tv_nsec); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci struct kernfs_iattrs___52* proc_iattr = 29662306a36Sopenharmony_ci (struct kernfs_iattrs___52*)BPF_CORE_READ(proc_kernfs, iattr); 29762306a36Sopenharmony_ci cgroup_data->cgroup_proc_mtime = 29862306a36Sopenharmony_ci BPF_CORE_READ(proc_iattr, ia_iattr.ia_mtime.tv_nsec); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci cgroup_data->cgroup_root_length = 0; 30262306a36Sopenharmony_ci cgroup_data->cgroup_proc_length = 0; 30362306a36Sopenharmony_ci cgroup_data->cgroup_full_length = 0; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci size_t cgroup_root_length = 30662306a36Sopenharmony_ci bpf_probe_read_kernel_str(payload, MAX_PATH, 30762306a36Sopenharmony_ci BPF_CORE_READ(root_kernfs, name)); 30862306a36Sopenharmony_ci barrier_var(cgroup_root_length); 30962306a36Sopenharmony_ci if (cgroup_root_length <= MAX_PATH) { 31062306a36Sopenharmony_ci barrier_var(cgroup_root_length); 31162306a36Sopenharmony_ci cgroup_data->cgroup_root_length = cgroup_root_length; 31262306a36Sopenharmony_ci payload += cgroup_root_length; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci size_t cgroup_proc_length = 31662306a36Sopenharmony_ci bpf_probe_read_kernel_str(payload, MAX_PATH, 31762306a36Sopenharmony_ci BPF_CORE_READ(proc_kernfs, name)); 31862306a36Sopenharmony_ci barrier_var(cgroup_proc_length); 31962306a36Sopenharmony_ci if (cgroup_proc_length <= MAX_PATH) { 32062306a36Sopenharmony_ci barrier_var(cgroup_proc_length); 32162306a36Sopenharmony_ci cgroup_data->cgroup_proc_length = cgroup_proc_length; 32262306a36Sopenharmony_ci payload += cgroup_proc_length; 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (FETCH_CGROUPS_FROM_BPF) { 32662306a36Sopenharmony_ci cgroup_data->cgroup_full_path_root_pos = -1; 32762306a36Sopenharmony_ci void* payload_end_pos = read_full_cgroup_path(proc_kernfs, root_kernfs, payload, 32862306a36Sopenharmony_ci &cgroup_data->cgroup_full_path_root_pos); 32962306a36Sopenharmony_ci cgroup_data->cgroup_full_length = payload_end_pos - payload; 33062306a36Sopenharmony_ci payload = payload_end_pos; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return (void*)payload; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cistatic INLINE void* populate_var_metadata(struct var_metadata_t* metadata, 33762306a36Sopenharmony_ci struct task_struct* task, 33862306a36Sopenharmony_ci u32 pid, void* payload) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci u64 uid_gid = bpf_get_current_uid_gid(); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci metadata->uid = (u32)uid_gid; 34362306a36Sopenharmony_ci metadata->gid = uid_gid >> 32; 34462306a36Sopenharmony_ci metadata->pid = pid; 34562306a36Sopenharmony_ci metadata->exec_id = BPF_CORE_READ(task, self_exec_id); 34662306a36Sopenharmony_ci metadata->start_time = BPF_CORE_READ(task, start_time); 34762306a36Sopenharmony_ci metadata->comm_length = 0; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci size_t comm_length = bpf_core_read_str(payload, TASK_COMM_LEN, &task->comm); 35062306a36Sopenharmony_ci barrier_var(comm_length); 35162306a36Sopenharmony_ci if (comm_length <= TASK_COMM_LEN) { 35262306a36Sopenharmony_ci barrier_var(comm_length); 35362306a36Sopenharmony_ci metadata->comm_length = comm_length; 35462306a36Sopenharmony_ci payload += comm_length; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci return (void*)payload; 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic INLINE struct var_kill_data_t* 36162306a36Sopenharmony_ciget_var_kill_data(struct pt_regs* ctx, int spid, int tpid, int sig) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci int zero = 0; 36462306a36Sopenharmony_ci struct var_kill_data_t* kill_data = bpf_map_lookup_elem(&data_heap, &zero); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci if (kill_data == NULL) 36762306a36Sopenharmony_ci return NULL; 36862306a36Sopenharmony_ci struct task_struct* task = (struct task_struct*)bpf_get_current_task(); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci void* payload = populate_var_metadata(&kill_data->meta, task, spid, kill_data->payload); 37162306a36Sopenharmony_ci payload = populate_cgroup_info(&kill_data->cgroup_data, task, payload); 37262306a36Sopenharmony_ci size_t payload_length = payload - (void*)kill_data->payload; 37362306a36Sopenharmony_ci kill_data->payload_length = payload_length; 37462306a36Sopenharmony_ci populate_ancestors(task, &kill_data->ancestors_info); 37562306a36Sopenharmony_ci kill_data->meta.type = KILL_EVENT; 37662306a36Sopenharmony_ci kill_data->kill_target_pid = tpid; 37762306a36Sopenharmony_ci kill_data->kill_sig = sig; 37862306a36Sopenharmony_ci kill_data->kill_count = 1; 37962306a36Sopenharmony_ci kill_data->last_kill_time = bpf_ktime_get_ns(); 38062306a36Sopenharmony_ci return kill_data; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic INLINE int trace_var_sys_kill(void* ctx, int tpid, int sig) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci if ((KILL_SIGNALS & (1ULL << sig)) == 0) 38662306a36Sopenharmony_ci return 0; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci u32 spid = get_userspace_pid(); 38962306a36Sopenharmony_ci struct var_kill_data_arr_t* arr_struct = bpf_map_lookup_elem(&var_tpid_to_data, &tpid); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (arr_struct == NULL) { 39262306a36Sopenharmony_ci struct var_kill_data_t* kill_data = get_var_kill_data(ctx, spid, tpid, sig); 39362306a36Sopenharmony_ci int zero = 0; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci if (kill_data == NULL) 39662306a36Sopenharmony_ci return 0; 39762306a36Sopenharmony_ci arr_struct = bpf_map_lookup_elem(&data_heap, &zero); 39862306a36Sopenharmony_ci if (arr_struct == NULL) 39962306a36Sopenharmony_ci return 0; 40062306a36Sopenharmony_ci bpf_probe_read_kernel(&arr_struct->array[0], 40162306a36Sopenharmony_ci sizeof(arr_struct->array[0]), kill_data); 40262306a36Sopenharmony_ci } else { 40362306a36Sopenharmony_ci int index = get_var_spid_index(arr_struct, spid); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (index == -1) { 40662306a36Sopenharmony_ci struct var_kill_data_t* kill_data = 40762306a36Sopenharmony_ci get_var_kill_data(ctx, spid, tpid, sig); 40862306a36Sopenharmony_ci if (kill_data == NULL) 40962306a36Sopenharmony_ci return 0; 41062306a36Sopenharmony_ci#ifdef UNROLL 41162306a36Sopenharmony_ci#pragma unroll 41262306a36Sopenharmony_ci#endif 41362306a36Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++) 41462306a36Sopenharmony_ci if (arr_struct->array[i].meta.pid == 0) { 41562306a36Sopenharmony_ci bpf_probe_read_kernel(&arr_struct->array[i], 41662306a36Sopenharmony_ci sizeof(arr_struct->array[i]), 41762306a36Sopenharmony_ci kill_data); 41862306a36Sopenharmony_ci bpf_map_update_elem(&var_tpid_to_data, &tpid, 41962306a36Sopenharmony_ci arr_struct, 0); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci return 0; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci return 0; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci struct var_kill_data_t* kill_data = &arr_struct->array[index]; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci u64 delta_sec = 42962306a36Sopenharmony_ci (bpf_ktime_get_ns() - kill_data->last_kill_time) / 1000000000; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (delta_sec < STALE_INFO) { 43262306a36Sopenharmony_ci kill_data->kill_count++; 43362306a36Sopenharmony_ci kill_data->last_kill_time = bpf_ktime_get_ns(); 43462306a36Sopenharmony_ci bpf_probe_read_kernel(&arr_struct->array[index], 43562306a36Sopenharmony_ci sizeof(arr_struct->array[index]), 43662306a36Sopenharmony_ci kill_data); 43762306a36Sopenharmony_ci } else { 43862306a36Sopenharmony_ci struct var_kill_data_t* kill_data = 43962306a36Sopenharmony_ci get_var_kill_data(ctx, spid, tpid, sig); 44062306a36Sopenharmony_ci if (kill_data == NULL) 44162306a36Sopenharmony_ci return 0; 44262306a36Sopenharmony_ci bpf_probe_read_kernel(&arr_struct->array[index], 44362306a36Sopenharmony_ci sizeof(arr_struct->array[index]), 44462306a36Sopenharmony_ci kill_data); 44562306a36Sopenharmony_ci } 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci bpf_map_update_elem(&var_tpid_to_data, &tpid, arr_struct, 0); 44862306a36Sopenharmony_ci return 0; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic INLINE void bpf_stats_enter(struct bpf_func_stats_ctx* bpf_stat_ctx, 45262306a36Sopenharmony_ci enum bpf_function_id func_id) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci int func_id_key = func_id; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci bpf_stat_ctx->start_time_ns = bpf_ktime_get_ns(); 45762306a36Sopenharmony_ci bpf_stat_ctx->bpf_func_stats_data_val = 45862306a36Sopenharmony_ci bpf_map_lookup_elem(&bpf_func_stats, &func_id_key); 45962306a36Sopenharmony_ci if (bpf_stat_ctx->bpf_func_stats_data_val) 46062306a36Sopenharmony_ci bpf_stat_ctx->bpf_func_stats_data_val->num_executions++; 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic INLINE void bpf_stats_exit(struct bpf_func_stats_ctx* bpf_stat_ctx) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci if (bpf_stat_ctx->bpf_func_stats_data_val) 46662306a36Sopenharmony_ci bpf_stat_ctx->bpf_func_stats_data_val->time_elapsed_ns += 46762306a36Sopenharmony_ci bpf_ktime_get_ns() - bpf_stat_ctx->start_time_ns; 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic INLINE void 47162306a36Sopenharmony_cibpf_stats_pre_submit_var_perf_event(struct bpf_func_stats_ctx* bpf_stat_ctx, 47262306a36Sopenharmony_ci struct var_metadata_t* meta) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci if (bpf_stat_ctx->bpf_func_stats_data_val) { 47562306a36Sopenharmony_ci bpf_stat_ctx->bpf_func_stats_data_val->num_perf_events++; 47662306a36Sopenharmony_ci meta->bpf_stats_num_perf_events = 47762306a36Sopenharmony_ci bpf_stat_ctx->bpf_func_stats_data_val->num_perf_events; 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci meta->bpf_stats_start_ktime_ns = bpf_stat_ctx->start_time_ns; 48062306a36Sopenharmony_ci meta->cpu_id = bpf_get_smp_processor_id(); 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic INLINE size_t 48462306a36Sopenharmony_ciread_absolute_file_path_from_dentry(struct dentry* filp_dentry, void* payload) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci size_t length = 0; 48762306a36Sopenharmony_ci size_t filepart_length; 48862306a36Sopenharmony_ci struct dentry* parent_dentry; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci#ifdef UNROLL 49162306a36Sopenharmony_ci#pragma unroll 49262306a36Sopenharmony_ci#endif 49362306a36Sopenharmony_ci for (int i = 0; i < MAX_PATH_DEPTH; i++) { 49462306a36Sopenharmony_ci filepart_length = 49562306a36Sopenharmony_ci bpf_probe_read_kernel_str(payload, MAX_PATH, 49662306a36Sopenharmony_ci BPF_CORE_READ(filp_dentry, d_name.name)); 49762306a36Sopenharmony_ci barrier_var(filepart_length); 49862306a36Sopenharmony_ci if (filepart_length > MAX_PATH) 49962306a36Sopenharmony_ci break; 50062306a36Sopenharmony_ci barrier_var(filepart_length); 50162306a36Sopenharmony_ci payload += filepart_length; 50262306a36Sopenharmony_ci length += filepart_length; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci parent_dentry = BPF_CORE_READ(filp_dentry, d_parent); 50562306a36Sopenharmony_ci if (filp_dentry == parent_dentry) 50662306a36Sopenharmony_ci break; 50762306a36Sopenharmony_ci filp_dentry = parent_dentry; 50862306a36Sopenharmony_ci } 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci return length; 51162306a36Sopenharmony_ci} 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_cistatic INLINE bool 51462306a36Sopenharmony_ciis_ancestor_in_allowed_inodes(struct dentry* filp_dentry) 51562306a36Sopenharmony_ci{ 51662306a36Sopenharmony_ci struct dentry* parent_dentry; 51762306a36Sopenharmony_ci#ifdef UNROLL 51862306a36Sopenharmony_ci#pragma unroll 51962306a36Sopenharmony_ci#endif 52062306a36Sopenharmony_ci for (int i = 0; i < MAX_PATH_DEPTH; i++) { 52162306a36Sopenharmony_ci u64 dir_ino = BPF_CORE_READ(filp_dentry, d_inode, i_ino); 52262306a36Sopenharmony_ci bool* allowed_dir = bpf_map_lookup_elem(&allowed_directory_inodes, &dir_ino); 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (allowed_dir != NULL) 52562306a36Sopenharmony_ci return true; 52662306a36Sopenharmony_ci parent_dentry = BPF_CORE_READ(filp_dentry, d_parent); 52762306a36Sopenharmony_ci if (filp_dentry == parent_dentry) 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci filp_dentry = parent_dentry; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci return false; 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_cistatic INLINE bool is_dentry_allowed_for_filemod(struct dentry* file_dentry, 53562306a36Sopenharmony_ci u32* device_id, 53662306a36Sopenharmony_ci u64* file_ino) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci u32 dev_id = BPF_CORE_READ(file_dentry, d_sb, s_dev); 53962306a36Sopenharmony_ci *device_id = dev_id; 54062306a36Sopenharmony_ci bool* allowed_device = bpf_map_lookup_elem(&allowed_devices, &dev_id); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci if (allowed_device == NULL) 54362306a36Sopenharmony_ci return false; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci u64 ino = BPF_CORE_READ(file_dentry, d_inode, i_ino); 54662306a36Sopenharmony_ci *file_ino = ino; 54762306a36Sopenharmony_ci bool* allowed_file = bpf_map_lookup_elem(&allowed_file_inodes, &ino); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci if (allowed_file == NULL) 55062306a36Sopenharmony_ci if (!is_ancestor_in_allowed_inodes(BPF_CORE_READ(file_dentry, d_parent))) 55162306a36Sopenharmony_ci return false; 55262306a36Sopenharmony_ci return true; 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ciSEC("kprobe/proc_sys_write") 55662306a36Sopenharmony_cissize_t BPF_KPROBE(kprobe__proc_sys_write, 55762306a36Sopenharmony_ci struct file* filp, const char* buf, 55862306a36Sopenharmony_ci size_t count, loff_t* ppos) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 56162306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_proc_sys_write); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci u32 pid = get_userspace_pid(); 56462306a36Sopenharmony_ci int zero = 0; 56562306a36Sopenharmony_ci struct var_sysctl_data_t* sysctl_data = 56662306a36Sopenharmony_ci bpf_map_lookup_elem(&data_heap, &zero); 56762306a36Sopenharmony_ci if (!sysctl_data) 56862306a36Sopenharmony_ci goto out; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci struct task_struct* task = (struct task_struct*)bpf_get_current_task(); 57162306a36Sopenharmony_ci sysctl_data->meta.type = SYSCTL_EVENT; 57262306a36Sopenharmony_ci void* payload = populate_var_metadata(&sysctl_data->meta, task, pid, sysctl_data->payload); 57362306a36Sopenharmony_ci payload = populate_cgroup_info(&sysctl_data->cgroup_data, task, payload); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci populate_ancestors(task, &sysctl_data->ancestors_info); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci sysctl_data->sysctl_val_length = 0; 57862306a36Sopenharmony_ci sysctl_data->sysctl_path_length = 0; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci size_t sysctl_val_length = bpf_probe_read_kernel_str(payload, 58162306a36Sopenharmony_ci CTL_MAXNAME, buf); 58262306a36Sopenharmony_ci barrier_var(sysctl_val_length); 58362306a36Sopenharmony_ci if (sysctl_val_length <= CTL_MAXNAME) { 58462306a36Sopenharmony_ci barrier_var(sysctl_val_length); 58562306a36Sopenharmony_ci sysctl_data->sysctl_val_length = sysctl_val_length; 58662306a36Sopenharmony_ci payload += sysctl_val_length; 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci size_t sysctl_path_length = 59062306a36Sopenharmony_ci bpf_probe_read_kernel_str(payload, MAX_PATH, 59162306a36Sopenharmony_ci BPF_CORE_READ(filp, f_path.dentry, 59262306a36Sopenharmony_ci d_name.name)); 59362306a36Sopenharmony_ci barrier_var(sysctl_path_length); 59462306a36Sopenharmony_ci if (sysctl_path_length <= MAX_PATH) { 59562306a36Sopenharmony_ci barrier_var(sysctl_path_length); 59662306a36Sopenharmony_ci sysctl_data->sysctl_path_length = sysctl_path_length; 59762306a36Sopenharmony_ci payload += sysctl_path_length; 59862306a36Sopenharmony_ci } 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci bpf_stats_pre_submit_var_perf_event(&stats_ctx, &sysctl_data->meta); 60162306a36Sopenharmony_ci unsigned long data_len = payload - (void*)sysctl_data; 60262306a36Sopenharmony_ci data_len = data_len > sizeof(struct var_sysctl_data_t) 60362306a36Sopenharmony_ci ? sizeof(struct var_sysctl_data_t) 60462306a36Sopenharmony_ci : data_len; 60562306a36Sopenharmony_ci bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, sysctl_data, data_len); 60662306a36Sopenharmony_ciout: 60762306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 60862306a36Sopenharmony_ci return 0; 60962306a36Sopenharmony_ci} 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ciSEC("tracepoint/syscalls/sys_enter_kill") 61262306a36Sopenharmony_ciint tracepoint__syscalls__sys_enter_kill(struct trace_event_raw_sys_enter* ctx) 61362306a36Sopenharmony_ci{ 61462306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_sys_enter_kill); 61762306a36Sopenharmony_ci int pid = ctx->args[0]; 61862306a36Sopenharmony_ci int sig = ctx->args[1]; 61962306a36Sopenharmony_ci int ret = trace_var_sys_kill(ctx, pid, sig); 62062306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 62162306a36Sopenharmony_ci return ret; 62262306a36Sopenharmony_ci}; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ciSEC("raw_tracepoint/sched_process_exit") 62562306a36Sopenharmony_ciint raw_tracepoint__sched_process_exit(void* ctx) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci int zero = 0; 62862306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 62962306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_sched_process_exit); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci u32 tpid = get_userspace_pid(); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci struct var_kill_data_arr_t* arr_struct = bpf_map_lookup_elem(&var_tpid_to_data, &tpid); 63462306a36Sopenharmony_ci struct var_kill_data_t* kill_data = bpf_map_lookup_elem(&data_heap, &zero); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci if (arr_struct == NULL || kill_data == NULL) 63762306a36Sopenharmony_ci goto out; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci struct task_struct* task = (struct task_struct*)bpf_get_current_task(); 64062306a36Sopenharmony_ci struct kernfs_node* proc_kernfs = BPF_CORE_READ(task, cgroups, dfl_cgrp, kn); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci#ifdef UNROLL 64362306a36Sopenharmony_ci#pragma unroll 64462306a36Sopenharmony_ci#endif 64562306a36Sopenharmony_ci for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++) { 64662306a36Sopenharmony_ci struct var_kill_data_t* past_kill_data = &arr_struct->array[i]; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci if (past_kill_data != NULL && past_kill_data->kill_target_pid == tpid) { 64962306a36Sopenharmony_ci bpf_probe_read_kernel(kill_data, sizeof(*past_kill_data), 65062306a36Sopenharmony_ci past_kill_data); 65162306a36Sopenharmony_ci void* payload = kill_data->payload; 65262306a36Sopenharmony_ci size_t offset = kill_data->payload_length; 65362306a36Sopenharmony_ci if (offset >= MAX_METADATA_PAYLOAD_LEN + MAX_CGROUP_PAYLOAD_LEN) 65462306a36Sopenharmony_ci return 0; 65562306a36Sopenharmony_ci payload += offset; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci kill_data->kill_target_name_length = 0; 65862306a36Sopenharmony_ci kill_data->kill_target_cgroup_proc_length = 0; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci size_t comm_length = bpf_core_read_str(payload, TASK_COMM_LEN, &task->comm); 66162306a36Sopenharmony_ci barrier_var(comm_length); 66262306a36Sopenharmony_ci if (comm_length <= TASK_COMM_LEN) { 66362306a36Sopenharmony_ci barrier_var(comm_length); 66462306a36Sopenharmony_ci kill_data->kill_target_name_length = comm_length; 66562306a36Sopenharmony_ci payload += comm_length; 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci size_t cgroup_proc_length = 66962306a36Sopenharmony_ci bpf_probe_read_kernel_str(payload, 67062306a36Sopenharmony_ci KILL_TARGET_LEN, 67162306a36Sopenharmony_ci BPF_CORE_READ(proc_kernfs, name)); 67262306a36Sopenharmony_ci barrier_var(cgroup_proc_length); 67362306a36Sopenharmony_ci if (cgroup_proc_length <= KILL_TARGET_LEN) { 67462306a36Sopenharmony_ci barrier_var(cgroup_proc_length); 67562306a36Sopenharmony_ci kill_data->kill_target_cgroup_proc_length = cgroup_proc_length; 67662306a36Sopenharmony_ci payload += cgroup_proc_length; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci bpf_stats_pre_submit_var_perf_event(&stats_ctx, &kill_data->meta); 68062306a36Sopenharmony_ci unsigned long data_len = (void*)payload - (void*)kill_data; 68162306a36Sopenharmony_ci data_len = data_len > sizeof(struct var_kill_data_t) 68262306a36Sopenharmony_ci ? sizeof(struct var_kill_data_t) 68362306a36Sopenharmony_ci : data_len; 68462306a36Sopenharmony_ci bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, kill_data, data_len); 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci bpf_map_delete_elem(&var_tpid_to_data, &tpid); 68862306a36Sopenharmony_ciout: 68962306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 69062306a36Sopenharmony_ci return 0; 69162306a36Sopenharmony_ci} 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ciSEC("raw_tracepoint/sched_process_exec") 69462306a36Sopenharmony_ciint raw_tracepoint__sched_process_exec(struct bpf_raw_tracepoint_args* ctx) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 69762306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_sched_process_exec); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci struct linux_binprm* bprm = (struct linux_binprm*)ctx->args[2]; 70062306a36Sopenharmony_ci u64 inode = BPF_CORE_READ(bprm, file, f_inode, i_ino); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci bool* should_filter_binprm = bpf_map_lookup_elem(&disallowed_exec_inodes, &inode); 70362306a36Sopenharmony_ci if (should_filter_binprm != NULL) 70462306a36Sopenharmony_ci goto out; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci int zero = 0; 70762306a36Sopenharmony_ci struct var_exec_data_t* proc_exec_data = bpf_map_lookup_elem(&data_heap, &zero); 70862306a36Sopenharmony_ci if (!proc_exec_data) 70962306a36Sopenharmony_ci goto out; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci if (INODE_FILTER && inode != INODE_FILTER) 71262306a36Sopenharmony_ci return 0; 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci u32 pid = get_userspace_pid(); 71562306a36Sopenharmony_ci struct task_struct* task = (struct task_struct*)bpf_get_current_task(); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci proc_exec_data->meta.type = EXEC_EVENT; 71862306a36Sopenharmony_ci proc_exec_data->bin_path_length = 0; 71962306a36Sopenharmony_ci proc_exec_data->cmdline_length = 0; 72062306a36Sopenharmony_ci proc_exec_data->environment_length = 0; 72162306a36Sopenharmony_ci void* payload = populate_var_metadata(&proc_exec_data->meta, task, pid, 72262306a36Sopenharmony_ci proc_exec_data->payload); 72362306a36Sopenharmony_ci payload = populate_cgroup_info(&proc_exec_data->cgroup_data, task, payload); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci struct task_struct* parent_task = BPF_CORE_READ(task, real_parent); 72662306a36Sopenharmony_ci proc_exec_data->parent_pid = BPF_CORE_READ(parent_task, tgid); 72762306a36Sopenharmony_ci proc_exec_data->parent_uid = BPF_CORE_READ(parent_task, real_cred, uid.val); 72862306a36Sopenharmony_ci proc_exec_data->parent_exec_id = BPF_CORE_READ(parent_task, self_exec_id); 72962306a36Sopenharmony_ci proc_exec_data->parent_start_time = BPF_CORE_READ(parent_task, start_time); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci const char* filename = BPF_CORE_READ(bprm, filename); 73262306a36Sopenharmony_ci size_t bin_path_length = 73362306a36Sopenharmony_ci bpf_probe_read_kernel_str(payload, MAX_FILENAME_LEN, filename); 73462306a36Sopenharmony_ci barrier_var(bin_path_length); 73562306a36Sopenharmony_ci if (bin_path_length <= MAX_FILENAME_LEN) { 73662306a36Sopenharmony_ci barrier_var(bin_path_length); 73762306a36Sopenharmony_ci proc_exec_data->bin_path_length = bin_path_length; 73862306a36Sopenharmony_ci payload += bin_path_length; 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci void* arg_start = (void*)BPF_CORE_READ(task, mm, arg_start); 74262306a36Sopenharmony_ci void* arg_end = (void*)BPF_CORE_READ(task, mm, arg_end); 74362306a36Sopenharmony_ci unsigned int cmdline_length = probe_read_lim(payload, arg_start, 74462306a36Sopenharmony_ci arg_end - arg_start, MAX_ARGS_LEN); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci if (cmdline_length <= MAX_ARGS_LEN) { 74762306a36Sopenharmony_ci barrier_var(cmdline_length); 74862306a36Sopenharmony_ci proc_exec_data->cmdline_length = cmdline_length; 74962306a36Sopenharmony_ci payload += cmdline_length; 75062306a36Sopenharmony_ci } 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci if (READ_ENVIRON_FROM_EXEC) { 75362306a36Sopenharmony_ci void* env_start = (void*)BPF_CORE_READ(task, mm, env_start); 75462306a36Sopenharmony_ci void* env_end = (void*)BPF_CORE_READ(task, mm, env_end); 75562306a36Sopenharmony_ci unsigned long env_len = probe_read_lim(payload, env_start, 75662306a36Sopenharmony_ci env_end - env_start, MAX_ENVIRON_LEN); 75762306a36Sopenharmony_ci if (cmdline_length <= MAX_ENVIRON_LEN) { 75862306a36Sopenharmony_ci proc_exec_data->environment_length = env_len; 75962306a36Sopenharmony_ci payload += env_len; 76062306a36Sopenharmony_ci } 76162306a36Sopenharmony_ci } 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci bpf_stats_pre_submit_var_perf_event(&stats_ctx, &proc_exec_data->meta); 76462306a36Sopenharmony_ci unsigned long data_len = payload - (void*)proc_exec_data; 76562306a36Sopenharmony_ci data_len = data_len > sizeof(struct var_exec_data_t) 76662306a36Sopenharmony_ci ? sizeof(struct var_exec_data_t) 76762306a36Sopenharmony_ci : data_len; 76862306a36Sopenharmony_ci bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, proc_exec_data, data_len); 76962306a36Sopenharmony_ciout: 77062306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 77162306a36Sopenharmony_ci return 0; 77262306a36Sopenharmony_ci} 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ciSEC("kretprobe/do_filp_open") 77562306a36Sopenharmony_ciint kprobe_ret__do_filp_open(struct pt_regs* ctx) 77662306a36Sopenharmony_ci{ 77762306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 77862306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_do_filp_open_ret); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci struct file* filp = (struct file*)PT_REGS_RC_CORE(ctx); 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci if (filp == NULL || IS_ERR(filp)) 78362306a36Sopenharmony_ci goto out; 78462306a36Sopenharmony_ci unsigned int flags = BPF_CORE_READ(filp, f_flags); 78562306a36Sopenharmony_ci if ((flags & (O_RDWR | O_WRONLY)) == 0) 78662306a36Sopenharmony_ci goto out; 78762306a36Sopenharmony_ci if ((flags & O_TMPFILE) > 0) 78862306a36Sopenharmony_ci goto out; 78962306a36Sopenharmony_ci struct inode* file_inode = BPF_CORE_READ(filp, f_inode); 79062306a36Sopenharmony_ci umode_t mode = BPF_CORE_READ(file_inode, i_mode); 79162306a36Sopenharmony_ci if (S_ISDIR(mode) || S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) || 79262306a36Sopenharmony_ci S_ISSOCK(mode)) 79362306a36Sopenharmony_ci goto out; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci struct dentry* filp_dentry = BPF_CORE_READ(filp, f_path.dentry); 79662306a36Sopenharmony_ci u32 device_id = 0; 79762306a36Sopenharmony_ci u64 file_ino = 0; 79862306a36Sopenharmony_ci if (!is_dentry_allowed_for_filemod(filp_dentry, &device_id, &file_ino)) 79962306a36Sopenharmony_ci goto out; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci int zero = 0; 80262306a36Sopenharmony_ci struct var_filemod_data_t* filemod_data = bpf_map_lookup_elem(&data_heap, &zero); 80362306a36Sopenharmony_ci if (!filemod_data) 80462306a36Sopenharmony_ci goto out; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci u32 pid = get_userspace_pid(); 80762306a36Sopenharmony_ci struct task_struct* task = (struct task_struct*)bpf_get_current_task(); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci filemod_data->meta.type = FILEMOD_EVENT; 81062306a36Sopenharmony_ci filemod_data->fmod_type = FMOD_OPEN; 81162306a36Sopenharmony_ci filemod_data->dst_flags = flags; 81262306a36Sopenharmony_ci filemod_data->src_inode = 0; 81362306a36Sopenharmony_ci filemod_data->dst_inode = file_ino; 81462306a36Sopenharmony_ci filemod_data->src_device_id = 0; 81562306a36Sopenharmony_ci filemod_data->dst_device_id = device_id; 81662306a36Sopenharmony_ci filemod_data->src_filepath_length = 0; 81762306a36Sopenharmony_ci filemod_data->dst_filepath_length = 0; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci void* payload = populate_var_metadata(&filemod_data->meta, task, pid, 82062306a36Sopenharmony_ci filemod_data->payload); 82162306a36Sopenharmony_ci payload = populate_cgroup_info(&filemod_data->cgroup_data, task, payload); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci size_t len = read_absolute_file_path_from_dentry(filp_dentry, payload); 82462306a36Sopenharmony_ci barrier_var(len); 82562306a36Sopenharmony_ci if (len <= MAX_FILEPATH_LENGTH) { 82662306a36Sopenharmony_ci barrier_var(len); 82762306a36Sopenharmony_ci payload += len; 82862306a36Sopenharmony_ci filemod_data->dst_filepath_length = len; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci bpf_stats_pre_submit_var_perf_event(&stats_ctx, &filemod_data->meta); 83162306a36Sopenharmony_ci unsigned long data_len = payload - (void*)filemod_data; 83262306a36Sopenharmony_ci data_len = data_len > sizeof(*filemod_data) ? sizeof(*filemod_data) : data_len; 83362306a36Sopenharmony_ci bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, filemod_data, data_len); 83462306a36Sopenharmony_ciout: 83562306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 83662306a36Sopenharmony_ci return 0; 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ciSEC("kprobe/vfs_link") 84062306a36Sopenharmony_ciint BPF_KPROBE(kprobe__vfs_link, 84162306a36Sopenharmony_ci struct dentry* old_dentry, struct mnt_idmap *idmap, 84262306a36Sopenharmony_ci struct inode* dir, struct dentry* new_dentry, 84362306a36Sopenharmony_ci struct inode** delegated_inode) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 84662306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_vfs_link); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci u32 src_device_id = 0; 84962306a36Sopenharmony_ci u64 src_file_ino = 0; 85062306a36Sopenharmony_ci u32 dst_device_id = 0; 85162306a36Sopenharmony_ci u64 dst_file_ino = 0; 85262306a36Sopenharmony_ci if (!is_dentry_allowed_for_filemod(old_dentry, &src_device_id, &src_file_ino) && 85362306a36Sopenharmony_ci !is_dentry_allowed_for_filemod(new_dentry, &dst_device_id, &dst_file_ino)) 85462306a36Sopenharmony_ci goto out; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci int zero = 0; 85762306a36Sopenharmony_ci struct var_filemod_data_t* filemod_data = bpf_map_lookup_elem(&data_heap, &zero); 85862306a36Sopenharmony_ci if (!filemod_data) 85962306a36Sopenharmony_ci goto out; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci u32 pid = get_userspace_pid(); 86262306a36Sopenharmony_ci struct task_struct* task = (struct task_struct*)bpf_get_current_task(); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci filemod_data->meta.type = FILEMOD_EVENT; 86562306a36Sopenharmony_ci filemod_data->fmod_type = FMOD_LINK; 86662306a36Sopenharmony_ci filemod_data->dst_flags = 0; 86762306a36Sopenharmony_ci filemod_data->src_inode = src_file_ino; 86862306a36Sopenharmony_ci filemod_data->dst_inode = dst_file_ino; 86962306a36Sopenharmony_ci filemod_data->src_device_id = src_device_id; 87062306a36Sopenharmony_ci filemod_data->dst_device_id = dst_device_id; 87162306a36Sopenharmony_ci filemod_data->src_filepath_length = 0; 87262306a36Sopenharmony_ci filemod_data->dst_filepath_length = 0; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci void* payload = populate_var_metadata(&filemod_data->meta, task, pid, 87562306a36Sopenharmony_ci filemod_data->payload); 87662306a36Sopenharmony_ci payload = populate_cgroup_info(&filemod_data->cgroup_data, task, payload); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci size_t len = read_absolute_file_path_from_dentry(old_dentry, payload); 87962306a36Sopenharmony_ci barrier_var(len); 88062306a36Sopenharmony_ci if (len <= MAX_FILEPATH_LENGTH) { 88162306a36Sopenharmony_ci barrier_var(len); 88262306a36Sopenharmony_ci payload += len; 88362306a36Sopenharmony_ci filemod_data->src_filepath_length = len; 88462306a36Sopenharmony_ci } 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci len = read_absolute_file_path_from_dentry(new_dentry, payload); 88762306a36Sopenharmony_ci barrier_var(len); 88862306a36Sopenharmony_ci if (len <= MAX_FILEPATH_LENGTH) { 88962306a36Sopenharmony_ci barrier_var(len); 89062306a36Sopenharmony_ci payload += len; 89162306a36Sopenharmony_ci filemod_data->dst_filepath_length = len; 89262306a36Sopenharmony_ci } 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci bpf_stats_pre_submit_var_perf_event(&stats_ctx, &filemod_data->meta); 89562306a36Sopenharmony_ci unsigned long data_len = payload - (void*)filemod_data; 89662306a36Sopenharmony_ci data_len = data_len > sizeof(*filemod_data) ? sizeof(*filemod_data) : data_len; 89762306a36Sopenharmony_ci bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, filemod_data, data_len); 89862306a36Sopenharmony_ciout: 89962306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 90062306a36Sopenharmony_ci return 0; 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ciSEC("kprobe/vfs_symlink") 90462306a36Sopenharmony_ciint BPF_KPROBE(kprobe__vfs_symlink, struct inode* dir, struct dentry* dentry, 90562306a36Sopenharmony_ci const char* oldname) 90662306a36Sopenharmony_ci{ 90762306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 90862306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_vfs_symlink); 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci u32 dst_device_id = 0; 91162306a36Sopenharmony_ci u64 dst_file_ino = 0; 91262306a36Sopenharmony_ci if (!is_dentry_allowed_for_filemod(dentry, &dst_device_id, &dst_file_ino)) 91362306a36Sopenharmony_ci goto out; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci int zero = 0; 91662306a36Sopenharmony_ci struct var_filemod_data_t* filemod_data = bpf_map_lookup_elem(&data_heap, &zero); 91762306a36Sopenharmony_ci if (!filemod_data) 91862306a36Sopenharmony_ci goto out; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci u32 pid = get_userspace_pid(); 92162306a36Sopenharmony_ci struct task_struct* task = (struct task_struct*)bpf_get_current_task(); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci filemod_data->meta.type = FILEMOD_EVENT; 92462306a36Sopenharmony_ci filemod_data->fmod_type = FMOD_SYMLINK; 92562306a36Sopenharmony_ci filemod_data->dst_flags = 0; 92662306a36Sopenharmony_ci filemod_data->src_inode = 0; 92762306a36Sopenharmony_ci filemod_data->dst_inode = dst_file_ino; 92862306a36Sopenharmony_ci filemod_data->src_device_id = 0; 92962306a36Sopenharmony_ci filemod_data->dst_device_id = dst_device_id; 93062306a36Sopenharmony_ci filemod_data->src_filepath_length = 0; 93162306a36Sopenharmony_ci filemod_data->dst_filepath_length = 0; 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_ci void* payload = populate_var_metadata(&filemod_data->meta, task, pid, 93462306a36Sopenharmony_ci filemod_data->payload); 93562306a36Sopenharmony_ci payload = populate_cgroup_info(&filemod_data->cgroup_data, task, payload); 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci size_t len = bpf_probe_read_kernel_str(payload, MAX_FILEPATH_LENGTH, 93862306a36Sopenharmony_ci oldname); 93962306a36Sopenharmony_ci barrier_var(len); 94062306a36Sopenharmony_ci if (len <= MAX_FILEPATH_LENGTH) { 94162306a36Sopenharmony_ci barrier_var(len); 94262306a36Sopenharmony_ci payload += len; 94362306a36Sopenharmony_ci filemod_data->src_filepath_length = len; 94462306a36Sopenharmony_ci } 94562306a36Sopenharmony_ci len = read_absolute_file_path_from_dentry(dentry, payload); 94662306a36Sopenharmony_ci barrier_var(len); 94762306a36Sopenharmony_ci if (len <= MAX_FILEPATH_LENGTH) { 94862306a36Sopenharmony_ci barrier_var(len); 94962306a36Sopenharmony_ci payload += len; 95062306a36Sopenharmony_ci filemod_data->dst_filepath_length = len; 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci bpf_stats_pre_submit_var_perf_event(&stats_ctx, &filemod_data->meta); 95362306a36Sopenharmony_ci unsigned long data_len = payload - (void*)filemod_data; 95462306a36Sopenharmony_ci data_len = data_len > sizeof(*filemod_data) ? sizeof(*filemod_data) : data_len; 95562306a36Sopenharmony_ci bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, filemod_data, data_len); 95662306a36Sopenharmony_ciout: 95762306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 95862306a36Sopenharmony_ci return 0; 95962306a36Sopenharmony_ci} 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ciSEC("raw_tracepoint/sched_process_fork") 96262306a36Sopenharmony_ciint raw_tracepoint__sched_process_fork(struct bpf_raw_tracepoint_args* ctx) 96362306a36Sopenharmony_ci{ 96462306a36Sopenharmony_ci struct bpf_func_stats_ctx stats_ctx; 96562306a36Sopenharmony_ci bpf_stats_enter(&stats_ctx, profiler_bpf_sched_process_fork); 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci int zero = 0; 96862306a36Sopenharmony_ci struct var_fork_data_t* fork_data = bpf_map_lookup_elem(&data_heap, &zero); 96962306a36Sopenharmony_ci if (!fork_data) 97062306a36Sopenharmony_ci goto out; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci struct task_struct* parent = (struct task_struct*)ctx->args[0]; 97362306a36Sopenharmony_ci struct task_struct* child = (struct task_struct*)ctx->args[1]; 97462306a36Sopenharmony_ci fork_data->meta.type = FORK_EVENT; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci void* payload = populate_var_metadata(&fork_data->meta, child, 97762306a36Sopenharmony_ci BPF_CORE_READ(child, pid), fork_data->payload); 97862306a36Sopenharmony_ci fork_data->parent_pid = BPF_CORE_READ(parent, pid); 97962306a36Sopenharmony_ci fork_data->parent_exec_id = BPF_CORE_READ(parent, self_exec_id); 98062306a36Sopenharmony_ci fork_data->parent_start_time = BPF_CORE_READ(parent, start_time); 98162306a36Sopenharmony_ci bpf_stats_pre_submit_var_perf_event(&stats_ctx, &fork_data->meta); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci unsigned long data_len = payload - (void*)fork_data; 98462306a36Sopenharmony_ci data_len = data_len > sizeof(*fork_data) ? sizeof(*fork_data) : data_len; 98562306a36Sopenharmony_ci bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, fork_data, data_len); 98662306a36Sopenharmony_ciout: 98762306a36Sopenharmony_ci bpf_stats_exit(&stats_ctx); 98862306a36Sopenharmony_ci return 0; 98962306a36Sopenharmony_ci} 99062306a36Sopenharmony_cichar _license[] SEC("license") = "GPL"; 991