1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2*387f9dfdSAndroid Build Coastguard Worker #include <vmlinux.h>
3*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_helpers.h>
4*387f9dfdSAndroid Build Coastguard Worker #include <bpf/bpf_core_read.h>
5*387f9dfdSAndroid Build Coastguard Worker #include "execsnoop.h"
6*387f9dfdSAndroid Build Coastguard Worker
7*387f9dfdSAndroid Build Coastguard Worker const volatile bool filter_cg = false;
8*387f9dfdSAndroid Build Coastguard Worker const volatile bool ignore_failed = true;
9*387f9dfdSAndroid Build Coastguard Worker const volatile uid_t targ_uid = INVALID_UID;
10*387f9dfdSAndroid Build Coastguard Worker const volatile int max_args = DEFAULT_MAXARGS;
11*387f9dfdSAndroid Build Coastguard Worker
12*387f9dfdSAndroid Build Coastguard Worker static const struct event empty_event = {};
13*387f9dfdSAndroid Build Coastguard Worker
14*387f9dfdSAndroid Build Coastguard Worker struct {
15*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_CGROUP_ARRAY);
16*387f9dfdSAndroid Build Coastguard Worker __type(key, u32);
17*387f9dfdSAndroid Build Coastguard Worker __type(value, u32);
18*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, 1);
19*387f9dfdSAndroid Build Coastguard Worker } cgroup_map SEC(".maps");
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Worker struct {
22*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_HASH);
23*387f9dfdSAndroid Build Coastguard Worker __uint(max_entries, 10240);
24*387f9dfdSAndroid Build Coastguard Worker __type(key, pid_t);
25*387f9dfdSAndroid Build Coastguard Worker __type(value, struct event);
26*387f9dfdSAndroid Build Coastguard Worker } execs SEC(".maps");
27*387f9dfdSAndroid Build Coastguard Worker
28*387f9dfdSAndroid Build Coastguard Worker struct {
29*387f9dfdSAndroid Build Coastguard Worker __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
30*387f9dfdSAndroid Build Coastguard Worker __uint(key_size, sizeof(u32));
31*387f9dfdSAndroid Build Coastguard Worker __uint(value_size, sizeof(u32));
32*387f9dfdSAndroid Build Coastguard Worker } events SEC(".maps");
33*387f9dfdSAndroid Build Coastguard Worker
valid_uid(uid_t uid)34*387f9dfdSAndroid Build Coastguard Worker static __always_inline bool valid_uid(uid_t uid) {
35*387f9dfdSAndroid Build Coastguard Worker return uid != INVALID_UID;
36*387f9dfdSAndroid Build Coastguard Worker }
37*387f9dfdSAndroid Build Coastguard Worker
38*387f9dfdSAndroid Build Coastguard Worker SEC("tracepoint/syscalls/sys_enter_execve")
tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter * ctx)39*387f9dfdSAndroid Build Coastguard Worker int tracepoint__syscalls__sys_enter_execve(struct trace_event_raw_sys_enter* ctx)
40*387f9dfdSAndroid Build Coastguard Worker {
41*387f9dfdSAndroid Build Coastguard Worker u64 id;
42*387f9dfdSAndroid Build Coastguard Worker pid_t pid, tgid;
43*387f9dfdSAndroid Build Coastguard Worker int ret;
44*387f9dfdSAndroid Build Coastguard Worker struct event *event;
45*387f9dfdSAndroid Build Coastguard Worker struct task_struct *task;
46*387f9dfdSAndroid Build Coastguard Worker const char **args = (const char **)(ctx->args[1]);
47*387f9dfdSAndroid Build Coastguard Worker const char *argp;
48*387f9dfdSAndroid Build Coastguard Worker
49*387f9dfdSAndroid Build Coastguard Worker if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
50*387f9dfdSAndroid Build Coastguard Worker return 0;
51*387f9dfdSAndroid Build Coastguard Worker
52*387f9dfdSAndroid Build Coastguard Worker uid_t uid = (u32)bpf_get_current_uid_gid();
53*387f9dfdSAndroid Build Coastguard Worker int i;
54*387f9dfdSAndroid Build Coastguard Worker
55*387f9dfdSAndroid Build Coastguard Worker if (valid_uid(targ_uid) && targ_uid != uid)
56*387f9dfdSAndroid Build Coastguard Worker return 0;
57*387f9dfdSAndroid Build Coastguard Worker
58*387f9dfdSAndroid Build Coastguard Worker id = bpf_get_current_pid_tgid();
59*387f9dfdSAndroid Build Coastguard Worker pid = (pid_t)id;
60*387f9dfdSAndroid Build Coastguard Worker tgid = id >> 32;
61*387f9dfdSAndroid Build Coastguard Worker if (bpf_map_update_elem(&execs, &pid, &empty_event, BPF_NOEXIST))
62*387f9dfdSAndroid Build Coastguard Worker return 0;
63*387f9dfdSAndroid Build Coastguard Worker
64*387f9dfdSAndroid Build Coastguard Worker event = bpf_map_lookup_elem(&execs, &pid);
65*387f9dfdSAndroid Build Coastguard Worker if (!event)
66*387f9dfdSAndroid Build Coastguard Worker return 0;
67*387f9dfdSAndroid Build Coastguard Worker
68*387f9dfdSAndroid Build Coastguard Worker event->pid = tgid;
69*387f9dfdSAndroid Build Coastguard Worker event->uid = uid;
70*387f9dfdSAndroid Build Coastguard Worker task = (struct task_struct*)bpf_get_current_task();
71*387f9dfdSAndroid Build Coastguard Worker event->ppid = (pid_t)BPF_CORE_READ(task, real_parent, tgid);
72*387f9dfdSAndroid Build Coastguard Worker event->args_count = 0;
73*387f9dfdSAndroid Build Coastguard Worker event->args_size = 0;
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker ret = bpf_probe_read_user_str(event->args, ARGSIZE, (const char*)ctx->args[0]);
76*387f9dfdSAndroid Build Coastguard Worker if (ret < 0) {
77*387f9dfdSAndroid Build Coastguard Worker return 0;
78*387f9dfdSAndroid Build Coastguard Worker }
79*387f9dfdSAndroid Build Coastguard Worker if (ret <= ARGSIZE) {
80*387f9dfdSAndroid Build Coastguard Worker event->args_size += ret;
81*387f9dfdSAndroid Build Coastguard Worker } else {
82*387f9dfdSAndroid Build Coastguard Worker /* write an empty string */
83*387f9dfdSAndroid Build Coastguard Worker event->args[0] = '\0';
84*387f9dfdSAndroid Build Coastguard Worker event->args_size++;
85*387f9dfdSAndroid Build Coastguard Worker }
86*387f9dfdSAndroid Build Coastguard Worker
87*387f9dfdSAndroid Build Coastguard Worker event->args_count++;
88*387f9dfdSAndroid Build Coastguard Worker #pragma unroll
89*387f9dfdSAndroid Build Coastguard Worker for (i = 1; i < TOTAL_MAX_ARGS && i < max_args; i++) {
90*387f9dfdSAndroid Build Coastguard Worker ret = bpf_probe_read_user(&argp, sizeof(argp), &args[i]);
91*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
92*387f9dfdSAndroid Build Coastguard Worker return 0;
93*387f9dfdSAndroid Build Coastguard Worker
94*387f9dfdSAndroid Build Coastguard Worker if (event->args_size > LAST_ARG)
95*387f9dfdSAndroid Build Coastguard Worker return 0;
96*387f9dfdSAndroid Build Coastguard Worker
97*387f9dfdSAndroid Build Coastguard Worker ret = bpf_probe_read_user_str(&event->args[event->args_size], ARGSIZE, argp);
98*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
99*387f9dfdSAndroid Build Coastguard Worker return 0;
100*387f9dfdSAndroid Build Coastguard Worker
101*387f9dfdSAndroid Build Coastguard Worker event->args_count++;
102*387f9dfdSAndroid Build Coastguard Worker event->args_size += ret;
103*387f9dfdSAndroid Build Coastguard Worker }
104*387f9dfdSAndroid Build Coastguard Worker /* try to read one more argument to check if there is one */
105*387f9dfdSAndroid Build Coastguard Worker ret = bpf_probe_read_user(&argp, sizeof(argp), &args[max_args]);
106*387f9dfdSAndroid Build Coastguard Worker if (ret < 0)
107*387f9dfdSAndroid Build Coastguard Worker return 0;
108*387f9dfdSAndroid Build Coastguard Worker
109*387f9dfdSAndroid Build Coastguard Worker /* pointer to max_args+1 isn't null, asume we have more arguments */
110*387f9dfdSAndroid Build Coastguard Worker event->args_count++;
111*387f9dfdSAndroid Build Coastguard Worker return 0;
112*387f9dfdSAndroid Build Coastguard Worker }
113*387f9dfdSAndroid Build Coastguard Worker
114*387f9dfdSAndroid Build Coastguard Worker SEC("tracepoint/syscalls/sys_exit_execve")
tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit * ctx)115*387f9dfdSAndroid Build Coastguard Worker int tracepoint__syscalls__sys_exit_execve(struct trace_event_raw_sys_exit* ctx)
116*387f9dfdSAndroid Build Coastguard Worker {
117*387f9dfdSAndroid Build Coastguard Worker u64 id;
118*387f9dfdSAndroid Build Coastguard Worker pid_t pid;
119*387f9dfdSAndroid Build Coastguard Worker int ret;
120*387f9dfdSAndroid Build Coastguard Worker struct event *event;
121*387f9dfdSAndroid Build Coastguard Worker
122*387f9dfdSAndroid Build Coastguard Worker if (filter_cg && !bpf_current_task_under_cgroup(&cgroup_map, 0))
123*387f9dfdSAndroid Build Coastguard Worker return 0;
124*387f9dfdSAndroid Build Coastguard Worker
125*387f9dfdSAndroid Build Coastguard Worker u32 uid = (u32)bpf_get_current_uid_gid();
126*387f9dfdSAndroid Build Coastguard Worker
127*387f9dfdSAndroid Build Coastguard Worker if (valid_uid(targ_uid) && targ_uid != uid)
128*387f9dfdSAndroid Build Coastguard Worker return 0;
129*387f9dfdSAndroid Build Coastguard Worker id = bpf_get_current_pid_tgid();
130*387f9dfdSAndroid Build Coastguard Worker pid = (pid_t)id;
131*387f9dfdSAndroid Build Coastguard Worker event = bpf_map_lookup_elem(&execs, &pid);
132*387f9dfdSAndroid Build Coastguard Worker if (!event)
133*387f9dfdSAndroid Build Coastguard Worker return 0;
134*387f9dfdSAndroid Build Coastguard Worker ret = ctx->ret;
135*387f9dfdSAndroid Build Coastguard Worker if (ignore_failed && ret < 0)
136*387f9dfdSAndroid Build Coastguard Worker goto cleanup;
137*387f9dfdSAndroid Build Coastguard Worker
138*387f9dfdSAndroid Build Coastguard Worker event->retval = ret;
139*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&event->comm, sizeof(event->comm));
140*387f9dfdSAndroid Build Coastguard Worker size_t len = EVENT_SIZE(event);
141*387f9dfdSAndroid Build Coastguard Worker if (len <= sizeof(*event))
142*387f9dfdSAndroid Build Coastguard Worker bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, event, len);
143*387f9dfdSAndroid Build Coastguard Worker cleanup:
144*387f9dfdSAndroid Build Coastguard Worker bpf_map_delete_elem(&execs, &pid);
145*387f9dfdSAndroid Build Coastguard Worker return 0;
146*387f9dfdSAndroid Build Coastguard Worker }
147*387f9dfdSAndroid Build Coastguard Worker
148*387f9dfdSAndroid Build Coastguard Worker char LICENSE[] SEC("license") = "GPL";
149