this repo has no description
at main 2.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2/* Copyright (c) 2020 Facebook */ 3#include "vmlinux.h" 4#include <bpf/bpf_helpers.h> 5#include <bpf/bpf_tracing.h> 6#include <bpf/bpf_core_read.h> 7#include "bootstrap.h" 8 9char LICENSE[] SEC("license") = "Dual BSD/GPL"; 10 11struct { 12 __uint(type, BPF_MAP_TYPE_HASH); 13 __uint(max_entries, 8192); 14 __type(key, pid_t); 15 __type(value, u64); 16} exec_start SEC(".maps"); 17 18struct { 19 __uint(type, BPF_MAP_TYPE_RINGBUF); 20 __uint(max_entries, 256 * 1024); 21} rb SEC(".maps"); 22 23const volatile unsigned long long min_duration_ns = 0; 24 25SEC("tp/sched/sched_process_exec") 26int handle_exec(struct trace_event_raw_sched_process_exec *ctx) 27{ 28 struct task_struct *task; 29 unsigned fname_off; 30 struct event *e; 31 pid_t pid; 32 u64 ts; 33 34 /* remember time exec() was executed for this PID */ 35 pid = bpf_get_current_pid_tgid() >> 32; 36 ts = bpf_ktime_get_ns(); 37 bpf_map_update_elem(&exec_start, &pid, &ts, BPF_ANY); 38 39 /* don't emit exec events when minimum duration is specified */ 40 if (min_duration_ns) 41 return 0; 42 43 /* reserve sample from BPF ringbuf */ 44 e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); 45 if (!e) 46 return 0; 47 48 /* fill out the sample with data */ 49 task = (struct task_struct *)bpf_get_current_task(); 50 51 e->exit_event = false; 52 e->pid = pid; 53 e->ppid = BPF_CORE_READ(task, real_parent, tgid); 54 bpf_get_current_comm(&e->comm, sizeof(e->comm)); 55 56 fname_off = ctx->__data_loc_filename & 0xFFFF; 57 bpf_probe_read_str(&e->filename, sizeof(e->filename), (void *)ctx + fname_off); 58 59 /* successfully submit it to user-space for post-processing */ 60 bpf_ringbuf_submit(e, 0); 61 return 0; 62} 63 64SEC("tp/sched/sched_process_exit") 65int handle_exit(struct trace_event_raw_sched_process_template *ctx) 66{ 67 struct task_struct *task; 68 struct event *e; 69 pid_t pid, tid; 70 u64 id, ts, *start_ts, duration_ns = 0; 71 72 /* get PID and TID of exiting thread/process */ 73 id = bpf_get_current_pid_tgid(); 74 pid = id >> 32; 75 tid = (u32)id; 76 77 /* ignore thread exits */ 78 if (pid != tid) 79 return 0; 80 81 /* if we recorded start of the process, calculate lifetime duration */ 82 start_ts = bpf_map_lookup_elem(&exec_start, &pid); 83 if (start_ts) 84 duration_ns = bpf_ktime_get_ns() - *start_ts; 85 else if (min_duration_ns) 86 return 0; 87 bpf_map_delete_elem(&exec_start, &pid); 88 89 /* if process didn't live long enough, return early */ 90 if (min_duration_ns && duration_ns < min_duration_ns) 91 return 0; 92 93 /* reserve sample from BPF ringbuf */ 94 e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); 95 if (!e) 96 return 0; 97 98 /* fill out the sample with data */ 99 task = (struct task_struct *)bpf_get_current_task(); 100 101 e->exit_event = true; 102 e->duration_ns = duration_ns; 103 e->pid = pid; 104 e->ppid = BPF_CORE_READ(task, real_parent, tgid); 105 e->exit_code = (BPF_CORE_READ(task, exit_code) >> 8) & 0xff; 106 bpf_get_current_comm(&e->comm, sizeof(e->comm)); 107 108 /* send data to user-space for post-processing */ 109 bpf_ringbuf_submit(e, 0); 110 return 0; 111}