Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
1
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
b061017
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
accounting
arch
bpf
build
cgroup
crypto
debugging
firewire
firmware
gpio
hv
iio
include
io_uring
kvm/kvm_stat
laptop
leds
lib
memory-model
nfsd
objtool
pci
pcmcia
perf
power
scripts
spi
testing
fault-injection
ktest
nvdimm
radix-tree
scatterlist
selftests
android
bpf
gnu
include
map_tests
prog_tests
progs
bpf_flow.c
btf_dump_test_case_bitfields.c
btf_dump_test_case_multidim.c
btf_dump_test_case_namespacing.c
btf_dump_test_case_ordering.c
btf_dump_test_case_packing.c
btf_dump_test_case_padding.c
btf_dump_test_case_syntax.c
connect4_prog.c
connect6_prog.c
dev_cgroup.c
get_cgroup_id_kern.c
loop1.c
loop2.c
loop3.c
netcnt_prog.c
pyperf.h
pyperf100.c
pyperf180.c
pyperf50.c
pyperf600.c
pyperf600_nounroll.c
sample_map_ret0.c
sample_ret0.c
sendmsg4_prog.c
sendmsg6_prog.c
socket_cookie_prog.c
sockmap_parse_prog.c
sockmap_tcp_msg_prog.c
sockmap_verdict_prog.c
strobemeta.c
strobemeta.h
strobemeta_nounroll1.c
strobemeta_nounroll2.c
test_adjust_tail.c
test_btf_haskv.c
test_btf_newkv.c
test_btf_nokv.c
test_get_stack_rawtp.c
test_global_data.c
test_jhash.h
test_l4lb.c
test_l4lb_noinline.c
test_lirc_mode2_kern.c
test_lwt_ip_encap.c
test_lwt_seg6local.c
test_map_in_map.c
test_map_lock.c
test_obj_id.c
test_pkt_access.c
test_pkt_md_access.c
test_queue_map.c
test_seg6_loop.c
test_select_reuseport_kern.c
test_send_signal_kern.c
test_sk_lookup_kern.c
test_skb_cgroup_id_kern.c
test_skb_ctx.c
test_sock_fields_kern.c
test_sockhash_kern.c
test_sockmap_kern.c
test_spin_lock.c
test_stack_map.c
test_stacktrace_build_id.c
test_stacktrace_map.c
test_sysctl_loop1.c
test_sysctl_loop2.c
test_sysctl_prog.c
test_tc_edt.c
test_tc_tunnel.c
test_tcp_check_syncookie_kern.c
test_tcp_estats.c
test_tcpbpf_kern.c
test_tcpnotify_kern.c
test_tracepoint.c
test_tunnel_kern.c
test_verif_scale1.c
test_verif_scale2.c
test_verif_scale3.c
test_xdp.c
test_xdp_loop.c
test_xdp_meta.c
test_xdp_noinline.c
test_xdp_redirect.c
test_xdp_vlan.c
xdp_dummy.c
xdping_kern.c
verifier
.gitignore
Makefile
bpf_endian.h
bpf_helpers.h
bpf_rand.h
bpf_rlimit.h
bpf_util.h
cgroup_helpers.c
cgroup_helpers.h
config
flow_dissector_load.c
flow_dissector_load.h
get_cgroup_id_user.c
netcnt_common.h
tcp_client.py
tcp_server.py
test_align.c
test_btf.c
test_btf.h
test_btf_dump.c
test_cgroup_attach.c
test_cgroup_storage.c
test_dev_cgroup.c
test_flow_dissector.c
test_flow_dissector.sh
test_hashmap.c
test_iptunnel_common.h
test_kmod.sh
test_libbpf.sh
test_libbpf_open.c
test_lirc_mode2.sh
test_lirc_mode2_user.c
test_lpm_map.c
test_lru_map.c
test_lwt_ip_encap.sh
test_lwt_seg6local.sh
test_maps.c
test_maps.h
test_netcnt.c
test_offload.py
test_progs.c
test_progs.h
test_queue_stack_map.h
test_section_names.c
test_select_reuseport.c
test_select_reuseport_common.h
test_skb_cgroup_id.sh
test_skb_cgroup_id_user.c
test_sock.c
test_sock_addr.c
test_sock_addr.sh
test_sock_fields.c
test_socket_cookie.c
test_sockmap.c
test_sockmap_kern.h
test_stub.c
test_sysctl.c
test_tag.c
test_tc_edt.sh
test_tc_tunnel.sh
test_tcp_check_syncookie.sh
test_tcp_check_syncookie_user.c
test_tcpbpf.h
test_tcpbpf_user.c
test_tcpnotify.h
test_tcpnotify_user.c
test_tunnel.sh
test_verifier.c
test_verifier_log.c
test_xdp_meta.sh
test_xdp_redirect.sh
test_xdp_vlan.sh
test_xdping.sh
trace_helpers.c
trace_helpers.h
urandom_read.c
with_addr.sh
with_tunnels.sh
xdping.c
xdping.h
breakpoints
capabilities
cgroup
cpu-hotplug
cpufreq
drivers
efivarfs
exec
filesystems
firmware
ftrace
futex
gpio
ia64
intel_pstate
ipc
ir
kcmp
kexec
kmod
kselftest
kvm
lib
livepatch
locking
media_tests
membarrier
memfd
memory-hotplug
mount
mqueue
net
netfilter
networking
nsfs
ntb
pidfd
powerpc
prctl
proc
pstore
ptp
ptrace
rcutorture
rseq
rtc
safesetid
seccomp
sigaltstack
size
sparc64
splice
static_keys
sync
sysctl
tc-testing
timers
tmpfs
tpm2
uevent
user
vDSO
vm
watchdog
x86
zram
.gitignore
Makefile
gen_kselftest_tar.sh
kselftest.h
kselftest_harness.h
kselftest_install.sh
kselftest_module.h
kselftest_module.sh
lib.mk
vsock
thermal/tmon
time
usb
virtio
vm
wmi
Makefile
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
tools
/
testing
/
selftests
/
bpf
/
progs
/
pyperf.h
Copy path
Blame
Blame
Latest commit
History
History
272 lines (234 loc) · 6.75 KB
Breadcrumbs
linux
/
tools
/
testing
/
selftests
/
bpf
/
progs
/
pyperf.h
Top
File metadata and controls
Code
Blame
272 lines (234 loc) · 6.75 KB
Raw
// SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Facebook #include <linux/sched.h> #include <linux/ptrace.h> #include <stdint.h> #include <stddef.h> #include <stdbool.h> #include <linux/bpf.h> #include "bpf_helpers.h" #define FUNCTION_NAME_LEN 64 #define FILE_NAME_LEN 128 #define TASK_COMM_LEN 16 typedef struct { int PyThreadState_frame; int PyThreadState_thread; int PyFrameObject_back; int PyFrameObject_code; int PyFrameObject_lineno; int PyCodeObject_filename; int PyCodeObject_name; int String_data; int String_size; } OffsetConfig; typedef struct { uintptr_t current_state_addr; uintptr_t tls_key_addr; OffsetConfig offsets; bool use_tls; } PidData; typedef struct { uint32_t success; } Stats; typedef struct { char name[FUNCTION_NAME_LEN]; char file[FILE_NAME_LEN]; } Symbol; typedef struct { uint32_t pid; uint32_t tid; char comm[TASK_COMM_LEN]; int32_t kernel_stack_id; int32_t user_stack_id; bool thread_current; bool pthread_match; bool stack_complete; int16_t stack_len; int32_t stack[STACK_MAX_LEN]; int has_meta; int metadata; char dummy_safeguard; } Event; struct bpf_elf_map { __u32 type; __u32 size_key; __u32 size_value; __u32 max_elem; __u32 flags; }; typedef int pid_t; typedef struct { void* f_back; // PyFrameObject.f_back, previous frame void* f_code; // PyFrameObject.f_code, pointer to PyCodeObject void* co_filename; // PyCodeObject.co_filename void* co_name; // PyCodeObject.co_name } FrameData; static inline __attribute__((__always_inline__)) void* get_thread_state(void* tls_base, PidData* pidData) { void* thread_state; int key; bpf_probe_read(&key, sizeof(key), (void*)(long)pidData->tls_key_addr); bpf_probe_read(&thread_state, sizeof(thread_state), tls_base + 0x310 + key * 0x10 + 0x08); return thread_state; } static inline __attribute__((__always_inline__)) bool get_frame_data(void* frame_ptr, PidData* pidData, FrameData* frame, Symbol* symbol) { // read data from PyFrameObject bpf_probe_read(&frame->f_back, sizeof(frame->f_back), frame_ptr + pidData->offsets.PyFrameObject_back); bpf_probe_read(&frame->f_code, sizeof(frame->f_code), frame_ptr + pidData->offsets.PyFrameObject_code); // read data from PyCodeObject if (!frame->f_code) return false; bpf_probe_read(&frame->co_filename, sizeof(frame->co_filename), frame->f_code + pidData->offsets.PyCodeObject_filename); bpf_probe_read(&frame->co_name, sizeof(frame->co_name), frame->f_code + pidData->offsets.PyCodeObject_name); // read actual names into symbol if (frame->co_filename) bpf_probe_read_str(&symbol->file, sizeof(symbol->file), frame->co_filename + pidData->offsets.String_data); if (frame->co_name) bpf_probe_read_str(&symbol->name, sizeof(symbol->name), frame->co_name + pidData->offsets.String_data); return true; } struct bpf_elf_map SEC("maps") pidmap = { .type = BPF_MAP_TYPE_HASH, .size_key = sizeof(int), .size_value = sizeof(PidData), .max_elem = 1, }; struct bpf_elf_map SEC("maps") eventmap = { .type = BPF_MAP_TYPE_HASH, .size_key = sizeof(int), .size_value = sizeof(Event), .max_elem = 1, }; struct bpf_elf_map SEC("maps") symbolmap = { .type = BPF_MAP_TYPE_HASH, .size_key = sizeof(Symbol), .size_value = sizeof(int), .max_elem = 1, }; struct bpf_elf_map SEC("maps") statsmap = { .type = BPF_MAP_TYPE_ARRAY, .size_key = sizeof(Stats), .size_value = sizeof(int), .max_elem = 1, }; struct bpf_elf_map SEC("maps") perfmap = { .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY, .size_key = sizeof(int), .size_value = sizeof(int), .max_elem = 32, }; struct bpf_elf_map SEC("maps") stackmap = { .type = BPF_MAP_TYPE_STACK_TRACE, .size_key = sizeof(int), .size_value = sizeof(long long) * 127, .max_elem = 1000, }; static inline __attribute__((__always_inline__)) int __on_event(struct pt_regs *ctx) { uint64_t pid_tgid = bpf_get_current_pid_tgid(); pid_t pid = (pid_t)(pid_tgid >> 32); PidData* pidData = bpf_map_lookup_elem(&pidmap, &pid); if (!pidData) return 0; int zero = 0; Event* event = bpf_map_lookup_elem(&eventmap, &zero); if (!event) return 0; event->pid = pid; event->tid = (pid_t)pid_tgid; bpf_get_current_comm(&event->comm, sizeof(event->comm)); event->user_stack_id = bpf_get_stackid(ctx, &stackmap, BPF_F_USER_STACK); event->kernel_stack_id = bpf_get_stackid(ctx, &stackmap, 0); void* thread_state_current = (void*)0; bpf_probe_read(&thread_state_current, sizeof(thread_state_current), (void*)(long)pidData->current_state_addr); struct task_struct* task = (struct task_struct*)bpf_get_current_task(); void* tls_base = (void*)task; void* thread_state = pidData->use_tls ? get_thread_state(tls_base, pidData) : thread_state_current; event->thread_current = thread_state == thread_state_current; if (pidData->use_tls) { uint64_t pthread_created; uint64_t pthread_self; bpf_probe_read(&pthread_self, sizeof(pthread_self), tls_base + 0x10); bpf_probe_read(&pthread_created, sizeof(pthread_created), thread_state + pidData->offsets.PyThreadState_thread); event->pthread_match = pthread_created == pthread_self; } else { event->pthread_match = 1; } if (event->pthread_match || !pidData->use_tls) { void* frame_ptr; FrameData frame; Symbol sym = {}; int cur_cpu = bpf_get_smp_processor_id(); bpf_probe_read(&frame_ptr, sizeof(frame_ptr), thread_state + pidData->offsets.PyThreadState_frame); int32_t* symbol_counter = bpf_map_lookup_elem(&symbolmap, &sym); if (symbol_counter == NULL) return 0; #ifdef NO_UNROLL #pragma clang loop unroll(disable) #else #pragma clang loop unroll(full) #endif /* Unwind python stack */ for (int i = 0; i < STACK_MAX_LEN; ++i) { if (frame_ptr && get_frame_data(frame_ptr, pidData, &frame, &sym)) { int32_t new_symbol_id = *symbol_counter * 64 + cur_cpu; int32_t *symbol_id = bpf_map_lookup_elem(&symbolmap, &sym); if (!symbol_id) { bpf_map_update_elem(&symbolmap, &sym, &zero, 0); symbol_id = bpf_map_lookup_elem(&symbolmap, &sym); if (!symbol_id) return 0; } if (*symbol_id == new_symbol_id) (*symbol_counter)++; event->stack[i] = *symbol_id; event->stack_len = i + 1; frame_ptr = frame.f_back; } } event->stack_complete = frame_ptr == NULL; } else { event->stack_complete = 1; } Stats* stats = bpf_map_lookup_elem(&statsmap, &zero); if (stats) stats->success++; event->has_meta = 0; bpf_perf_event_output(ctx, &perfmap, 0, event, offsetof(Event, metadata)); return 0; } SEC("raw_tracepoint/kfree_skb") int on_event(struct pt_regs* ctx) { int i, ret = 0; ret |= __on_event(ctx); ret |= __on_event(ctx); ret |= __on_event(ctx); ret |= __on_event(ctx); ret |= __on_event(ctx); return ret; } char _license[] SEC("license") = "GPL";
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
You can’t perform that action at this time.