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