xref: /aosp_15_r20/external/bcc/libbpf-tools/opensnoop.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Facebook
3 // Copyright (c) 2020 Netflix
4 #include <vmlinux.h>
5 #include <bpf/bpf_helpers.h>
6 #include "opensnoop.h"
7 
8 const volatile pid_t targ_pid = 0;
9 const volatile pid_t targ_tgid = 0;
10 const volatile uid_t targ_uid = 0;
11 const volatile bool targ_failed = false;
12 
13 struct {
14 	__uint(type, BPF_MAP_TYPE_HASH);
15 	__uint(max_entries, 10240);
16 	__type(key, u32);
17 	__type(value, struct args_t);
18 } start 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 static __always_inline
trace_allowed(u32 tgid,u32 pid)31 bool trace_allowed(u32 tgid, u32 pid)
32 {
33 	u32 uid;
34 
35 	/* filters */
36 	if (targ_tgid && targ_tgid != tgid)
37 		return false;
38 	if (targ_pid && targ_pid != pid)
39 		return false;
40 	if (valid_uid(targ_uid)) {
41 		uid = (u32)bpf_get_current_uid_gid();
42 		if (targ_uid != uid) {
43 			return false;
44 		}
45 	}
46 	return true;
47 }
48 
49 SEC("tracepoint/syscalls/sys_enter_open")
tracepoint__syscalls__sys_enter_open(struct trace_event_raw_sys_enter * ctx)50 int tracepoint__syscalls__sys_enter_open(struct trace_event_raw_sys_enter* ctx)
51 {
52 	u64 id = bpf_get_current_pid_tgid();
53 	/* use kernel terminology here for tgid/pid: */
54 	u32 tgid = id >> 32;
55 	u32 pid = id;
56 
57 	/* store arg info for later lookup */
58 	if (trace_allowed(tgid, pid)) {
59 		struct args_t args = {};
60 		args.fname = (const char *)ctx->args[0];
61 		args.flags = (int)ctx->args[1];
62 		bpf_map_update_elem(&start, &pid, &args, 0);
63 	}
64 	return 0;
65 }
66 
67 SEC("tracepoint/syscalls/sys_enter_openat")
tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter * ctx)68 int tracepoint__syscalls__sys_enter_openat(struct trace_event_raw_sys_enter* ctx)
69 {
70 	u64 id = bpf_get_current_pid_tgid();
71 	/* use kernel terminology here for tgid/pid: */
72 	u32 tgid = id >> 32;
73 	u32 pid = id;
74 
75 	/* store arg info for later lookup */
76 	if (trace_allowed(tgid, pid)) {
77 		struct args_t args = {};
78 		args.fname = (const char *)ctx->args[1];
79 		args.flags = (int)ctx->args[2];
80 		bpf_map_update_elem(&start, &pid, &args, 0);
81 	}
82 	return 0;
83 }
84 
85 static __always_inline
trace_exit(struct trace_event_raw_sys_exit * ctx)86 int trace_exit(struct trace_event_raw_sys_exit* ctx)
87 {
88 	struct event event = {};
89 	struct args_t *ap;
90 	uintptr_t stack[3];
91 	int ret;
92 	u32 pid = bpf_get_current_pid_tgid();
93 
94 	ap = bpf_map_lookup_elem(&start, &pid);
95 	if (!ap)
96 		return 0;	/* missed entry */
97 	ret = ctx->ret;
98 	if (targ_failed && ret >= 0)
99 		goto cleanup;	/* want failed only */
100 
101 	/* event data */
102 	event.pid = bpf_get_current_pid_tgid() >> 32;
103 	event.uid = bpf_get_current_uid_gid();
104 	bpf_get_current_comm(&event.comm, sizeof(event.comm));
105 	bpf_probe_read_user_str(&event.fname, sizeof(event.fname), ap->fname);
106 	event.flags = ap->flags;
107 	event.ret = ret;
108 
109 	bpf_get_stack(ctx, &stack, sizeof(stack),
110 		      BPF_F_USER_STACK);
111 	/* Skip the first address that is usually the syscall it-self */
112 	event.callers[0] = stack[1];
113 	event.callers[1] = stack[2];
114 
115 	/* emit event */
116 	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU,
117 			      &event, sizeof(event));
118 
119 cleanup:
120 	bpf_map_delete_elem(&start, &pid);
121 	return 0;
122 }
123 
124 SEC("tracepoint/syscalls/sys_exit_open")
tracepoint__syscalls__sys_exit_open(struct trace_event_raw_sys_exit * ctx)125 int tracepoint__syscalls__sys_exit_open(struct trace_event_raw_sys_exit* ctx)
126 {
127 	return trace_exit(ctx);
128 }
129 
130 SEC("tracepoint/syscalls/sys_exit_openat")
tracepoint__syscalls__sys_exit_openat(struct trace_event_raw_sys_exit * ctx)131 int tracepoint__syscalls__sys_exit_openat(struct trace_event_raw_sys_exit* ctx)
132 {
133 	return trace_exit(ctx);
134 }
135 
136 char LICENSE[] SEC("license") = "GPL";
137