xref: /aosp_15_r20/external/bcc/libbpf-tools/statsnoop.bpf.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2021 Hengqi Chen
3 #include <vmlinux.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include "statsnoop.h"
7 
8 #define MAX_ENTRIES 10240
9 
10 const volatile pid_t target_pid = 0;
11 const volatile bool  trace_failed_only = false;
12 
13 struct {
14 	__uint(type, BPF_MAP_TYPE_HASH);
15 	__uint(max_entries, MAX_ENTRIES);
16 	__type(key, __u32);
17 	__type(value, const char *);
18 } values 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 
probe_entry(void * ctx,const char * pathname)26 static int probe_entry(void *ctx, const char *pathname)
27 {
28 	__u64 id = bpf_get_current_pid_tgid();
29 	__u32 pid = id >> 32;
30 	__u32 tid = (__u32)id;
31 
32 	if (!pathname)
33 		return 0;
34 
35 	if (target_pid && target_pid != pid)
36 		return 0;
37 
38 	bpf_map_update_elem(&values, &tid, &pathname, BPF_ANY);
39 	return 0;
40 };
41 
probe_return(void * ctx,int ret)42 static int probe_return(void *ctx, int ret)
43 {
44 	__u64 id = bpf_get_current_pid_tgid();
45 	__u32 pid = id >> 32;
46 	__u32 tid = (__u32)id;
47 	const char **pathname;
48 	struct event event = {};
49 
50 	pathname = bpf_map_lookup_elem(&values, &tid);
51 	if (!pathname)
52 		return 0;
53 
54 	if (trace_failed_only && ret >= 0) {
55 		bpf_map_delete_elem(&values, &tid);
56 		return 0;
57 	}
58 
59 	event.pid = pid;
60 	event.ts_ns = bpf_ktime_get_ns();
61 	event.ret = ret;
62 	bpf_get_current_comm(&event.comm, sizeof(event.comm));
63 	bpf_probe_read_user_str(event.pathname, sizeof(event.pathname), *pathname);
64 
65 	bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &event, sizeof(event));
66 	bpf_map_delete_elem(&values, &tid);
67 	return 0;
68 }
69 
70 SEC("tracepoint/syscalls/sys_enter_statfs")
handle_statfs_entry(struct trace_event_raw_sys_enter * ctx)71 int handle_statfs_entry(struct trace_event_raw_sys_enter *ctx)
72 {
73 	return probe_entry(ctx, (const char *)ctx->args[0]);
74 }
75 
76 SEC("tracepoint/syscalls/sys_exit_statfs")
handle_statfs_return(struct trace_event_raw_sys_exit * ctx)77 int handle_statfs_return(struct trace_event_raw_sys_exit *ctx)
78 {
79 	return probe_return(ctx, (int)ctx->ret);
80 }
81 
82 SEC("tracepoint/syscalls/sys_enter_newstat")
handle_newstat_entry(struct trace_event_raw_sys_enter * ctx)83 int handle_newstat_entry(struct trace_event_raw_sys_enter *ctx)
84 {
85 	return probe_entry(ctx, (const char *)ctx->args[0]);
86 }
87 
88 SEC("tracepoint/syscalls/sys_exit_newstat")
handle_newstat_return(struct trace_event_raw_sys_exit * ctx)89 int handle_newstat_return(struct trace_event_raw_sys_exit *ctx)
90 {
91 	return probe_return(ctx, (int)ctx->ret);
92 }
93 
94 SEC("tracepoint/syscalls/sys_enter_statx")
handle_statx_entry(struct trace_event_raw_sys_enter * ctx)95 int handle_statx_entry(struct trace_event_raw_sys_enter *ctx)
96 {
97 	return probe_entry(ctx, (const char *)ctx->args[1]);
98 }
99 
100 SEC("tracepoint/syscalls/sys_exit_statx")
handle_statx_return(struct trace_event_raw_sys_exit * ctx)101 int handle_statx_return(struct trace_event_raw_sys_exit *ctx)
102 {
103 	return probe_return(ctx, (int)ctx->ret);
104 }
105 
106 SEC("tracepoint/syscalls/sys_enter_newfstatat")
handle_newfstatat_entry(struct trace_event_raw_sys_enter * ctx)107 int handle_newfstatat_entry(struct trace_event_raw_sys_enter *ctx)
108 {
109 	return probe_entry(ctx, (const char *)ctx->args[1]);
110 }
111 
112 SEC("tracepoint/syscalls/sys_exit_newfstatat")
handle_newfstatat_return(struct trace_event_raw_sys_exit * ctx)113 int handle_newfstatat_return(struct trace_event_raw_sys_exit *ctx)
114 {
115 	return probe_return(ctx, (int)ctx->ret);
116 }
117 
118 SEC("tracepoint/syscalls/sys_enter_newlstat")
handle_newlstat_entry(struct trace_event_raw_sys_enter * ctx)119 int handle_newlstat_entry(struct trace_event_raw_sys_enter *ctx)
120 {
121 	return probe_entry(ctx, (const char *)ctx->args[0]);
122 }
123 
124 SEC("tracepoint/syscalls/sys_exit_newlstat")
handle_newlstat_return(struct trace_event_raw_sys_exit * ctx)125 int handle_newlstat_return(struct trace_event_raw_sys_exit *ctx)
126 {
127 	return probe_return(ctx, (int)ctx->ret);
128 }
129 
130 char LICENSE[] SEC("license") = "GPL";
131