0001
0002
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 {
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,
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";