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