aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/testing/selftests/bpf/progs/test_core_autosize.c
blob: 9a7829c5e4a725c475eca53bf6504156fba6cad7 (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
173
174
175
176
177
178
179
180
181
182
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020 Facebook */

#include <linux/bpf.h>
#include <stdint.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>

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

/* fields of exactly the same size */
struct test_struct___samesize {
	void *ptr;
	unsigned long long val1;
	unsigned int val2;
	unsigned short val3;
	unsigned char val4;
} __attribute((preserve_access_index));

/* unsigned fields that have to be downsized by libbpf */
struct test_struct___downsize {
	void *ptr;
	unsigned long val1;
	unsigned long val2;
	unsigned long val3;
	unsigned long val4;
	/* total sz: 40 */
} __attribute__((preserve_access_index));

/* fields with signed integers of wrong size, should be rejected */
struct test_struct___signed {
	void *ptr;
	long val1;
	long val2;
	long val3;
	long val4;
} __attribute((preserve_access_index));

/* real layout and sizes according to test's (32-bit) BTF */
struct test_struct___real {
	unsigned int ptr; /* can't use `void *`, it is always 8 byte in BPF target */
	unsigned int val2;
	unsigned long long val1;
	unsigned short val3;
	unsigned char val4;
	unsigned char _pad;
	/* total sz: 20 */
};

struct test_struct___real input = {
	.ptr = 0x01020304,
	.val1 = 0x1020304050607080,
	.val2 = 0x0a0b0c0d,
	.val3 = 0xfeed,
	.val4 = 0xb9,
	._pad = 0xff, /* make sure no accidental zeros are present */
};

unsigned long long ptr_samesized = 0;
unsigned long long val1_samesized = 0;
unsigned long long val2_samesized = 0;
unsigned long long val3_samesized = 0;
unsigned long long val4_samesized = 0;
struct test_struct___real output_samesized = {};

unsigned long long ptr_downsized = 0;
unsigned long long val1_downsized = 0;
unsigned long long val2_downsized = 0;
unsigned long long val3_downsized = 0;
unsigned long long val4_downsized = 0;
struct test_struct___real output_downsized = {};

unsigned long long ptr_probed = 0;
unsigned long long val1_probed = 0;
unsigned long long val2_probed = 0;
unsigned long long val3_probed = 0;
unsigned long long val4_probed = 0;

unsigned long long ptr_signed = 0;
unsigned long long val1_signed = 0;
unsigned long long val2_signed = 0;
unsigned long long val3_signed = 0;
unsigned long long val4_signed = 0;
struct test_struct___real output_signed = {};

SEC("raw_tp/sys_exit")
int handle_samesize(void *ctx)
{
	struct test_struct___samesize *in = (void *)&input;
	struct test_struct___samesize *out = (void *)&output_samesized;

	ptr_samesized = (unsigned long long)in->ptr;
	val1_samesized = in->val1;
	val2_samesized = in->val2;
	val3_samesized = in->val3;
	val4_samesized = in->val4;

	out->ptr = in->ptr;
	out->val1 = in->val1;
	out->val2 = in->val2;
	out->val3 = in->val3;
	out->val4 = in->val4;

	return 0;
}

SEC("raw_tp/sys_exit")
int handle_downsize(void *ctx)
{
	struct test_struct___downsize *in = (void *)&input;
	struct test_struct___downsize *out = (void *)&output_downsized;

	ptr_downsized = (unsigned long long)in->ptr;
	val1_downsized = in->val1;
	val2_downsized = in->val2;
	val3_downsized = in->val3;
	val4_downsized = in->val4;

	out->ptr = in->ptr;
	out->val1 = in->val1;
	out->val2 = in->val2;
	out->val3 = in->val3;
	out->val4 = in->val4;

	return 0;
}

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define bpf_core_read_int bpf_core_read
#else
#define bpf_core_read_int(dst, sz, src) ({ \
	/* Prevent "subtraction from stack pointer prohibited" */ \
	volatile long __off = sizeof(*dst) - (sz); \
	bpf_core_read((char *)(dst) + __off, sz, src); \
})
#endif

SEC("raw_tp/sys_enter")
int handle_probed(void *ctx)
{
	struct test_struct___downsize *in = (void *)&input;
	__u64 tmp;

	tmp = 0;
	bpf_core_read_int(&tmp, bpf_core_field_size(in->ptr), &in->ptr);
	ptr_probed = tmp;

	tmp = 0;
	bpf_core_read_int(&tmp, bpf_core_field_size(in->val1), &in->val1);
	val1_probed = tmp;

	tmp = 0;
	bpf_core_read_int(&tmp, bpf_core_field_size(in->val2), &in->val2);
	val2_probed = tmp;

	tmp = 0;
	bpf_core_read_int(&tmp, bpf_core_field_size(in->val3), &in->val3);
	val3_probed = tmp;

	tmp = 0;
	bpf_core_read_int(&tmp, bpf_core_field_size(in->val4), &in->val4);
	val4_probed = tmp;

	return 0;
}

SEC("raw_tp/sys_enter")
int handle_signed(void *ctx)
{
	struct test_struct___signed *in = (void *)&input;
	struct test_struct___signed *out = (void *)&output_signed;

	val2_signed = in->val2;
	val3_signed = in->val3;
	val4_signed = in->val4;

	out->val2= in->val2;
	out->val3= in->val3;
	out->val4= in->val4;

	return 0;
}