Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2020 Facebook */
0003 #include <vmlinux.h>
0004 #include <bpf/bpf_core_read.h>
0005 #include <bpf/bpf_helpers.h>
0006 #include <bpf/bpf_tracing.h>
0007 
0008 #include "profiler.h"
0009 
0010 #ifndef NULL
0011 #define NULL 0
0012 #endif
0013 
0014 #define O_WRONLY 00000001
0015 #define O_RDWR 00000002
0016 #define O_DIRECTORY 00200000
0017 #define __O_TMPFILE 020000000
0018 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
0019 #define MAX_ERRNO 4095
0020 #define S_IFMT 00170000
0021 #define S_IFSOCK 0140000
0022 #define S_IFLNK 0120000
0023 #define S_IFREG 0100000
0024 #define S_IFBLK 0060000
0025 #define S_IFDIR 0040000
0026 #define S_IFCHR 0020000
0027 #define S_IFIFO 0010000
0028 #define S_ISUID 0004000
0029 #define S_ISGID 0002000
0030 #define S_ISVTX 0001000
0031 #define S_ISLNK(m) (((m)&S_IFMT) == S_IFLNK)
0032 #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
0033 #define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
0034 #define S_ISBLK(m) (((m)&S_IFMT) == S_IFBLK)
0035 #define S_ISFIFO(m) (((m)&S_IFMT) == S_IFIFO)
0036 #define S_ISSOCK(m) (((m)&S_IFMT) == S_IFSOCK)
0037 #define IS_ERR_VALUE(x) (unsigned long)(void*)(x) >= (unsigned long)-MAX_ERRNO
0038 
0039 #define KILL_DATA_ARRAY_SIZE 8
0040 
0041 struct var_kill_data_arr_t {
0042     struct var_kill_data_t array[KILL_DATA_ARRAY_SIZE];
0043 };
0044 
0045 union any_profiler_data_t {
0046     struct var_exec_data_t var_exec;
0047     struct var_kill_data_t var_kill;
0048     struct var_sysctl_data_t var_sysctl;
0049     struct var_filemod_data_t var_filemod;
0050     struct var_fork_data_t var_fork;
0051     struct var_kill_data_arr_t var_kill_data_arr;
0052 };
0053 
0054 volatile struct profiler_config_struct bpf_config = {};
0055 
0056 #define FETCH_CGROUPS_FROM_BPF (bpf_config.fetch_cgroups_from_bpf)
0057 #define CGROUP_FS_INODE (bpf_config.cgroup_fs_inode)
0058 #define CGROUP_LOGIN_SESSION_INODE \
0059     (bpf_config.cgroup_login_session_inode)
0060 #define KILL_SIGNALS (bpf_config.kill_signals_mask)
0061 #define STALE_INFO (bpf_config.stale_info_secs)
0062 #define INODE_FILTER (bpf_config.inode_filter)
0063 #define READ_ENVIRON_FROM_EXEC (bpf_config.read_environ_from_exec)
0064 #define ENABLE_CGROUP_V1_RESOLVER (bpf_config.enable_cgroup_v1_resolver)
0065 
0066 struct kernfs_iattrs___52 {
0067     struct iattr ia_iattr;
0068 };
0069 
0070 struct kernfs_node___52 {
0071     union /* kernfs_node_id */ {
0072         struct {
0073             u32 ino;
0074             u32 generation;
0075         };
0076         u64 id;
0077     } id;
0078 };
0079 
0080 struct {
0081     __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0082     __uint(max_entries, 1);
0083     __type(key, u32);
0084     __type(value, union any_profiler_data_t);
0085 } data_heap SEC(".maps");
0086 
0087 struct {
0088     __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
0089     __uint(key_size, sizeof(int));
0090     __uint(value_size, sizeof(int));
0091 } events SEC(".maps");
0092 
0093 struct {
0094     __uint(type, BPF_MAP_TYPE_HASH);
0095     __uint(max_entries, KILL_DATA_ARRAY_SIZE);
0096     __type(key, u32);
0097     __type(value, struct var_kill_data_arr_t);
0098 } var_tpid_to_data SEC(".maps");
0099 
0100 struct {
0101     __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0102     __uint(max_entries, profiler_bpf_max_function_id);
0103     __type(key, u32);
0104     __type(value, struct bpf_func_stats_data);
0105 } bpf_func_stats SEC(".maps");
0106 
0107 struct {
0108     __uint(type, BPF_MAP_TYPE_HASH);
0109     __type(key, u32);
0110     __type(value, bool);
0111     __uint(max_entries, 16);
0112 } allowed_devices SEC(".maps");
0113 
0114 struct {
0115     __uint(type, BPF_MAP_TYPE_HASH);
0116     __type(key, u64);
0117     __type(value, bool);
0118     __uint(max_entries, 1024);
0119 } allowed_file_inodes SEC(".maps");
0120 
0121 struct {
0122     __uint(type, BPF_MAP_TYPE_HASH);
0123     __type(key, u64);
0124     __type(value, bool);
0125     __uint(max_entries, 1024);
0126 } allowed_directory_inodes SEC(".maps");
0127 
0128 struct {
0129     __uint(type, BPF_MAP_TYPE_HASH);
0130     __type(key, u32);
0131     __type(value, bool);
0132     __uint(max_entries, 16);
0133 } disallowed_exec_inodes SEC(".maps");
0134 
0135 #ifndef ARRAY_SIZE
0136 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
0137 #endif
0138 
0139 static INLINE bool IS_ERR(const void* ptr)
0140 {
0141     return IS_ERR_VALUE((unsigned long)ptr);
0142 }
0143 
0144 static INLINE u32 get_userspace_pid()
0145 {
0146     return bpf_get_current_pid_tgid() >> 32;
0147 }
0148 
0149 static INLINE bool is_init_process(u32 tgid)
0150 {
0151     return tgid == 1 || tgid == 0;
0152 }
0153 
0154 static INLINE unsigned long
0155 probe_read_lim(void* dst, void* src, unsigned long len, unsigned long max)
0156 {
0157     len = len < max ? len : max;
0158     if (len > 1) {
0159         if (bpf_probe_read(dst, len, src))
0160             return 0;
0161     } else if (len == 1) {
0162         if (bpf_probe_read(dst, 1, src))
0163             return 0;
0164     }
0165     return len;
0166 }
0167 
0168 static INLINE int get_var_spid_index(struct var_kill_data_arr_t* arr_struct,
0169                      int spid)
0170 {
0171 #ifdef UNROLL
0172 #pragma unroll
0173 #endif
0174     for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++)
0175         if (arr_struct->array[i].meta.pid == spid)
0176             return i;
0177     return -1;
0178 }
0179 
0180 static INLINE void populate_ancestors(struct task_struct* task,
0181                       struct ancestors_data_t* ancestors_data)
0182 {
0183     struct task_struct* parent = task;
0184     u32 num_ancestors, ppid;
0185 
0186     ancestors_data->num_ancestors = 0;
0187 #ifdef UNROLL
0188 #pragma unroll
0189 #endif
0190     for (num_ancestors = 0; num_ancestors < MAX_ANCESTORS; num_ancestors++) {
0191         parent = BPF_CORE_READ(parent, real_parent);
0192         if (parent == NULL)
0193             break;
0194         ppid = BPF_CORE_READ(parent, tgid);
0195         if (is_init_process(ppid))
0196             break;
0197         ancestors_data->ancestor_pids[num_ancestors] = ppid;
0198         ancestors_data->ancestor_exec_ids[num_ancestors] =
0199             BPF_CORE_READ(parent, self_exec_id);
0200         ancestors_data->ancestor_start_times[num_ancestors] =
0201             BPF_CORE_READ(parent, start_time);
0202         ancestors_data->num_ancestors = num_ancestors;
0203     }
0204 }
0205 
0206 static INLINE void* read_full_cgroup_path(struct kernfs_node* cgroup_node,
0207                       struct kernfs_node* cgroup_root_node,
0208                       void* payload,
0209                       int* root_pos)
0210 {
0211     void* payload_start = payload;
0212     size_t filepart_length;
0213 
0214 #ifdef UNROLL
0215 #pragma unroll
0216 #endif
0217     for (int i = 0; i < MAX_CGROUPS_PATH_DEPTH; i++) {
0218         filepart_length =
0219             bpf_probe_read_str(payload, MAX_PATH, BPF_CORE_READ(cgroup_node, name));
0220         if (!cgroup_node)
0221             return payload;
0222         if (cgroup_node == cgroup_root_node)
0223             *root_pos = payload - payload_start;
0224         if (filepart_length <= MAX_PATH) {
0225             barrier_var(filepart_length);
0226             payload += filepart_length;
0227         }
0228         cgroup_node = BPF_CORE_READ(cgroup_node, parent);
0229     }
0230     return payload;
0231 }
0232 
0233 static ino_t get_inode_from_kernfs(struct kernfs_node* node)
0234 {
0235     struct kernfs_node___52* node52 = (void*)node;
0236 
0237     if (bpf_core_field_exists(node52->id.ino)) {
0238         barrier_var(node52);
0239         return BPF_CORE_READ(node52, id.ino);
0240     } else {
0241         barrier_var(node);
0242         return (u64)BPF_CORE_READ(node, id);
0243     }
0244 }
0245 
0246 extern bool CONFIG_CGROUP_PIDS __kconfig __weak;
0247 enum cgroup_subsys_id___local {
0248     pids_cgrp_id___local = 123, /* value doesn't matter */
0249 };
0250 
0251 static INLINE void* populate_cgroup_info(struct cgroup_data_t* cgroup_data,
0252                      struct task_struct* task,
0253                      void* payload)
0254 {
0255     struct kernfs_node* root_kernfs =
0256         BPF_CORE_READ(task, nsproxy, cgroup_ns, root_cset, dfl_cgrp, kn);
0257     struct kernfs_node* proc_kernfs = BPF_CORE_READ(task, cgroups, dfl_cgrp, kn);
0258 
0259 #if __has_builtin(__builtin_preserve_enum_value)
0260     if (ENABLE_CGROUP_V1_RESOLVER && CONFIG_CGROUP_PIDS) {
0261         int cgrp_id = bpf_core_enum_value(enum cgroup_subsys_id___local,
0262                           pids_cgrp_id___local);
0263 #ifdef UNROLL
0264 #pragma unroll
0265 #endif
0266         for (int i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
0267             struct cgroup_subsys_state* subsys =
0268                 BPF_CORE_READ(task, cgroups, subsys[i]);
0269             if (subsys != NULL) {
0270                 int subsys_id = BPF_CORE_READ(subsys, ss, id);
0271                 if (subsys_id == cgrp_id) {
0272                     proc_kernfs = BPF_CORE_READ(subsys, cgroup, kn);
0273                     root_kernfs = BPF_CORE_READ(subsys, ss, root, kf_root, kn);
0274                     break;
0275                 }
0276             }
0277         }
0278     }
0279 #endif
0280 
0281     cgroup_data->cgroup_root_inode = get_inode_from_kernfs(root_kernfs);
0282     cgroup_data->cgroup_proc_inode = get_inode_from_kernfs(proc_kernfs);
0283 
0284     if (bpf_core_field_exists(root_kernfs->iattr->ia_mtime)) {
0285         cgroup_data->cgroup_root_mtime =
0286             BPF_CORE_READ(root_kernfs, iattr, ia_mtime.tv_nsec);
0287         cgroup_data->cgroup_proc_mtime =
0288             BPF_CORE_READ(proc_kernfs, iattr, ia_mtime.tv_nsec);
0289     } else {
0290         struct kernfs_iattrs___52* root_iattr =
0291             (struct kernfs_iattrs___52*)BPF_CORE_READ(root_kernfs, iattr);
0292         cgroup_data->cgroup_root_mtime =
0293             BPF_CORE_READ(root_iattr, ia_iattr.ia_mtime.tv_nsec);
0294 
0295         struct kernfs_iattrs___52* proc_iattr =
0296             (struct kernfs_iattrs___52*)BPF_CORE_READ(proc_kernfs, iattr);
0297         cgroup_data->cgroup_proc_mtime =
0298             BPF_CORE_READ(proc_iattr, ia_iattr.ia_mtime.tv_nsec);
0299     }
0300 
0301     cgroup_data->cgroup_root_length = 0;
0302     cgroup_data->cgroup_proc_length = 0;
0303     cgroup_data->cgroup_full_length = 0;
0304 
0305     size_t cgroup_root_length =
0306         bpf_probe_read_str(payload, MAX_PATH, BPF_CORE_READ(root_kernfs, name));
0307     barrier_var(cgroup_root_length);
0308     if (cgroup_root_length <= MAX_PATH) {
0309         barrier_var(cgroup_root_length);
0310         cgroup_data->cgroup_root_length = cgroup_root_length;
0311         payload += cgroup_root_length;
0312     }
0313 
0314     size_t cgroup_proc_length =
0315         bpf_probe_read_str(payload, MAX_PATH, BPF_CORE_READ(proc_kernfs, name));
0316     barrier_var(cgroup_proc_length);
0317     if (cgroup_proc_length <= MAX_PATH) {
0318         barrier_var(cgroup_proc_length);
0319         cgroup_data->cgroup_proc_length = cgroup_proc_length;
0320         payload += cgroup_proc_length;
0321     }
0322 
0323     if (FETCH_CGROUPS_FROM_BPF) {
0324         cgroup_data->cgroup_full_path_root_pos = -1;
0325         void* payload_end_pos = read_full_cgroup_path(proc_kernfs, root_kernfs, payload,
0326                                   &cgroup_data->cgroup_full_path_root_pos);
0327         cgroup_data->cgroup_full_length = payload_end_pos - payload;
0328         payload = payload_end_pos;
0329     }
0330 
0331     return (void*)payload;
0332 }
0333 
0334 static INLINE void* populate_var_metadata(struct var_metadata_t* metadata,
0335                       struct task_struct* task,
0336                       u32 pid, void* payload)
0337 {
0338     u64 uid_gid = bpf_get_current_uid_gid();
0339 
0340     metadata->uid = (u32)uid_gid;
0341     metadata->gid = uid_gid >> 32;
0342     metadata->pid = pid;
0343     metadata->exec_id = BPF_CORE_READ(task, self_exec_id);
0344     metadata->start_time = BPF_CORE_READ(task, start_time);
0345     metadata->comm_length = 0;
0346 
0347     size_t comm_length = bpf_core_read_str(payload, TASK_COMM_LEN, &task->comm);
0348     barrier_var(comm_length);
0349     if (comm_length <= TASK_COMM_LEN) {
0350         barrier_var(comm_length);
0351         metadata->comm_length = comm_length;
0352         payload += comm_length;
0353     }
0354 
0355     return (void*)payload;
0356 }
0357 
0358 static INLINE struct var_kill_data_t*
0359 get_var_kill_data(struct pt_regs* ctx, int spid, int tpid, int sig)
0360 {
0361     int zero = 0;
0362     struct var_kill_data_t* kill_data = bpf_map_lookup_elem(&data_heap, &zero);
0363 
0364     if (kill_data == NULL)
0365         return NULL;
0366     struct task_struct* task = (struct task_struct*)bpf_get_current_task();
0367 
0368     void* payload = populate_var_metadata(&kill_data->meta, task, spid, kill_data->payload);
0369     payload = populate_cgroup_info(&kill_data->cgroup_data, task, payload);
0370     size_t payload_length = payload - (void*)kill_data->payload;
0371     kill_data->payload_length = payload_length;
0372     populate_ancestors(task, &kill_data->ancestors_info);
0373     kill_data->meta.type = KILL_EVENT;
0374     kill_data->kill_target_pid = tpid;
0375     kill_data->kill_sig = sig;
0376     kill_data->kill_count = 1;
0377     kill_data->last_kill_time = bpf_ktime_get_ns();
0378     return kill_data;
0379 }
0380 
0381 static INLINE int trace_var_sys_kill(void* ctx, int tpid, int sig)
0382 {
0383     if ((KILL_SIGNALS & (1ULL << sig)) == 0)
0384         return 0;
0385 
0386     u32 spid = get_userspace_pid();
0387     struct var_kill_data_arr_t* arr_struct = bpf_map_lookup_elem(&var_tpid_to_data, &tpid);
0388 
0389     if (arr_struct == NULL) {
0390         struct var_kill_data_t* kill_data = get_var_kill_data(ctx, spid, tpid, sig);
0391         int zero = 0;
0392 
0393         if (kill_data == NULL)
0394             return 0;
0395         arr_struct = bpf_map_lookup_elem(&data_heap, &zero);
0396         if (arr_struct == NULL)
0397             return 0;
0398         bpf_probe_read(&arr_struct->array[0], sizeof(arr_struct->array[0]), kill_data);
0399     } else {
0400         int index = get_var_spid_index(arr_struct, spid);
0401 
0402         if (index == -1) {
0403             struct var_kill_data_t* kill_data =
0404                 get_var_kill_data(ctx, spid, tpid, sig);
0405             if (kill_data == NULL)
0406                 return 0;
0407 #ifdef UNROLL
0408 #pragma unroll
0409 #endif
0410             for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++)
0411                 if (arr_struct->array[i].meta.pid == 0) {
0412                     bpf_probe_read(&arr_struct->array[i],
0413                                sizeof(arr_struct->array[i]), kill_data);
0414                     bpf_map_update_elem(&var_tpid_to_data, &tpid,
0415                                 arr_struct, 0);
0416 
0417                     return 0;
0418                 }
0419             return 0;
0420         }
0421 
0422         struct var_kill_data_t* kill_data = &arr_struct->array[index];
0423 
0424         u64 delta_sec =
0425             (bpf_ktime_get_ns() - kill_data->last_kill_time) / 1000000000;
0426 
0427         if (delta_sec < STALE_INFO) {
0428             kill_data->kill_count++;
0429             kill_data->last_kill_time = bpf_ktime_get_ns();
0430             bpf_probe_read(&arr_struct->array[index],
0431                        sizeof(arr_struct->array[index]),
0432                        kill_data);
0433         } else {
0434             struct var_kill_data_t* kill_data =
0435                 get_var_kill_data(ctx, spid, tpid, sig);
0436             if (kill_data == NULL)
0437                 return 0;
0438             bpf_probe_read(&arr_struct->array[index],
0439                        sizeof(arr_struct->array[index]),
0440                        kill_data);
0441         }
0442     }
0443     bpf_map_update_elem(&var_tpid_to_data, &tpid, arr_struct, 0);
0444     return 0;
0445 }
0446 
0447 static INLINE void bpf_stats_enter(struct bpf_func_stats_ctx* bpf_stat_ctx,
0448                    enum bpf_function_id func_id)
0449 {
0450     int func_id_key = func_id;
0451 
0452     bpf_stat_ctx->start_time_ns = bpf_ktime_get_ns();
0453     bpf_stat_ctx->bpf_func_stats_data_val =
0454         bpf_map_lookup_elem(&bpf_func_stats, &func_id_key);
0455     if (bpf_stat_ctx->bpf_func_stats_data_val)
0456         bpf_stat_ctx->bpf_func_stats_data_val->num_executions++;
0457 }
0458 
0459 static INLINE void bpf_stats_exit(struct bpf_func_stats_ctx* bpf_stat_ctx)
0460 {
0461     if (bpf_stat_ctx->bpf_func_stats_data_val)
0462         bpf_stat_ctx->bpf_func_stats_data_val->time_elapsed_ns +=
0463             bpf_ktime_get_ns() - bpf_stat_ctx->start_time_ns;
0464 }
0465 
0466 static INLINE void
0467 bpf_stats_pre_submit_var_perf_event(struct bpf_func_stats_ctx* bpf_stat_ctx,
0468                     struct var_metadata_t* meta)
0469 {
0470     if (bpf_stat_ctx->bpf_func_stats_data_val) {
0471         bpf_stat_ctx->bpf_func_stats_data_val->num_perf_events++;
0472         meta->bpf_stats_num_perf_events =
0473             bpf_stat_ctx->bpf_func_stats_data_val->num_perf_events;
0474     }
0475     meta->bpf_stats_start_ktime_ns = bpf_stat_ctx->start_time_ns;
0476     meta->cpu_id = bpf_get_smp_processor_id();
0477 }
0478 
0479 static INLINE size_t
0480 read_absolute_file_path_from_dentry(struct dentry* filp_dentry, void* payload)
0481 {
0482     size_t length = 0;
0483     size_t filepart_length;
0484     struct dentry* parent_dentry;
0485 
0486 #ifdef UNROLL
0487 #pragma unroll
0488 #endif
0489     for (int i = 0; i < MAX_PATH_DEPTH; i++) {
0490         filepart_length = bpf_probe_read_str(payload, MAX_PATH,
0491                              BPF_CORE_READ(filp_dentry, d_name.name));
0492         barrier_var(filepart_length);
0493         if (filepart_length > MAX_PATH)
0494             break;
0495         barrier_var(filepart_length);
0496         payload += filepart_length;
0497         length += filepart_length;
0498 
0499         parent_dentry = BPF_CORE_READ(filp_dentry, d_parent);
0500         if (filp_dentry == parent_dentry)
0501             break;
0502         filp_dentry = parent_dentry;
0503     }
0504 
0505     return length;
0506 }
0507 
0508 static INLINE bool
0509 is_ancestor_in_allowed_inodes(struct dentry* filp_dentry)
0510 {
0511     struct dentry* parent_dentry;
0512 #ifdef UNROLL
0513 #pragma unroll
0514 #endif
0515     for (int i = 0; i < MAX_PATH_DEPTH; i++) {
0516         u64 dir_ino = BPF_CORE_READ(filp_dentry, d_inode, i_ino);
0517         bool* allowed_dir = bpf_map_lookup_elem(&allowed_directory_inodes, &dir_ino);
0518 
0519         if (allowed_dir != NULL)
0520             return true;
0521         parent_dentry = BPF_CORE_READ(filp_dentry, d_parent);
0522         if (filp_dentry == parent_dentry)
0523             break;
0524         filp_dentry = parent_dentry;
0525     }
0526     return false;
0527 }
0528 
0529 static INLINE bool is_dentry_allowed_for_filemod(struct dentry* file_dentry,
0530                          u32* device_id,
0531                          u64* file_ino)
0532 {
0533     u32 dev_id = BPF_CORE_READ(file_dentry, d_sb, s_dev);
0534     *device_id = dev_id;
0535     bool* allowed_device = bpf_map_lookup_elem(&allowed_devices, &dev_id);
0536 
0537     if (allowed_device == NULL)
0538         return false;
0539 
0540     u64 ino = BPF_CORE_READ(file_dentry, d_inode, i_ino);
0541     *file_ino = ino;
0542     bool* allowed_file = bpf_map_lookup_elem(&allowed_file_inodes, &ino);
0543 
0544     if (allowed_file == NULL)
0545         if (!is_ancestor_in_allowed_inodes(BPF_CORE_READ(file_dentry, d_parent)))
0546             return false;
0547     return true;
0548 }
0549 
0550 SEC("kprobe/proc_sys_write")
0551 ssize_t BPF_KPROBE(kprobe__proc_sys_write,
0552            struct file* filp, const char* buf,
0553            size_t count, loff_t* ppos)
0554 {
0555     struct bpf_func_stats_ctx stats_ctx;
0556     bpf_stats_enter(&stats_ctx, profiler_bpf_proc_sys_write);
0557 
0558     u32 pid = get_userspace_pid();
0559     int zero = 0;
0560     struct var_sysctl_data_t* sysctl_data =
0561         bpf_map_lookup_elem(&data_heap, &zero);
0562     if (!sysctl_data)
0563         goto out;
0564 
0565     struct task_struct* task = (struct task_struct*)bpf_get_current_task();
0566     sysctl_data->meta.type = SYSCTL_EVENT;
0567     void* payload = populate_var_metadata(&sysctl_data->meta, task, pid, sysctl_data->payload);
0568     payload = populate_cgroup_info(&sysctl_data->cgroup_data, task, payload);
0569 
0570     populate_ancestors(task, &sysctl_data->ancestors_info);
0571 
0572     sysctl_data->sysctl_val_length = 0;
0573     sysctl_data->sysctl_path_length = 0;
0574 
0575     size_t sysctl_val_length = bpf_probe_read_str(payload, CTL_MAXNAME, buf);
0576     barrier_var(sysctl_val_length);
0577     if (sysctl_val_length <= CTL_MAXNAME) {
0578         barrier_var(sysctl_val_length);
0579         sysctl_data->sysctl_val_length = sysctl_val_length;
0580         payload += sysctl_val_length;
0581     }
0582 
0583     size_t sysctl_path_length = bpf_probe_read_str(payload, MAX_PATH,
0584                                BPF_CORE_READ(filp, f_path.dentry, d_name.name));
0585     barrier_var(sysctl_path_length);
0586     if (sysctl_path_length <= MAX_PATH) {
0587         barrier_var(sysctl_path_length);
0588         sysctl_data->sysctl_path_length = sysctl_path_length;
0589         payload += sysctl_path_length;
0590     }
0591 
0592     bpf_stats_pre_submit_var_perf_event(&stats_ctx, &sysctl_data->meta);
0593     unsigned long data_len = payload - (void*)sysctl_data;
0594     data_len = data_len > sizeof(struct var_sysctl_data_t)
0595         ? sizeof(struct var_sysctl_data_t)
0596         : data_len;
0597     bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, sysctl_data, data_len);
0598 out:
0599     bpf_stats_exit(&stats_ctx);
0600     return 0;
0601 }
0602 
0603 SEC("tracepoint/syscalls/sys_enter_kill")
0604 int tracepoint__syscalls__sys_enter_kill(struct trace_event_raw_sys_enter* ctx)
0605 {
0606     struct bpf_func_stats_ctx stats_ctx;
0607 
0608     bpf_stats_enter(&stats_ctx, profiler_bpf_sys_enter_kill);
0609     int pid = ctx->args[0];
0610     int sig = ctx->args[1];
0611     int ret = trace_var_sys_kill(ctx, pid, sig);
0612     bpf_stats_exit(&stats_ctx);
0613     return ret;
0614 };
0615 
0616 SEC("raw_tracepoint/sched_process_exit")
0617 int raw_tracepoint__sched_process_exit(void* ctx)
0618 {
0619     int zero = 0;
0620     struct bpf_func_stats_ctx stats_ctx;
0621     bpf_stats_enter(&stats_ctx, profiler_bpf_sched_process_exit);
0622 
0623     u32 tpid = get_userspace_pid();
0624 
0625     struct var_kill_data_arr_t* arr_struct = bpf_map_lookup_elem(&var_tpid_to_data, &tpid);
0626     struct var_kill_data_t* kill_data = bpf_map_lookup_elem(&data_heap, &zero);
0627 
0628     if (arr_struct == NULL || kill_data == NULL)
0629         goto out;
0630 
0631     struct task_struct* task = (struct task_struct*)bpf_get_current_task();
0632     struct kernfs_node* proc_kernfs = BPF_CORE_READ(task, cgroups, dfl_cgrp, kn);
0633 
0634 #ifdef UNROLL
0635 #pragma unroll
0636 #endif
0637     for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++) {
0638         struct var_kill_data_t* past_kill_data = &arr_struct->array[i];
0639 
0640         if (past_kill_data != NULL && past_kill_data->kill_target_pid == tpid) {
0641             bpf_probe_read(kill_data, sizeof(*past_kill_data), past_kill_data);
0642             void* payload = kill_data->payload;
0643             size_t offset = kill_data->payload_length;
0644             if (offset >= MAX_METADATA_PAYLOAD_LEN + MAX_CGROUP_PAYLOAD_LEN)
0645                 return 0;
0646             payload += offset;
0647 
0648             kill_data->kill_target_name_length = 0;
0649             kill_data->kill_target_cgroup_proc_length = 0;
0650 
0651             size_t comm_length = bpf_core_read_str(payload, TASK_COMM_LEN, &task->comm);
0652             barrier_var(comm_length);
0653             if (comm_length <= TASK_COMM_LEN) {
0654                 barrier_var(comm_length);
0655                 kill_data->kill_target_name_length = comm_length;
0656                 payload += comm_length;
0657             }
0658 
0659             size_t cgroup_proc_length = bpf_probe_read_str(payload, KILL_TARGET_LEN,
0660                                        BPF_CORE_READ(proc_kernfs, name));
0661             barrier_var(cgroup_proc_length);
0662             if (cgroup_proc_length <= KILL_TARGET_LEN) {
0663                 barrier_var(cgroup_proc_length);
0664                 kill_data->kill_target_cgroup_proc_length = cgroup_proc_length;
0665                 payload += cgroup_proc_length;
0666             }
0667 
0668             bpf_stats_pre_submit_var_perf_event(&stats_ctx, &kill_data->meta);
0669             unsigned long data_len = (void*)payload - (void*)kill_data;
0670             data_len = data_len > sizeof(struct var_kill_data_t)
0671                 ? sizeof(struct var_kill_data_t)
0672                 : data_len;
0673             bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, kill_data, data_len);
0674         }
0675     }
0676     bpf_map_delete_elem(&var_tpid_to_data, &tpid);
0677 out:
0678     bpf_stats_exit(&stats_ctx);
0679     return 0;
0680 }
0681 
0682 SEC("raw_tracepoint/sched_process_exec")
0683 int raw_tracepoint__sched_process_exec(struct bpf_raw_tracepoint_args* ctx)
0684 {
0685     struct bpf_func_stats_ctx stats_ctx;
0686     bpf_stats_enter(&stats_ctx, profiler_bpf_sched_process_exec);
0687 
0688     struct linux_binprm* bprm = (struct linux_binprm*)ctx->args[2];
0689     u64 inode = BPF_CORE_READ(bprm, file, f_inode, i_ino);
0690 
0691     bool* should_filter_binprm = bpf_map_lookup_elem(&disallowed_exec_inodes, &inode);
0692     if (should_filter_binprm != NULL)
0693         goto out;
0694 
0695     int zero = 0;
0696     struct var_exec_data_t* proc_exec_data = bpf_map_lookup_elem(&data_heap, &zero);
0697     if (!proc_exec_data)
0698         goto out;
0699 
0700     if (INODE_FILTER && inode != INODE_FILTER)
0701         return 0;
0702 
0703     u32 pid = get_userspace_pid();
0704     struct task_struct* task = (struct task_struct*)bpf_get_current_task();
0705 
0706     proc_exec_data->meta.type = EXEC_EVENT;
0707     proc_exec_data->bin_path_length = 0;
0708     proc_exec_data->cmdline_length = 0;
0709     proc_exec_data->environment_length = 0;
0710     void* payload = populate_var_metadata(&proc_exec_data->meta, task, pid,
0711                           proc_exec_data->payload);
0712     payload = populate_cgroup_info(&proc_exec_data->cgroup_data, task, payload);
0713 
0714     struct task_struct* parent_task = BPF_CORE_READ(task, real_parent);
0715     proc_exec_data->parent_pid = BPF_CORE_READ(parent_task, tgid);
0716     proc_exec_data->parent_uid = BPF_CORE_READ(parent_task, real_cred, uid.val);
0717     proc_exec_data->parent_exec_id = BPF_CORE_READ(parent_task, self_exec_id);
0718     proc_exec_data->parent_start_time = BPF_CORE_READ(parent_task, start_time);
0719 
0720     const char* filename = BPF_CORE_READ(bprm, filename);
0721     size_t bin_path_length = bpf_probe_read_str(payload, MAX_FILENAME_LEN, filename);
0722     barrier_var(bin_path_length);
0723     if (bin_path_length <= MAX_FILENAME_LEN) {
0724         barrier_var(bin_path_length);
0725         proc_exec_data->bin_path_length = bin_path_length;
0726         payload += bin_path_length;
0727     }
0728 
0729     void* arg_start = (void*)BPF_CORE_READ(task, mm, arg_start);
0730     void* arg_end = (void*)BPF_CORE_READ(task, mm, arg_end);
0731     unsigned int cmdline_length = probe_read_lim(payload, arg_start,
0732                              arg_end - arg_start, MAX_ARGS_LEN);
0733 
0734     if (cmdline_length <= MAX_ARGS_LEN) {
0735         barrier_var(cmdline_length);
0736         proc_exec_data->cmdline_length = cmdline_length;
0737         payload += cmdline_length;
0738     }
0739 
0740     if (READ_ENVIRON_FROM_EXEC) {
0741         void* env_start = (void*)BPF_CORE_READ(task, mm, env_start);
0742         void* env_end = (void*)BPF_CORE_READ(task, mm, env_end);
0743         unsigned long env_len = probe_read_lim(payload, env_start,
0744                                env_end - env_start, MAX_ENVIRON_LEN);
0745         if (cmdline_length <= MAX_ENVIRON_LEN) {
0746             proc_exec_data->environment_length = env_len;
0747             payload += env_len;
0748         }
0749     }
0750 
0751     bpf_stats_pre_submit_var_perf_event(&stats_ctx, &proc_exec_data->meta);
0752     unsigned long data_len = payload - (void*)proc_exec_data;
0753     data_len = data_len > sizeof(struct var_exec_data_t)
0754         ? sizeof(struct var_exec_data_t)
0755         : data_len;
0756     bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, proc_exec_data, data_len);
0757 out:
0758     bpf_stats_exit(&stats_ctx);
0759     return 0;
0760 }
0761 
0762 SEC("kretprobe/do_filp_open")
0763 int kprobe_ret__do_filp_open(struct pt_regs* ctx)
0764 {
0765     struct bpf_func_stats_ctx stats_ctx;
0766     bpf_stats_enter(&stats_ctx, profiler_bpf_do_filp_open_ret);
0767 
0768     struct file* filp = (struct file*)PT_REGS_RC_CORE(ctx);
0769 
0770     if (filp == NULL || IS_ERR(filp))
0771         goto out;
0772     unsigned int flags = BPF_CORE_READ(filp, f_flags);
0773     if ((flags & (O_RDWR | O_WRONLY)) == 0)
0774         goto out;
0775     if ((flags & O_TMPFILE) > 0)
0776         goto out;
0777     struct inode* file_inode = BPF_CORE_READ(filp, f_inode);
0778     umode_t mode = BPF_CORE_READ(file_inode, i_mode);
0779     if (S_ISDIR(mode) || S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) ||
0780         S_ISSOCK(mode))
0781         goto out;
0782 
0783     struct dentry* filp_dentry = BPF_CORE_READ(filp, f_path.dentry);
0784     u32 device_id = 0;
0785     u64 file_ino = 0;
0786     if (!is_dentry_allowed_for_filemod(filp_dentry, &device_id, &file_ino))
0787         goto out;
0788 
0789     int zero = 0;
0790     struct var_filemod_data_t* filemod_data = bpf_map_lookup_elem(&data_heap, &zero);
0791     if (!filemod_data)
0792         goto out;
0793 
0794     u32 pid = get_userspace_pid();
0795     struct task_struct* task = (struct task_struct*)bpf_get_current_task();
0796 
0797     filemod_data->meta.type = FILEMOD_EVENT;
0798     filemod_data->fmod_type = FMOD_OPEN;
0799     filemod_data->dst_flags = flags;
0800     filemod_data->src_inode = 0;
0801     filemod_data->dst_inode = file_ino;
0802     filemod_data->src_device_id = 0;
0803     filemod_data->dst_device_id = device_id;
0804     filemod_data->src_filepath_length = 0;
0805     filemod_data->dst_filepath_length = 0;
0806 
0807     void* payload = populate_var_metadata(&filemod_data->meta, task, pid,
0808                           filemod_data->payload);
0809     payload = populate_cgroup_info(&filemod_data->cgroup_data, task, payload);
0810 
0811     size_t len = read_absolute_file_path_from_dentry(filp_dentry, payload);
0812     barrier_var(len);
0813     if (len <= MAX_FILEPATH_LENGTH) {
0814         barrier_var(len);
0815         payload += len;
0816         filemod_data->dst_filepath_length = len;
0817     }
0818     bpf_stats_pre_submit_var_perf_event(&stats_ctx, &filemod_data->meta);
0819     unsigned long data_len = payload - (void*)filemod_data;
0820     data_len = data_len > sizeof(*filemod_data) ? sizeof(*filemod_data) : data_len;
0821     bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, filemod_data, data_len);
0822 out:
0823     bpf_stats_exit(&stats_ctx);
0824     return 0;
0825 }
0826 
0827 SEC("kprobe/vfs_link")
0828 int BPF_KPROBE(kprobe__vfs_link,
0829            struct dentry* old_dentry, struct user_namespace *mnt_userns,
0830            struct inode* dir, struct dentry* new_dentry,
0831            struct inode** delegated_inode)
0832 {
0833     struct bpf_func_stats_ctx stats_ctx;
0834     bpf_stats_enter(&stats_ctx, profiler_bpf_vfs_link);
0835 
0836     u32 src_device_id = 0;
0837     u64 src_file_ino = 0;
0838     u32 dst_device_id = 0;
0839     u64 dst_file_ino = 0;
0840     if (!is_dentry_allowed_for_filemod(old_dentry, &src_device_id, &src_file_ino) &&
0841         !is_dentry_allowed_for_filemod(new_dentry, &dst_device_id, &dst_file_ino))
0842         goto out;
0843 
0844     int zero = 0;
0845     struct var_filemod_data_t* filemod_data = bpf_map_lookup_elem(&data_heap, &zero);
0846     if (!filemod_data)
0847         goto out;
0848 
0849     u32 pid = get_userspace_pid();
0850     struct task_struct* task = (struct task_struct*)bpf_get_current_task();
0851 
0852     filemod_data->meta.type = FILEMOD_EVENT;
0853     filemod_data->fmod_type = FMOD_LINK;
0854     filemod_data->dst_flags = 0;
0855     filemod_data->src_inode = src_file_ino;
0856     filemod_data->dst_inode = dst_file_ino;
0857     filemod_data->src_device_id = src_device_id;
0858     filemod_data->dst_device_id = dst_device_id;
0859     filemod_data->src_filepath_length = 0;
0860     filemod_data->dst_filepath_length = 0;
0861 
0862     void* payload = populate_var_metadata(&filemod_data->meta, task, pid,
0863                           filemod_data->payload);
0864     payload = populate_cgroup_info(&filemod_data->cgroup_data, task, payload);
0865 
0866     size_t len = read_absolute_file_path_from_dentry(old_dentry, payload);
0867     barrier_var(len);
0868     if (len <= MAX_FILEPATH_LENGTH) {
0869         barrier_var(len);
0870         payload += len;
0871         filemod_data->src_filepath_length = len;
0872     }
0873 
0874     len = read_absolute_file_path_from_dentry(new_dentry, payload);
0875     barrier_var(len);
0876     if (len <= MAX_FILEPATH_LENGTH) {
0877         barrier_var(len);
0878         payload += len;
0879         filemod_data->dst_filepath_length = len;
0880     }
0881 
0882     bpf_stats_pre_submit_var_perf_event(&stats_ctx, &filemod_data->meta);
0883     unsigned long data_len = payload - (void*)filemod_data;
0884     data_len = data_len > sizeof(*filemod_data) ? sizeof(*filemod_data) : data_len;
0885     bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, filemod_data, data_len);
0886 out:
0887     bpf_stats_exit(&stats_ctx);
0888     return 0;
0889 }
0890 
0891 SEC("kprobe/vfs_symlink")
0892 int BPF_KPROBE(kprobe__vfs_symlink, struct inode* dir, struct dentry* dentry,
0893            const char* oldname)
0894 {
0895     struct bpf_func_stats_ctx stats_ctx;
0896     bpf_stats_enter(&stats_ctx, profiler_bpf_vfs_symlink);
0897 
0898     u32 dst_device_id = 0;
0899     u64 dst_file_ino = 0;
0900     if (!is_dentry_allowed_for_filemod(dentry, &dst_device_id, &dst_file_ino))
0901         goto out;
0902 
0903     int zero = 0;
0904     struct var_filemod_data_t* filemod_data = bpf_map_lookup_elem(&data_heap, &zero);
0905     if (!filemod_data)
0906         goto out;
0907 
0908     u32 pid = get_userspace_pid();
0909     struct task_struct* task = (struct task_struct*)bpf_get_current_task();
0910 
0911     filemod_data->meta.type = FILEMOD_EVENT;
0912     filemod_data->fmod_type = FMOD_SYMLINK;
0913     filemod_data->dst_flags = 0;
0914     filemod_data->src_inode = 0;
0915     filemod_data->dst_inode = dst_file_ino;
0916     filemod_data->src_device_id = 0;
0917     filemod_data->dst_device_id = dst_device_id;
0918     filemod_data->src_filepath_length = 0;
0919     filemod_data->dst_filepath_length = 0;
0920 
0921     void* payload = populate_var_metadata(&filemod_data->meta, task, pid,
0922                           filemod_data->payload);
0923     payload = populate_cgroup_info(&filemod_data->cgroup_data, task, payload);
0924 
0925     size_t len = bpf_probe_read_str(payload, MAX_FILEPATH_LENGTH, oldname);
0926     barrier_var(len);
0927     if (len <= MAX_FILEPATH_LENGTH) {
0928         barrier_var(len);
0929         payload += len;
0930         filemod_data->src_filepath_length = len;
0931     }
0932     len = read_absolute_file_path_from_dentry(dentry, payload);
0933     barrier_var(len);
0934     if (len <= MAX_FILEPATH_LENGTH) {
0935         barrier_var(len);
0936         payload += len;
0937         filemod_data->dst_filepath_length = len;
0938     }
0939     bpf_stats_pre_submit_var_perf_event(&stats_ctx, &filemod_data->meta);
0940     unsigned long data_len = payload - (void*)filemod_data;
0941     data_len = data_len > sizeof(*filemod_data) ? sizeof(*filemod_data) : data_len;
0942     bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, filemod_data, data_len);
0943 out:
0944     bpf_stats_exit(&stats_ctx);
0945     return 0;
0946 }
0947 
0948 SEC("raw_tracepoint/sched_process_fork")
0949 int raw_tracepoint__sched_process_fork(struct bpf_raw_tracepoint_args* ctx)
0950 {
0951     struct bpf_func_stats_ctx stats_ctx;
0952     bpf_stats_enter(&stats_ctx, profiler_bpf_sched_process_fork);
0953 
0954     int zero = 0;
0955     struct var_fork_data_t* fork_data = bpf_map_lookup_elem(&data_heap, &zero);
0956     if (!fork_data)
0957         goto out;
0958 
0959     struct task_struct* parent = (struct task_struct*)ctx->args[0];
0960     struct task_struct* child = (struct task_struct*)ctx->args[1];
0961     fork_data->meta.type = FORK_EVENT;
0962 
0963     void* payload = populate_var_metadata(&fork_data->meta, child,
0964                           BPF_CORE_READ(child, pid), fork_data->payload);
0965     fork_data->parent_pid = BPF_CORE_READ(parent, pid);
0966     fork_data->parent_exec_id = BPF_CORE_READ(parent, self_exec_id);
0967     fork_data->parent_start_time = BPF_CORE_READ(parent, start_time);
0968     bpf_stats_pre_submit_var_perf_event(&stats_ctx, &fork_data->meta);
0969 
0970     unsigned long data_len = payload - (void*)fork_data;
0971     data_len = data_len > sizeof(*fork_data) ? sizeof(*fork_data) : data_len;
0972     bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, fork_data, data_len);
0973 out:
0974     bpf_stats_exit(&stats_ctx);
0975     return 0;
0976 }
0977 char _license[] SEC("license") = "GPL";