1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3 #include "vmlinux.h"
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include <bpf/bpf_core_read.h>
7 #include "bpf_misc.h"
8
9 char _license[] SEC("license") = "GPL";
10
11 static long stack[256];
12
13 /*
14 * KPROBE contexts
15 */
16
kprobe_typedef_ctx_subprog(bpf_user_pt_regs_t * ctx)17 __weak int kprobe_typedef_ctx_subprog(bpf_user_pt_regs_t *ctx)
18 {
19 return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
20 }
21
22 SEC("?kprobe")
23 __success
kprobe_typedef_ctx(void * ctx)24 int kprobe_typedef_ctx(void *ctx)
25 {
26 return kprobe_typedef_ctx_subprog(ctx);
27 }
28
29 #define pt_regs_struct_t typeof(*(__PT_REGS_CAST((struct pt_regs *)NULL)))
30
kprobe_struct_ctx_subprog(pt_regs_struct_t * ctx)31 __weak int kprobe_struct_ctx_subprog(pt_regs_struct_t *ctx)
32 {
33 return bpf_get_stack((void *)ctx, &stack, sizeof(stack), 0);
34 }
35
36 SEC("?kprobe")
37 __success
kprobe_resolved_ctx(void * ctx)38 int kprobe_resolved_ctx(void *ctx)
39 {
40 return kprobe_struct_ctx_subprog(ctx);
41 }
42
43 /* this is current hack to make this work on old kernels */
44 struct bpf_user_pt_regs_t {};
45
kprobe_workaround_ctx_subprog(struct bpf_user_pt_regs_t * ctx)46 __weak int kprobe_workaround_ctx_subprog(struct bpf_user_pt_regs_t *ctx)
47 {
48 return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
49 }
50
51 SEC("?kprobe")
52 __success
kprobe_workaround_ctx(void * ctx)53 int kprobe_workaround_ctx(void *ctx)
54 {
55 return kprobe_workaround_ctx_subprog(ctx);
56 }
57
58 /*
59 * RAW_TRACEPOINT contexts
60 */
61
raw_tp_ctx_subprog(struct bpf_raw_tracepoint_args * ctx)62 __weak int raw_tp_ctx_subprog(struct bpf_raw_tracepoint_args *ctx)
63 {
64 return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
65 }
66
67 SEC("?raw_tp")
68 __success
raw_tp_ctx(void * ctx)69 int raw_tp_ctx(void *ctx)
70 {
71 return raw_tp_ctx_subprog(ctx);
72 }
73
74 /*
75 * RAW_TRACEPOINT_WRITABLE contexts
76 */
77
raw_tp_writable_ctx_subprog(struct bpf_raw_tracepoint_args * ctx)78 __weak int raw_tp_writable_ctx_subprog(struct bpf_raw_tracepoint_args *ctx)
79 {
80 return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
81 }
82
83 SEC("?raw_tp")
84 __success
raw_tp_writable_ctx(void * ctx)85 int raw_tp_writable_ctx(void *ctx)
86 {
87 return raw_tp_writable_ctx_subprog(ctx);
88 }
89
90 /*
91 * PERF_EVENT contexts
92 */
93
perf_event_ctx_subprog(struct bpf_perf_event_data * ctx)94 __weak int perf_event_ctx_subprog(struct bpf_perf_event_data *ctx)
95 {
96 return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
97 }
98
99 SEC("?perf_event")
100 __success
perf_event_ctx(void * ctx)101 int perf_event_ctx(void *ctx)
102 {
103 return perf_event_ctx_subprog(ctx);
104 }
105
106 /* this global subprog can be now called from many types of entry progs, each
107 * with different context type
108 */
subprog_ctx_tag(void * ctx __arg_ctx)109 __weak int subprog_ctx_tag(void *ctx __arg_ctx)
110 {
111 return bpf_get_stack(ctx, stack, sizeof(stack), 0);
112 }
113
114 struct my_struct { int x; };
115
subprog_multi_ctx_tags(void * ctx1 __arg_ctx,struct my_struct * mem,void * ctx2 __arg_ctx)116 __weak int subprog_multi_ctx_tags(void *ctx1 __arg_ctx,
117 struct my_struct *mem,
118 void *ctx2 __arg_ctx)
119 {
120 if (!mem)
121 return 0;
122
123 return bpf_get_stack(ctx1, stack, sizeof(stack), 0) +
124 mem->x +
125 bpf_get_stack(ctx2, stack, sizeof(stack), 0);
126 }
127
128 SEC("?raw_tp")
129 __success __log_level(2)
arg_tag_ctx_raw_tp(void * ctx)130 int arg_tag_ctx_raw_tp(void *ctx)
131 {
132 struct my_struct x = { .x = 123 };
133
134 return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
135 }
136
137 SEC("?perf_event")
138 __success __log_level(2)
arg_tag_ctx_perf(void * ctx)139 int arg_tag_ctx_perf(void *ctx)
140 {
141 struct my_struct x = { .x = 123 };
142
143 return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
144 }
145
146 SEC("?kprobe")
147 __success __log_level(2)
arg_tag_ctx_kprobe(void * ctx)148 int arg_tag_ctx_kprobe(void *ctx)
149 {
150 struct my_struct x = { .x = 123 };
151
152 return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
153 }
154