1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2018 Facebook 3 4 #include <linux/bpf.h> 5 #include "bpf_helpers.h" 6 7 #ifndef PERF_MAX_STACK_DEPTH 8 #define PERF_MAX_STACK_DEPTH 127 9 #endif 10 11 struct { 12 __u32 type; 13 __u32 max_entries; 14 __u32 *key; 15 __u32 *value; 16 } control_map SEC(".maps") = { 17 .type = BPF_MAP_TYPE_ARRAY, 18 .max_entries = 1, 19 }; 20 21 struct { 22 __u32 type; 23 __u32 max_entries; 24 __u32 *key; 25 __u32 *value; 26 } stackid_hmap SEC(".maps") = { 27 .type = BPF_MAP_TYPE_HASH, 28 .max_entries = 16384, 29 }; 30 31 typedef struct bpf_stack_build_id stack_trace_t[PERF_MAX_STACK_DEPTH]; 32 33 struct { 34 __u32 type; 35 __u32 max_entries; 36 __u32 map_flags; 37 __u32 key_size; 38 __u32 value_size; 39 } stackmap SEC(".maps") = { 40 .type = BPF_MAP_TYPE_STACK_TRACE, 41 .max_entries = 128, 42 .map_flags = BPF_F_STACK_BUILD_ID, 43 .key_size = sizeof(__u32), 44 .value_size = sizeof(stack_trace_t), 45 }; 46 47 struct { 48 __u32 type; 49 __u32 max_entries; 50 __u32 *key; 51 /* there seems to be a bug in kernel not handling typedef properly */ 52 struct bpf_stack_build_id (*value)[PERF_MAX_STACK_DEPTH]; 53 } stack_amap SEC(".maps") = { 54 .type = BPF_MAP_TYPE_ARRAY, 55 .max_entries = 128, 56 }; 57 58 /* taken from /sys/kernel/debug/tracing/events/random/urandom_read/format */ 59 struct random_urandom_args { 60 unsigned long long pad; 61 int got_bits; 62 int pool_left; 63 int input_left; 64 }; 65 66 SEC("tracepoint/random/urandom_read") 67 int oncpu(struct random_urandom_args *args) 68 { 69 __u32 max_len = sizeof(struct bpf_stack_build_id) 70 * PERF_MAX_STACK_DEPTH; 71 __u32 key = 0, val = 0, *value_p; 72 void *stack_p; 73 74 value_p = bpf_map_lookup_elem(&control_map, &key); 75 if (value_p && *value_p) 76 return 0; /* skip if non-zero *value_p */ 77 78 /* The size of stackmap and stackid_hmap should be the same */ 79 key = bpf_get_stackid(args, &stackmap, BPF_F_USER_STACK); 80 if ((int)key >= 0) { 81 bpf_map_update_elem(&stackid_hmap, &key, &val, 0); 82 stack_p = bpf_map_lookup_elem(&stack_amap, &key); 83 if (stack_p) 84 bpf_get_stack(args, stack_p, max_len, 85 BPF_F_USER_STACK | BPF_F_USER_BUILD_ID); 86 } 87 88 return 0; 89 } 90 91 char _license[] SEC("license") = "GPL"; 92 __u32 _version SEC("version") = 1; /* ignored by tracepoints, required by libbpf.a */ 93