aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/testing/selftests/bpf/progs/test_global_func_ctx_args.c
blob: 143c8a4852bfe70506253ca880bac91a409b8a9f (plain) (blame)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "bpf_misc.h"

char _license[] SEC("license") = "GPL";

static long stack[256];

/*
 * KPROBE contexts
 */

__weak int kprobe_typedef_ctx_subprog(bpf_user_pt_regs_t *ctx)
{
	return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}

SEC("?kprobe")
__success
int kprobe_typedef_ctx(void *ctx)
{
	return kprobe_typedef_ctx_subprog(ctx);
}

/* s390x defines:
 *
 * typedef user_pt_regs bpf_user_pt_regs_t;
 * typedef struct { ... } user_pt_regs;
 *
 * And so "canonical" underlying struct type is anonymous.
 * So on s390x only valid ways to have PTR_TO_CTX argument in global subprogs
 * are:
 *   - bpf_user_pt_regs_t *ctx (typedef);
 *   - struct bpf_user_pt_regs_t *ctx (backwards compatible struct hack);
 *   - void *ctx __arg_ctx (arg:ctx tag)
 *
 * Other architectures also allow using underlying struct types (e.g.,
 * `struct pt_regs *ctx` for x86-64)
 */
#ifndef bpf_target_s390

#define pt_regs_struct_t typeof(*(__PT_REGS_CAST((struct pt_regs *)NULL)))

__weak int kprobe_struct_ctx_subprog(pt_regs_struct_t *ctx)
{
	return bpf_get_stack((void *)ctx, &stack, sizeof(stack), 0);
}

SEC("?kprobe")
__success
int kprobe_resolved_ctx(void *ctx)
{
	return kprobe_struct_ctx_subprog(ctx);
}

#endif

/* this is current hack to make this work on old kernels */
struct bpf_user_pt_regs_t {};

__weak int kprobe_workaround_ctx_subprog(struct bpf_user_pt_regs_t *ctx)
{
	return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}

SEC("?kprobe")
__success
int kprobe_workaround_ctx(void *ctx)
{
	return kprobe_workaround_ctx_subprog(ctx);
}

/*
 * RAW_TRACEPOINT contexts
 */

__weak int raw_tp_ctx_subprog(struct bpf_raw_tracepoint_args *ctx)
{
	return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}

SEC("?raw_tp")
__success
int raw_tp_ctx(void *ctx)
{
	return raw_tp_ctx_subprog(ctx);
}

/*
 * RAW_TRACEPOINT_WRITABLE contexts
 */

__weak int raw_tp_writable_ctx_subprog(struct bpf_raw_tracepoint_args *ctx)
{
	return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}

SEC("?raw_tp")
__success
int raw_tp_writable_ctx(void *ctx)
{
	return raw_tp_writable_ctx_subprog(ctx);
}

/*
 * PERF_EVENT contexts
 */

__weak int perf_event_ctx_subprog(struct bpf_perf_event_data *ctx)
{
	return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}

SEC("?perf_event")
__success
int perf_event_ctx(void *ctx)
{
	return perf_event_ctx_subprog(ctx);
}

/* this global subprog can be now called from many types of entry progs, each
 * with different context type
 */
__weak int subprog_ctx_tag(void *ctx __arg_ctx)
{
	return bpf_get_stack(ctx, stack, sizeof(stack), 0);
}

struct my_struct { int x; };

__weak int subprog_multi_ctx_tags(void *ctx1 __arg_ctx,
				  struct my_struct *mem,
				  void *ctx2 __arg_ctx)
{
	if (!mem)
		return 0;

	return bpf_get_stack(ctx1, stack, sizeof(stack), 0) +
	       mem->x +
	       bpf_get_stack(ctx2, stack, sizeof(stack), 0);
}

SEC("?raw_tp")
__success __log_level(2)
int arg_tag_ctx_raw_tp(void *ctx)
{
	struct my_struct x = { .x = 123 };

	return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
}

SEC("?perf_event")
__success __log_level(2)
int arg_tag_ctx_perf(void *ctx)
{
	struct my_struct x = { .x = 123 };

	return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
}

SEC("?kprobe")
__success __log_level(2)
int arg_tag_ctx_kprobe(void *ctx)
{
	struct my_struct x = { .x = 123 };

	return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
}