1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2018 Facebook |
3 | |
4 | #include <linux/bpf.h> |
5 | #include <bpf/bpf_helpers.h> |
6 | |
7 | #ifndef PERF_MAX_STACK_DEPTH |
8 | #define PERF_MAX_STACK_DEPTH 127 |
9 | #endif |
10 | |
11 | struct { |
12 | __uint(type, BPF_MAP_TYPE_ARRAY); |
13 | __uint(max_entries, 1); |
14 | __type(key, __u32); |
15 | __type(value, __u32); |
16 | } control_map SEC(".maps" ); |
17 | |
18 | struct { |
19 | __uint(type, BPF_MAP_TYPE_HASH); |
20 | __uint(max_entries, 16384); |
21 | __type(key, __u32); |
22 | __type(value, __u32); |
23 | } stackid_hmap SEC(".maps" ); |
24 | |
25 | typedef struct bpf_stack_build_id stack_trace_t[PERF_MAX_STACK_DEPTH]; |
26 | |
27 | struct { |
28 | __uint(type, BPF_MAP_TYPE_STACK_TRACE); |
29 | __uint(max_entries, 128); |
30 | __uint(map_flags, BPF_F_STACK_BUILD_ID); |
31 | __type(key, __u32); |
32 | __type(value, stack_trace_t); |
33 | } stackmap SEC(".maps" ); |
34 | |
35 | struct { |
36 | __uint(type, BPF_MAP_TYPE_ARRAY); |
37 | __uint(max_entries, 128); |
38 | __type(key, __u32); |
39 | __type(value, stack_trace_t); |
40 | } stack_amap SEC(".maps" ); |
41 | |
42 | SEC("kprobe/urandom_read_iter" ) |
43 | int oncpu(struct pt_regs *args) |
44 | { |
45 | __u32 max_len = sizeof(struct bpf_stack_build_id) |
46 | * PERF_MAX_STACK_DEPTH; |
47 | __u32 key = 0, val = 0, *value_p; |
48 | void *stack_p; |
49 | |
50 | value_p = bpf_map_lookup_elem(&control_map, &key); |
51 | if (value_p && *value_p) |
52 | return 0; /* skip if non-zero *value_p */ |
53 | |
54 | /* The size of stackmap and stackid_hmap should be the same */ |
55 | key = bpf_get_stackid(args, &stackmap, BPF_F_USER_STACK); |
56 | if ((int)key >= 0) { |
57 | bpf_map_update_elem(&stackid_hmap, &key, &val, 0); |
58 | stack_p = bpf_map_lookup_elem(&stack_amap, &key); |
59 | if (stack_p) |
60 | bpf_get_stack(args, stack_p, max_len, |
61 | BPF_F_USER_STACK | BPF_F_USER_BUILD_ID); |
62 | } |
63 | |
64 | return 0; |
65 | } |
66 | |
67 | char _license[] SEC("license" ) = "GPL" ; |
68 | |