]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - tools/testing/selftests/bpf/test_align.c
Merge tag 'powerpc-4.13-8' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[mirror_ubuntu-artful-kernel.git] / tools / testing / selftests / bpf / test_align.c
CommitLineData
18b3ad90
DM
1#include <asm/types.h>
2#include <linux/types.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <errno.h>
8#include <string.h>
9#include <stddef.h>
10#include <stdbool.h>
11
f735b649
DB
12#include <sys/resource.h>
13
18b3ad90
DM
14#include <linux/unistd.h>
15#include <linux/filter.h>
16#include <linux/bpf_perf_event.h>
17#include <linux/bpf.h>
18
19#include <bpf/bpf.h>
20
21#include "../../../include/linux/filter.h"
22
23#ifndef ARRAY_SIZE
24# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
25#endif
26
27#define MAX_INSNS 512
28#define MAX_MATCHES 16
29
30struct bpf_align_test {
31 const char *descr;
32 struct bpf_insn insns[MAX_INSNS];
33 enum {
34 UNDEF,
35 ACCEPT,
36 REJECT
37 } result;
38 enum bpf_prog_type prog_type;
39 const char *matches[MAX_MATCHES];
40};
41
42static struct bpf_align_test tests[] = {
43 {
44 .descr = "mov",
45 .insns = {
46 BPF_MOV64_IMM(BPF_REG_3, 2),
47 BPF_MOV64_IMM(BPF_REG_3, 4),
48 BPF_MOV64_IMM(BPF_REG_3, 8),
49 BPF_MOV64_IMM(BPF_REG_3, 16),
50 BPF_MOV64_IMM(BPF_REG_3, 32),
51 BPF_MOV64_IMM(BPF_REG_0, 0),
52 BPF_EXIT_INSN(),
53 },
54 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
55 .matches = {
56 "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
57 "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
58 "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
59 "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
60 "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
61 },
62 },
63 {
64 .descr = "shift",
65 .insns = {
66 BPF_MOV64_IMM(BPF_REG_3, 1),
67 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
68 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
69 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
70 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
71 BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4),
72 BPF_MOV64_IMM(BPF_REG_4, 32),
73 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
74 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
75 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
76 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
77 BPF_MOV64_IMM(BPF_REG_0, 0),
78 BPF_EXIT_INSN(),
79 },
80 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
81 .matches = {
82 "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
83 "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
84 "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
85 "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
86 "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
87 "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
88 "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
89 "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
90 "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
91 "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
92 "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
93 },
94 },
95 {
96 .descr = "addsub",
97 .insns = {
98 BPF_MOV64_IMM(BPF_REG_3, 4),
99 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4),
100 BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2),
101 BPF_MOV64_IMM(BPF_REG_4, 8),
102 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
103 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
104 BPF_MOV64_IMM(BPF_REG_0, 0),
105 BPF_EXIT_INSN(),
106 },
107 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
108 .matches = {
109 "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
110 "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp",
111 "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp",
112 "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
113 "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp",
114 "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
115 },
116 },
117 {
118 .descr = "mul",
119 .insns = {
120 BPF_MOV64_IMM(BPF_REG_3, 7),
121 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1),
122 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2),
123 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4),
124 BPF_MOV64_IMM(BPF_REG_0, 0),
125 BPF_EXIT_INSN(),
126 },
127 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
128 .matches = {
129 "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
130 "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
131 "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
132 "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp",
133 },
134 },
135
136#define PREP_PKT_POINTERS \
137 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
138 offsetof(struct __sk_buff, data)), \
139 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \
140 offsetof(struct __sk_buff, data_end))
141
142#define LOAD_UNKNOWN(DST_REG) \
143 PREP_PKT_POINTERS, \
144 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \
145 BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \
146 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \
147 BPF_EXIT_INSN(), \
148 BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0)
149
150 {
151 .descr = "unknown shift",
152 .insns = {
153 LOAD_UNKNOWN(BPF_REG_3),
154 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
155 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
156 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
157 BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
158 LOAD_UNKNOWN(BPF_REG_4),
159 BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5),
160 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
161 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
162 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
163 BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
164 BPF_MOV64_IMM(BPF_REG_0, 0),
165 BPF_EXIT_INSN(),
166 },
167 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
168 .matches = {
169 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
170 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp",
171 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp",
172 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp",
173 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp",
174 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp",
175 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp",
176 "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp",
177 "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp",
178 "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp",
179 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp",
180 },
181 },
182 {
183 .descr = "unknown mul",
184 .insns = {
185 LOAD_UNKNOWN(BPF_REG_3),
186 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
187 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1),
188 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
189 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
190 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
191 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4),
192 BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
193 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8),
194 BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
195 BPF_MOV64_IMM(BPF_REG_0, 0),
196 BPF_EXIT_INSN(),
197 },
198 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
199 .matches = {
200 "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
201 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
202 "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp",
203 "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
204 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp",
205 "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
206 "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp",
207 "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
208 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp",
209 "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp"
210 },
211 },
212 {
213 .descr = "packet const offset",
214 .insns = {
215 PREP_PKT_POINTERS,
216 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
217
218 BPF_MOV64_IMM(BPF_REG_0, 0),
219
220 /* Skip over ethernet header. */
221 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
222 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
223 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
224 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
225 BPF_EXIT_INSN(),
226
227 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0),
228 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1),
229 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2),
230 BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3),
231 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0),
232 BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2),
233 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
234
235 BPF_MOV64_IMM(BPF_REG_0, 0),
236 BPF_EXIT_INSN(),
237 },
238 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
239 .matches = {
240 "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp",
241 "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp",
242 "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp",
243 "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp",
244 "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
245 "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
246 },
247 },
248 {
249 .descr = "packet variable offset",
250 .insns = {
251 LOAD_UNKNOWN(BPF_REG_6),
252 BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
253
254 /* First, add a constant to the R5 packet pointer,
255 * then a variable with a known alignment.
256 */
257 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
258 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
259 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
260 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
261 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
262 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
263 BPF_EXIT_INSN(),
264 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
265
266 /* Now, test in the other direction. Adding first
267 * the variable offset to R5, then the constant.
268 */
269 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
270 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
271 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
272 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
273 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
274 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
275 BPF_EXIT_INSN(),
276 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
277
6832a333
DM
278 /* Test multiple accumulations of unknown values
279 * into a packet pointer.
280 */
281 BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
282 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
283 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
284 BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4),
285 BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
286 BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
287 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
288 BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
289 BPF_EXIT_INSN(),
290 BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
291
18b3ad90
DM
292 BPF_MOV64_IMM(BPF_REG_0, 0),
293 BPF_EXIT_INSN(),
294 },
295 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
296 .matches = {
297 /* Calculated offset in R6 has unknown value, but known
298 * alignment of 4.
299 */
300 "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp",
301
302 /* Offset is added to packet pointer R5, resulting in known
303 * auxiliary alignment and offset.
304 */
305 "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
306
307 /* At the time the word size load is performed from R5,
308 * it's total offset is NET_IP_ALIGN + reg->off (0) +
309 * reg->aux_off (14) which is 16. Then the variable
310 * offset is considered using reg->aux_off_align which
311 * is 4 and meets the load's requirements.
312 */
313 "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
314
315
316 /* Variable offset is added to R5 packet pointer,
317 * resulting in auxiliary alignment of 4.
318 */
319 "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
320
321 /* Constant offset is added to R5, resulting in
322 * reg->off of 14.
323 */
324 "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
325
326 /* At the time the word size load is performed from R5,
327 * it's total offset is NET_IP_ALIGN + reg->off (14) which
328 * is 16. Then the variable offset is considered using
329 * reg->aux_off_align which is 4 and meets the load's
330 * requirements.
331 */
332 "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
6832a333
DM
333
334 /* Constant offset is added to R5 packet pointer,
335 * resulting in reg->off value of 14.
336 */
337 "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp",
338 /* Variable offset is added to R5, resulting in an
339 * auxiliary offset of 14, and an auxiliary alignment of 4.
340 */
341 "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
342 /* Constant is added to R5 again, setting reg->off to 4. */
343 "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
344 /* And once more we add a variable, which causes an accumulation
345 * of reg->off into reg->aux_off_align, with resulting value of
346 * 18. The auxiliary alignment stays at 4.
347 */
348 "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
349 /* At the time the word size load is performed from R5,
350 * it's total offset is NET_IP_ALIGN + reg->off (0) +
351 * reg->aux_off (18) which is 20. Then the variable offset
352 * is considered using reg->aux_off_align which is 4 and meets
353 * the load's requirements.
354 */
355 "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
18b3ad90
DM
356 },
357 },
358};
359
360static int probe_filter_length(const struct bpf_insn *fp)
361{
362 int len;
363
364 for (len = MAX_INSNS - 1; len > 0; --len)
365 if (fp[len].code != 0 || fp[len].imm != 0)
366 break;
367 return len + 1;
368}
369
370static char bpf_vlog[32768];
371
372static int do_test_single(struct bpf_align_test *test)
373{
374 struct bpf_insn *prog = test->insns;
375 int prog_type = test->prog_type;
376 int prog_len, i;
377 int fd_prog;
378 int ret;
379
380 prog_len = probe_filter_length(prog);
381 fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
382 prog, prog_len, 1, "GPL", 0,
d6554904 383 bpf_vlog, sizeof(bpf_vlog), 2);
18b3ad90
DM
384 if (fd_prog < 0) {
385 printf("Failed to load program.\n");
386 printf("%s", bpf_vlog);
387 ret = 1;
388 } else {
389 ret = 0;
390 for (i = 0; i < MAX_MATCHES; i++) {
391 const char *t, *m = test->matches[i];
392
393 if (!m)
394 break;
395 t = strstr(bpf_vlog, m);
396 if (!t) {
397 printf("Failed to find match: %s\n", m);
398 ret = 1;
399 printf("%s", bpf_vlog);
400 break;
401 }
402 }
18b3ad90
DM
403 close(fd_prog);
404 }
405 return ret;
406}
407
408static int do_test(unsigned int from, unsigned int to)
409{
410 int all_pass = 0;
411 int all_fail = 0;
412 unsigned int i;
413
414 for (i = from; i < to; i++) {
415 struct bpf_align_test *test = &tests[i];
416 int fail;
417
418 printf("Test %3d: %s ... ",
419 i, test->descr);
420 fail = do_test_single(test);
421 if (fail) {
422 all_fail++;
423 printf("FAIL\n");
424 } else {
425 all_pass++;
426 printf("PASS\n");
427 }
428 }
429 printf("Results: %d pass %d fail\n",
430 all_pass, all_fail);
efe5f9c0 431 return all_fail ? EXIT_FAILURE : EXIT_SUCCESS;
18b3ad90
DM
432}
433
434int main(int argc, char **argv)
435{
436 unsigned int from = 0, to = ARRAY_SIZE(tests);
f735b649
DB
437 struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
438
439 setrlimit(RLIMIT_MEMLOCK, &rinf);
18b3ad90
DM
440
441 if (argc == 3) {
442 unsigned int l = atoi(argv[argc - 2]);
443 unsigned int u = atoi(argv[argc - 1]);
444
445 if (l < to && u < to) {
446 from = l;
447 to = u + 1;
448 }
449 } else if (argc == 2) {
450 unsigned int t = atoi(argv[argc - 1]);
451
452 if (t < to) {
453 from = t;
454 to = t + 1;
455 }
456 }
457 return do_test(from, to);
458}