1
2
3
4#include <fcntl.h>
5#include <stdint.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10
11#include <linux/filter.h>
12
13#include <bpf/bpf.h>
14#include <bpf/libbpf.h>
15
16#include <bpf/bpf_endian.h>
17#include "bpf_rlimit.h"
18#include "bpf_util.h"
19#include "cgroup_helpers.h"
20
21#define CG_PATH "/foo"
22#define MAX_INSNS 512
23#define FIXUP_SYSCTL_VALUE 0
24
25char bpf_log_buf[BPF_LOG_BUF_SIZE];
26
27struct sysctl_test {
28 const char *descr;
29 size_t fixup_value_insn;
30 struct bpf_insn insns[MAX_INSNS];
31 const char *prog_file;
32 enum bpf_attach_type attach_type;
33 const char *sysctl;
34 int open_flags;
35 int seek;
36 const char *newval;
37 const char *oldval;
38 enum {
39 LOAD_REJECT,
40 ATTACH_REJECT,
41 OP_EPERM,
42 SUCCESS,
43 } result;
44};
45
46static struct sysctl_test tests[] = {
47 {
48 .descr = "sysctl wrong attach_type",
49 .insns = {
50 BPF_MOV64_IMM(BPF_REG_0, 1),
51 BPF_EXIT_INSN(),
52 },
53 .attach_type = 0,
54 .sysctl = "kernel/ostype",
55 .open_flags = O_RDONLY,
56 .result = ATTACH_REJECT,
57 },
58 {
59 .descr = "sysctl:read allow all",
60 .insns = {
61 BPF_MOV64_IMM(BPF_REG_0, 1),
62 BPF_EXIT_INSN(),
63 },
64 .attach_type = BPF_CGROUP_SYSCTL,
65 .sysctl = "kernel/ostype",
66 .open_flags = O_RDONLY,
67 .result = SUCCESS,
68 },
69 {
70 .descr = "sysctl:read deny all",
71 .insns = {
72 BPF_MOV64_IMM(BPF_REG_0, 0),
73 BPF_EXIT_INSN(),
74 },
75 .attach_type = BPF_CGROUP_SYSCTL,
76 .sysctl = "kernel/ostype",
77 .open_flags = O_RDONLY,
78 .result = OP_EPERM,
79 },
80 {
81 .descr = "ctx:write sysctl:read read ok",
82 .insns = {
83
84 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
85 offsetof(struct bpf_sysctl, write)),
86 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2),
87
88
89 BPF_MOV64_IMM(BPF_REG_0, 0),
90 BPF_JMP_A(1),
91
92
93 BPF_MOV64_IMM(BPF_REG_0, 1),
94 BPF_EXIT_INSN(),
95 },
96 .attach_type = BPF_CGROUP_SYSCTL,
97 .sysctl = "kernel/ostype",
98 .open_flags = O_RDONLY,
99 .result = SUCCESS,
100 },
101 {
102 .descr = "ctx:write sysctl:write read ok",
103 .insns = {
104
105 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
106 offsetof(struct bpf_sysctl, write)),
107 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2),
108
109
110 BPF_MOV64_IMM(BPF_REG_0, 0),
111 BPF_JMP_A(1),
112
113
114 BPF_MOV64_IMM(BPF_REG_0, 1),
115 BPF_EXIT_INSN(),
116 },
117 .attach_type = BPF_CGROUP_SYSCTL,
118 .sysctl = "kernel/domainname",
119 .open_flags = O_WRONLY,
120 .newval = "(none)",
121 .result = OP_EPERM,
122 },
123 {
124 .descr = "ctx:write sysctl:write read ok narrow",
125 .insns = {
126
127#if __BYTE_ORDER == __LITTLE_ENDIAN
128 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1,
129 offsetof(struct bpf_sysctl, write)),
130#else
131 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1,
132 offsetof(struct bpf_sysctl, write) + 2),
133#endif
134 BPF_ALU64_IMM(BPF_AND, BPF_REG_7, 1),
135
136 BPF_MOV64_IMM(BPF_REG_0, 1),
137 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_7),
138 BPF_EXIT_INSN(),
139 },
140 .attach_type = BPF_CGROUP_SYSCTL,
141 .sysctl = "kernel/domainname",
142 .open_flags = O_WRONLY,
143 .newval = "(none)",
144 .result = OP_EPERM,
145 },
146 {
147 .descr = "ctx:write sysctl:read write reject",
148 .insns = {
149
150 BPF_MOV64_IMM(BPF_REG_0, 0),
151 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
152 offsetof(struct bpf_sysctl, write)),
153 BPF_MOV64_IMM(BPF_REG_0, 1),
154 BPF_EXIT_INSN(),
155 },
156 .attach_type = BPF_CGROUP_SYSCTL,
157 .sysctl = "kernel/ostype",
158 .open_flags = O_RDONLY,
159 .result = LOAD_REJECT,
160 },
161 {
162 .descr = "ctx:file_pos sysctl:read read ok",
163 .insns = {
164
165 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
166 offsetof(struct bpf_sysctl, file_pos)),
167 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 3, 2),
168
169
170 BPF_MOV64_IMM(BPF_REG_0, 1),
171 BPF_JMP_A(1),
172
173
174 BPF_MOV64_IMM(BPF_REG_0, 0),
175 BPF_EXIT_INSN(),
176 },
177 .attach_type = BPF_CGROUP_SYSCTL,
178 .sysctl = "kernel/ostype",
179 .open_flags = O_RDONLY,
180 .seek = 3,
181 .result = SUCCESS,
182 },
183 {
184 .descr = "ctx:file_pos sysctl:read read ok narrow",
185 .insns = {
186
187#if __BYTE_ORDER == __LITTLE_ENDIAN
188 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
189 offsetof(struct bpf_sysctl, file_pos)),
190#else
191 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
192 offsetof(struct bpf_sysctl, file_pos) + 3),
193#endif
194 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2),
195
196
197 BPF_MOV64_IMM(BPF_REG_0, 1),
198 BPF_JMP_A(1),
199
200
201 BPF_MOV64_IMM(BPF_REG_0, 0),
202 BPF_EXIT_INSN(),
203 },
204 .attach_type = BPF_CGROUP_SYSCTL,
205 .sysctl = "kernel/ostype",
206 .open_flags = O_RDONLY,
207 .seek = 4,
208 .result = SUCCESS,
209 },
210 {
211 .descr = "ctx:file_pos sysctl:read write ok",
212 .insns = {
213
214 BPF_MOV64_IMM(BPF_REG_0, 2),
215 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
216 offsetof(struct bpf_sysctl, file_pos)),
217 BPF_MOV64_IMM(BPF_REG_0, 1),
218 BPF_EXIT_INSN(),
219 },
220 .attach_type = BPF_CGROUP_SYSCTL,
221 .sysctl = "kernel/ostype",
222 .open_flags = O_RDONLY,
223 .oldval = "nux\n",
224 .result = SUCCESS,
225 },
226 {
227 .descr = "sysctl_get_name sysctl_value:base ok",
228 .insns = {
229
230 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
231 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
232 BPF_MOV64_IMM(BPF_REG_0, 0),
233 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
234
235 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
236
237
238 BPF_MOV64_IMM(BPF_REG_3, 8),
239
240
241 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
242
243
244 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
245
246
247 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6),
248
249 BPF_LD_IMM64(BPF_REG_8,
250 bpf_be64_to_cpu(0x7463705f6d656d00ULL)),
251 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
252 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
253
254
255 BPF_MOV64_IMM(BPF_REG_0, 1),
256 BPF_JMP_A(1),
257
258
259 BPF_MOV64_IMM(BPF_REG_0, 0),
260 BPF_EXIT_INSN(),
261 },
262 .attach_type = BPF_CGROUP_SYSCTL,
263 .sysctl = "net/ipv4/tcp_mem",
264 .open_flags = O_RDONLY,
265 .result = SUCCESS,
266 },
267 {
268 .descr = "sysctl_get_name sysctl_value:base E2BIG truncated",
269 .insns = {
270
271 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
272 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
273 BPF_MOV64_IMM(BPF_REG_0, 0),
274 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
275
276 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
277
278
279 BPF_MOV64_IMM(BPF_REG_3, 7),
280
281
282 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
283
284
285 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
286
287
288 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
289
290
291 BPF_LD_IMM64(BPF_REG_8,
292 bpf_be64_to_cpu(0x7463705f6d650000ULL)),
293 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
294 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
295
296
297 BPF_MOV64_IMM(BPF_REG_0, 1),
298 BPF_JMP_A(1),
299
300
301 BPF_MOV64_IMM(BPF_REG_0, 0),
302 BPF_EXIT_INSN(),
303 },
304 .attach_type = BPF_CGROUP_SYSCTL,
305 .sysctl = "net/ipv4/tcp_mem",
306 .open_flags = O_RDONLY,
307 .result = SUCCESS,
308 },
309 {
310 .descr = "sysctl_get_name sysctl:full ok",
311 .insns = {
312
313 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
314 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
315 BPF_MOV64_IMM(BPF_REG_0, 0),
316 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
317 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
318 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16),
319
320 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
321
322
323 BPF_MOV64_IMM(BPF_REG_3, 17),
324
325
326 BPF_MOV64_IMM(BPF_REG_4, 0),
327
328
329 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
330
331
332 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14),
333
334
335 BPF_LD_IMM64(BPF_REG_8,
336 bpf_be64_to_cpu(0x6e65742f69707634ULL)),
337 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
338 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10),
339
340
341 BPF_LD_IMM64(BPF_REG_8,
342 bpf_be64_to_cpu(0x2f7463705f6d656dULL)),
343 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
344 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
345
346
347 BPF_LD_IMM64(BPF_REG_8, 0x0ULL),
348 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16),
349 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
350
351
352 BPF_MOV64_IMM(BPF_REG_0, 1),
353 BPF_JMP_A(1),
354
355
356 BPF_MOV64_IMM(BPF_REG_0, 0),
357 BPF_EXIT_INSN(),
358 },
359 .attach_type = BPF_CGROUP_SYSCTL,
360 .sysctl = "net/ipv4/tcp_mem",
361 .open_flags = O_RDONLY,
362 .result = SUCCESS,
363 },
364 {
365 .descr = "sysctl_get_name sysctl:full E2BIG truncated",
366 .insns = {
367
368 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
369 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
370 BPF_MOV64_IMM(BPF_REG_0, 0),
371 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
372 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
373
374 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
375
376
377 BPF_MOV64_IMM(BPF_REG_3, 16),
378
379
380 BPF_MOV64_IMM(BPF_REG_4, 0),
381
382
383 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
384
385
386 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10),
387
388
389 BPF_LD_IMM64(BPF_REG_8,
390 bpf_be64_to_cpu(0x6e65742f69707634ULL)),
391 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
392 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
393
394
395 BPF_LD_IMM64(BPF_REG_8,
396 bpf_be64_to_cpu(0x2f7463705f6d6500ULL)),
397 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
398 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
399
400
401 BPF_MOV64_IMM(BPF_REG_0, 1),
402 BPF_JMP_A(1),
403
404
405 BPF_MOV64_IMM(BPF_REG_0, 0),
406 BPF_EXIT_INSN(),
407 },
408 .attach_type = BPF_CGROUP_SYSCTL,
409 .sysctl = "net/ipv4/tcp_mem",
410 .open_flags = O_RDONLY,
411 .result = SUCCESS,
412 },
413 {
414 .descr = "sysctl_get_name sysctl:full E2BIG truncated small",
415 .insns = {
416
417 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
418 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
419 BPF_MOV64_IMM(BPF_REG_0, 0),
420 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
421
422 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
423
424
425 BPF_MOV64_IMM(BPF_REG_3, 7),
426
427
428 BPF_MOV64_IMM(BPF_REG_4, 0),
429
430
431 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
432
433
434 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
435
436
437 BPF_LD_IMM64(BPF_REG_8,
438 bpf_be64_to_cpu(0x6e65742f69700000ULL)),
439 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
440 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
441
442
443 BPF_MOV64_IMM(BPF_REG_0, 1),
444 BPF_JMP_A(1),
445
446
447 BPF_MOV64_IMM(BPF_REG_0, 0),
448 BPF_EXIT_INSN(),
449 },
450 .attach_type = BPF_CGROUP_SYSCTL,
451 .sysctl = "net/ipv4/tcp_mem",
452 .open_flags = O_RDONLY,
453 .result = SUCCESS,
454 },
455 {
456 .descr = "sysctl_get_current_value sysctl:read ok, gt",
457 .insns = {
458
459 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
460 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
461 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
462
463
464 BPF_MOV64_IMM(BPF_REG_3, 8),
465
466
467 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
468
469
470 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
471
472
473 BPF_LD_IMM64(BPF_REG_8,
474 bpf_be64_to_cpu(0x4c696e75780a0000ULL)),
475 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
476 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
477
478
479 BPF_MOV64_IMM(BPF_REG_0, 1),
480 BPF_JMP_A(1),
481
482
483 BPF_MOV64_IMM(BPF_REG_0, 0),
484 BPF_EXIT_INSN(),
485 },
486 .attach_type = BPF_CGROUP_SYSCTL,
487 .sysctl = "kernel/ostype",
488 .open_flags = O_RDONLY,
489 .result = SUCCESS,
490 },
491 {
492 .descr = "sysctl_get_current_value sysctl:read ok, eq",
493 .insns = {
494
495 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
496 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
497 BPF_MOV64_IMM(BPF_REG_0, 0),
498 BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 7),
499
500 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
501
502
503 BPF_MOV64_IMM(BPF_REG_3, 7),
504
505
506 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
507
508
509 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
510
511
512 BPF_LD_IMM64(BPF_REG_8,
513 bpf_be64_to_cpu(0x4c696e75780a0000ULL)),
514 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
515 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
516
517
518 BPF_MOV64_IMM(BPF_REG_0, 1),
519 BPF_JMP_A(1),
520
521
522 BPF_MOV64_IMM(BPF_REG_0, 0),
523 BPF_EXIT_INSN(),
524 },
525 .attach_type = BPF_CGROUP_SYSCTL,
526 .sysctl = "kernel/ostype",
527 .open_flags = O_RDONLY,
528 .result = SUCCESS,
529 },
530 {
531 .descr = "sysctl_get_current_value sysctl:read E2BIG truncated",
532 .insns = {
533
534 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
535 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
536 BPF_MOV64_IMM(BPF_REG_0, 0),
537 BPF_STX_MEM(BPF_H, BPF_REG_7, BPF_REG_0, 6),
538
539 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
540
541
542 BPF_MOV64_IMM(BPF_REG_3, 6),
543
544
545 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
546
547
548 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
549
550
551 BPF_LD_IMM64(BPF_REG_8,
552 bpf_be64_to_cpu(0x4c696e7578000000ULL)),
553 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
554 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
555
556
557 BPF_MOV64_IMM(BPF_REG_0, 1),
558 BPF_JMP_A(1),
559
560
561 BPF_MOV64_IMM(BPF_REG_0, 0),
562 BPF_EXIT_INSN(),
563 },
564 .attach_type = BPF_CGROUP_SYSCTL,
565 .sysctl = "kernel/ostype",
566 .open_flags = O_RDONLY,
567 .result = SUCCESS,
568 },
569 {
570 .descr = "sysctl_get_current_value sysctl:read EINVAL",
571 .insns = {
572
573 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
574 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
575
576 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
577
578
579 BPF_MOV64_IMM(BPF_REG_3, 8),
580
581
582 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
583
584
585 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4),
586
587
588 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
589 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2),
590
591
592 BPF_MOV64_IMM(BPF_REG_0, 0),
593 BPF_JMP_A(1),
594
595
596 BPF_MOV64_IMM(BPF_REG_0, 1),
597 BPF_EXIT_INSN(),
598 },
599 .attach_type = BPF_CGROUP_SYSCTL,
600 .sysctl = "net/ipv6/conf/lo/stable_secret",
601 .open_flags = O_RDONLY,
602 .result = OP_EPERM,
603 },
604 {
605 .descr = "sysctl_get_current_value sysctl:write ok",
606 .fixup_value_insn = 6,
607 .insns = {
608
609 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
610 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
611
612 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
613
614
615 BPF_MOV64_IMM(BPF_REG_3, 8),
616
617
618 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
619
620
621 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6),
622
623
624 BPF_LD_IMM64(BPF_REG_8, FIXUP_SYSCTL_VALUE),
625 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
626 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
627
628
629 BPF_MOV64_IMM(BPF_REG_0, 0),
630 BPF_JMP_A(1),
631
632
633 BPF_MOV64_IMM(BPF_REG_0, 1),
634 BPF_EXIT_INSN(),
635 },
636 .attach_type = BPF_CGROUP_SYSCTL,
637 .sysctl = "net/ipv4/route/mtu_expires",
638 .open_flags = O_WRONLY,
639 .newval = "600",
640 .result = OP_EPERM,
641 },
642 {
643 .descr = "sysctl_get_new_value sysctl:read EINVAL",
644 .insns = {
645
646 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
647 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
648 BPF_MOV64_IMM(BPF_REG_0, 0),
649 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
650
651 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
652
653
654 BPF_MOV64_IMM(BPF_REG_3, 8),
655
656
657 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
658
659
660 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
661
662
663 BPF_MOV64_IMM(BPF_REG_0, 1),
664 BPF_JMP_A(1),
665
666
667 BPF_MOV64_IMM(BPF_REG_0, 0),
668 BPF_EXIT_INSN(),
669 },
670 .attach_type = BPF_CGROUP_SYSCTL,
671 .sysctl = "net/ipv4/tcp_mem",
672 .open_flags = O_RDONLY,
673 .result = SUCCESS,
674 },
675 {
676 .descr = "sysctl_get_new_value sysctl:write ok",
677 .insns = {
678
679 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
680 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
681
682 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
683
684
685 BPF_MOV64_IMM(BPF_REG_3, 4),
686
687
688 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
689
690
691 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
692
693
694 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
695 BPF_JMP_IMM(BPF_JNE, BPF_REG_9,
696 bpf_ntohl(0x36303600), 2),
697
698
699 BPF_MOV64_IMM(BPF_REG_0, 0),
700 BPF_JMP_A(1),
701
702
703 BPF_MOV64_IMM(BPF_REG_0, 1),
704 BPF_EXIT_INSN(),
705 },
706 .attach_type = BPF_CGROUP_SYSCTL,
707 .sysctl = "net/ipv4/route/mtu_expires",
708 .open_flags = O_WRONLY,
709 .newval = "606",
710 .result = OP_EPERM,
711 },
712 {
713 .descr = "sysctl_get_new_value sysctl:write ok long",
714 .insns = {
715
716 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
717 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
718
719 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
720
721
722 BPF_MOV64_IMM(BPF_REG_3, 24),
723
724
725 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
726
727
728 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14),
729
730
731 BPF_LD_IMM64(BPF_REG_8,
732 bpf_be64_to_cpu(0x3330303030303020ULL)),
733 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
734 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10),
735
736
737 BPF_LD_IMM64(BPF_REG_8,
738 bpf_be64_to_cpu(0x3430303030303020ULL)),
739 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
740 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
741
742
743 BPF_LD_IMM64(BPF_REG_8,
744 bpf_be64_to_cpu(0x3630303030303000ULL)),
745 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16),
746 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
747
748
749 BPF_MOV64_IMM(BPF_REG_0, 0),
750 BPF_JMP_A(1),
751
752
753 BPF_MOV64_IMM(BPF_REG_0, 1),
754 BPF_EXIT_INSN(),
755 },
756 .attach_type = BPF_CGROUP_SYSCTL,
757 .sysctl = "net/ipv4/tcp_mem",
758 .open_flags = O_WRONLY,
759 .newval = "3000000 4000000 6000000",
760 .result = OP_EPERM,
761 },
762 {
763 .descr = "sysctl_get_new_value sysctl:write E2BIG",
764 .insns = {
765
766 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
767 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
768 BPF_MOV64_IMM(BPF_REG_0, 0),
769 BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 3),
770
771 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
772
773
774 BPF_MOV64_IMM(BPF_REG_3, 3),
775
776
777 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
778
779
780 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4),
781
782
783 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
784 BPF_JMP_IMM(BPF_JNE, BPF_REG_9,
785 bpf_ntohl(0x36300000), 2),
786
787
788 BPF_MOV64_IMM(BPF_REG_0, 0),
789 BPF_JMP_A(1),
790
791
792 BPF_MOV64_IMM(BPF_REG_0, 1),
793 BPF_EXIT_INSN(),
794 },
795 .attach_type = BPF_CGROUP_SYSCTL,
796 .sysctl = "net/ipv4/route/mtu_expires",
797 .open_flags = O_WRONLY,
798 .newval = "606",
799 .result = OP_EPERM,
800 },
801 {
802 .descr = "sysctl_set_new_value sysctl:read EINVAL",
803 .insns = {
804
805 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
806 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
807 BPF_MOV64_IMM(BPF_REG_0,
808 bpf_ntohl(0x36303000)),
809 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
810
811 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
812
813
814 BPF_MOV64_IMM(BPF_REG_3, 3),
815
816
817 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
818
819
820 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
821
822
823 BPF_MOV64_IMM(BPF_REG_0, 1),
824 BPF_JMP_A(1),
825
826
827 BPF_MOV64_IMM(BPF_REG_0, 0),
828 BPF_EXIT_INSN(),
829 },
830 .attach_type = BPF_CGROUP_SYSCTL,
831 .sysctl = "net/ipv4/route/mtu_expires",
832 .open_flags = O_RDONLY,
833 .result = SUCCESS,
834 },
835 {
836 .descr = "sysctl_set_new_value sysctl:write ok",
837 .fixup_value_insn = 2,
838 .insns = {
839
840 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
841 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
842 BPF_LD_IMM64(BPF_REG_0, FIXUP_SYSCTL_VALUE),
843 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
844
845 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
846
847
848 BPF_MOV64_IMM(BPF_REG_3, 3),
849
850
851 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
852
853
854 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
855
856
857 BPF_MOV64_IMM(BPF_REG_0, 1),
858 BPF_JMP_A(1),
859
860
861 BPF_MOV64_IMM(BPF_REG_0, 0),
862 BPF_EXIT_INSN(),
863 },
864 .attach_type = BPF_CGROUP_SYSCTL,
865 .sysctl = "net/ipv4/route/mtu_expires",
866 .open_flags = O_WRONLY,
867 .newval = "606",
868 .result = SUCCESS,
869 },
870 {
871 "bpf_strtoul one number string",
872 .insns = {
873
874 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
875 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
876 BPF_MOV64_IMM(BPF_REG_0,
877 bpf_ntohl(0x36303000)),
878 BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
879
880 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
881
882
883 BPF_MOV64_IMM(BPF_REG_2, 4),
884
885
886 BPF_MOV64_IMM(BPF_REG_3, 0),
887
888
889 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
890 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
891 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
892
893 BPF_EMIT_CALL(BPF_FUNC_strtoul),
894
895
896 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
897
898 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
899 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 2),
900
901
902 BPF_MOV64_IMM(BPF_REG_0, 1),
903 BPF_JMP_A(1),
904
905
906 BPF_MOV64_IMM(BPF_REG_0, 0),
907 BPF_EXIT_INSN(),
908 },
909 .attach_type = BPF_CGROUP_SYSCTL,
910 .sysctl = "net/ipv4/route/mtu_expires",
911 .open_flags = O_RDONLY,
912 .result = SUCCESS,
913 },
914 {
915 "bpf_strtoul multi number string",
916 .insns = {
917
918 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
919 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
920
921 BPF_LD_IMM64(BPF_REG_0,
922 bpf_be64_to_cpu(0x3630302036303200ULL)),
923 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
924 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
925
926
927 BPF_MOV64_IMM(BPF_REG_2, 8),
928
929
930 BPF_MOV64_IMM(BPF_REG_3, 0),
931
932
933 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
934 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
935 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
936
937 BPF_EMIT_CALL(BPF_FUNC_strtoul),
938
939
940 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18),
941
942 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
943 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 16),
944
945
946 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
947 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
948 BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0),
949 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
950
951
952 BPF_MOV64_IMM(BPF_REG_2, 8),
953 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0),
954
955
956 BPF_MOV64_IMM(BPF_REG_3, 0),
957
958
959 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
960 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
961 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
962
963 BPF_EMIT_CALL(BPF_FUNC_strtoul),
964
965
966 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
967
968 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
969 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 602, 2),
970
971
972 BPF_MOV64_IMM(BPF_REG_0, 1),
973 BPF_JMP_A(1),
974
975
976 BPF_MOV64_IMM(BPF_REG_0, 0),
977 BPF_EXIT_INSN(),
978 },
979 .attach_type = BPF_CGROUP_SYSCTL,
980 .sysctl = "net/ipv4/tcp_mem",
981 .open_flags = O_RDONLY,
982 .result = SUCCESS,
983 },
984 {
985 "bpf_strtoul buf_len = 0, reject",
986 .insns = {
987
988 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
989 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
990 BPF_MOV64_IMM(BPF_REG_0,
991 bpf_ntohl(0x36303000)),
992 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
993
994 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
995
996
997 BPF_MOV64_IMM(BPF_REG_2, 0),
998
999
1000 BPF_MOV64_IMM(BPF_REG_3, 0),
1001
1002
1003 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1004 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1005 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1006
1007 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1008
1009 BPF_MOV64_IMM(BPF_REG_0, 1),
1010 BPF_EXIT_INSN(),
1011 },
1012 .attach_type = BPF_CGROUP_SYSCTL,
1013 .sysctl = "net/ipv4/route/mtu_expires",
1014 .open_flags = O_RDONLY,
1015 .result = LOAD_REJECT,
1016 },
1017 {
1018 "bpf_strtoul supported base, ok",
1019 .insns = {
1020
1021 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1022 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1023 BPF_MOV64_IMM(BPF_REG_0,
1024 bpf_ntohl(0x30373700)),
1025 BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1026
1027 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1028
1029
1030 BPF_MOV64_IMM(BPF_REG_2, 4),
1031
1032
1033 BPF_MOV64_IMM(BPF_REG_3, 8),
1034
1035
1036 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1037 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1038 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1039
1040 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1041
1042
1043 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1044
1045 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1046 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 63, 2),
1047
1048
1049 BPF_MOV64_IMM(BPF_REG_0, 1),
1050 BPF_JMP_A(1),
1051
1052
1053 BPF_MOV64_IMM(BPF_REG_0, 0),
1054 BPF_EXIT_INSN(),
1055 },
1056 .attach_type = BPF_CGROUP_SYSCTL,
1057 .sysctl = "net/ipv4/route/mtu_expires",
1058 .open_flags = O_RDONLY,
1059 .result = SUCCESS,
1060 },
1061 {
1062 "bpf_strtoul unsupported base, EINVAL",
1063 .insns = {
1064
1065 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1066 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1067 BPF_MOV64_IMM(BPF_REG_0,
1068 bpf_ntohl(0x36303000)),
1069 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1070
1071 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1072
1073
1074 BPF_MOV64_IMM(BPF_REG_2, 4),
1075
1076
1077 BPF_MOV64_IMM(BPF_REG_3, 3),
1078
1079
1080 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1081 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1082 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1083
1084 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1085
1086
1087 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1088
1089
1090 BPF_MOV64_IMM(BPF_REG_0, 1),
1091 BPF_JMP_A(1),
1092
1093
1094 BPF_MOV64_IMM(BPF_REG_0, 0),
1095 BPF_EXIT_INSN(),
1096 },
1097 .attach_type = BPF_CGROUP_SYSCTL,
1098 .sysctl = "net/ipv4/route/mtu_expires",
1099 .open_flags = O_RDONLY,
1100 .result = SUCCESS,
1101 },
1102 {
1103 "bpf_strtoul buf with spaces only, EINVAL",
1104 .insns = {
1105
1106 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1107 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1108 BPF_MOV64_IMM(BPF_REG_0,
1109 bpf_ntohl(0x0d0c0a09)),
1110 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1111
1112 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1113
1114
1115 BPF_MOV64_IMM(BPF_REG_2, 4),
1116
1117
1118 BPF_MOV64_IMM(BPF_REG_3, 0),
1119
1120
1121 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1122 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1123 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1124
1125 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1126
1127
1128 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1129
1130
1131 BPF_MOV64_IMM(BPF_REG_0, 1),
1132 BPF_JMP_A(1),
1133
1134
1135 BPF_MOV64_IMM(BPF_REG_0, 0),
1136 BPF_EXIT_INSN(),
1137 },
1138 .attach_type = BPF_CGROUP_SYSCTL,
1139 .sysctl = "net/ipv4/route/mtu_expires",
1140 .open_flags = O_RDONLY,
1141 .result = SUCCESS,
1142 },
1143 {
1144 "bpf_strtoul negative number, EINVAL",
1145 .insns = {
1146
1147 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1148 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1149
1150 BPF_MOV64_IMM(BPF_REG_0,
1151 bpf_ntohl(0x0a2d3600)),
1152 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1153
1154 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1155
1156
1157 BPF_MOV64_IMM(BPF_REG_2, 4),
1158
1159
1160 BPF_MOV64_IMM(BPF_REG_3, 0),
1161
1162
1163 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1164 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1165 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1166
1167 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1168
1169
1170 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1171
1172
1173 BPF_MOV64_IMM(BPF_REG_0, 1),
1174 BPF_JMP_A(1),
1175
1176
1177 BPF_MOV64_IMM(BPF_REG_0, 0),
1178 BPF_EXIT_INSN(),
1179 },
1180 .attach_type = BPF_CGROUP_SYSCTL,
1181 .sysctl = "net/ipv4/route/mtu_expires",
1182 .open_flags = O_RDONLY,
1183 .result = SUCCESS,
1184 },
1185 {
1186 "bpf_strtol negative number, ok",
1187 .insns = {
1188
1189 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1190 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1191
1192 BPF_MOV64_IMM(BPF_REG_0,
1193 bpf_ntohl(0x0a2d3600)),
1194 BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1195
1196 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1197
1198
1199 BPF_MOV64_IMM(BPF_REG_2, 4),
1200
1201
1202 BPF_MOV64_IMM(BPF_REG_3, 10),
1203
1204
1205 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1206 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1207 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1208
1209 BPF_EMIT_CALL(BPF_FUNC_strtol),
1210
1211
1212 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1213
1214 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1215 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -6, 2),
1216
1217
1218 BPF_MOV64_IMM(BPF_REG_0, 1),
1219 BPF_JMP_A(1),
1220
1221
1222 BPF_MOV64_IMM(BPF_REG_0, 0),
1223 BPF_EXIT_INSN(),
1224 },
1225 .attach_type = BPF_CGROUP_SYSCTL,
1226 .sysctl = "net/ipv4/route/mtu_expires",
1227 .open_flags = O_RDONLY,
1228 .result = SUCCESS,
1229 },
1230 {
1231 "bpf_strtol hex number, ok",
1232 .insns = {
1233
1234 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1235 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1236
1237 BPF_MOV64_IMM(BPF_REG_0,
1238 bpf_ntohl(0x30786665)),
1239 BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1240
1241 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1242
1243
1244 BPF_MOV64_IMM(BPF_REG_2, 4),
1245
1246
1247 BPF_MOV64_IMM(BPF_REG_3, 0),
1248
1249
1250 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1251 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1252 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1253
1254 BPF_EMIT_CALL(BPF_FUNC_strtol),
1255
1256
1257 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
1258
1259 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1260 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 254, 2),
1261
1262
1263 BPF_MOV64_IMM(BPF_REG_0, 1),
1264 BPF_JMP_A(1),
1265
1266
1267 BPF_MOV64_IMM(BPF_REG_0, 0),
1268 BPF_EXIT_INSN(),
1269 },
1270 .attach_type = BPF_CGROUP_SYSCTL,
1271 .sysctl = "net/ipv4/route/mtu_expires",
1272 .open_flags = O_RDONLY,
1273 .result = SUCCESS,
1274 },
1275 {
1276 "bpf_strtol max long",
1277 .insns = {
1278
1279 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1280 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
1281 BPF_LD_IMM64(BPF_REG_0,
1282 bpf_be64_to_cpu(0x3932323333373230ULL)),
1283 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1284 BPF_LD_IMM64(BPF_REG_0,
1285 bpf_be64_to_cpu(0x3336383534373735ULL)),
1286 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
1287 BPF_LD_IMM64(BPF_REG_0,
1288 bpf_be64_to_cpu(0x3830370000000000ULL)),
1289 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16),
1290
1291 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1292
1293
1294 BPF_MOV64_IMM(BPF_REG_2, 19),
1295
1296
1297 BPF_MOV64_IMM(BPF_REG_3, 0),
1298
1299
1300 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1301 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1302 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1303
1304 BPF_EMIT_CALL(BPF_FUNC_strtol),
1305
1306
1307 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 19, 6),
1308
1309 BPF_LD_IMM64(BPF_REG_8, 0x7fffffffffffffffULL),
1310 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1311 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
1312
1313
1314 BPF_MOV64_IMM(BPF_REG_0, 1),
1315 BPF_JMP_A(1),
1316
1317
1318 BPF_MOV64_IMM(BPF_REG_0, 0),
1319 BPF_EXIT_INSN(),
1320 },
1321 .attach_type = BPF_CGROUP_SYSCTL,
1322 .sysctl = "net/ipv4/route/mtu_expires",
1323 .open_flags = O_RDONLY,
1324 .result = SUCCESS,
1325 },
1326 {
1327 "bpf_strtol overflow, ERANGE",
1328 .insns = {
1329
1330 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1331 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
1332 BPF_LD_IMM64(BPF_REG_0,
1333 bpf_be64_to_cpu(0x3932323333373230ULL)),
1334 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1335 BPF_LD_IMM64(BPF_REG_0,
1336 bpf_be64_to_cpu(0x3336383534373735ULL)),
1337 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
1338 BPF_LD_IMM64(BPF_REG_0,
1339 bpf_be64_to_cpu(0x3830380000000000ULL)),
1340 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16),
1341
1342 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1343
1344
1345 BPF_MOV64_IMM(BPF_REG_2, 19),
1346
1347
1348 BPF_MOV64_IMM(BPF_REG_3, 0),
1349
1350
1351 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1352 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1353 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1354
1355 BPF_EMIT_CALL(BPF_FUNC_strtol),
1356
1357
1358 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2),
1359
1360
1361 BPF_MOV64_IMM(BPF_REG_0, 1),
1362 BPF_JMP_A(1),
1363
1364
1365 BPF_MOV64_IMM(BPF_REG_0, 0),
1366 BPF_EXIT_INSN(),
1367 },
1368 .attach_type = BPF_CGROUP_SYSCTL,
1369 .sysctl = "net/ipv4/route/mtu_expires",
1370 .open_flags = O_RDONLY,
1371 .result = SUCCESS,
1372 },
1373 {
1374 "C prog: deny all writes",
1375 .prog_file = "./test_sysctl_prog.o",
1376 .attach_type = BPF_CGROUP_SYSCTL,
1377 .sysctl = "net/ipv4/tcp_mem",
1378 .open_flags = O_WRONLY,
1379 .newval = "123 456 789",
1380 .result = OP_EPERM,
1381 },
1382 {
1383 "C prog: deny access by name",
1384 .prog_file = "./test_sysctl_prog.o",
1385 .attach_type = BPF_CGROUP_SYSCTL,
1386 .sysctl = "net/ipv4/route/mtu_expires",
1387 .open_flags = O_RDONLY,
1388 .result = OP_EPERM,
1389 },
1390 {
1391 "C prog: read tcp_mem",
1392 .prog_file = "./test_sysctl_prog.o",
1393 .attach_type = BPF_CGROUP_SYSCTL,
1394 .sysctl = "net/ipv4/tcp_mem",
1395 .open_flags = O_RDONLY,
1396 .result = SUCCESS,
1397 },
1398};
1399
1400static size_t probe_prog_length(const struct bpf_insn *fp)
1401{
1402 size_t len;
1403
1404 for (len = MAX_INSNS - 1; len > 0; --len)
1405 if (fp[len].code != 0 || fp[len].imm != 0)
1406 break;
1407 return len + 1;
1408}
1409
1410static int fixup_sysctl_value(const char *buf, size_t buf_len,
1411 struct bpf_insn *prog, size_t insn_num)
1412{
1413 union {
1414 uint8_t raw[sizeof(uint64_t)];
1415 uint64_t num;
1416 } value = {};
1417
1418 if (buf_len > sizeof(value)) {
1419 log_err("Value is too big (%zd) to use in fixup", buf_len);
1420 return -1;
1421 }
1422 if (prog[insn_num].code != (BPF_LD | BPF_DW | BPF_IMM)) {
1423 log_err("Can fixup only BPF_LD_IMM64 insns");
1424 return -1;
1425 }
1426
1427 memcpy(value.raw, buf, buf_len);
1428 prog[insn_num].imm = (uint32_t)value.num;
1429 prog[insn_num + 1].imm = (uint32_t)(value.num >> 32);
1430
1431 return 0;
1432}
1433
1434static int load_sysctl_prog_insns(struct sysctl_test *test,
1435 const char *sysctl_path)
1436{
1437 struct bpf_insn *prog = test->insns;
1438 struct bpf_load_program_attr attr;
1439 int ret;
1440
1441 memset(&attr, 0, sizeof(struct bpf_load_program_attr));
1442 attr.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL;
1443 attr.insns = prog;
1444 attr.insns_cnt = probe_prog_length(attr.insns);
1445 attr.license = "GPL";
1446
1447 if (test->fixup_value_insn) {
1448 char buf[128];
1449 ssize_t len;
1450 int fd;
1451
1452 fd = open(sysctl_path, O_RDONLY | O_CLOEXEC);
1453 if (fd < 0) {
1454 log_err("open(%s) failed", sysctl_path);
1455 return -1;
1456 }
1457 len = read(fd, buf, sizeof(buf));
1458 if (len == -1) {
1459 log_err("read(%s) failed", sysctl_path);
1460 close(fd);
1461 return -1;
1462 }
1463 close(fd);
1464 if (fixup_sysctl_value(buf, len, prog, test->fixup_value_insn))
1465 return -1;
1466 }
1467
1468 ret = bpf_load_program_xattr(&attr, bpf_log_buf, BPF_LOG_BUF_SIZE);
1469 if (ret < 0 && test->result != LOAD_REJECT) {
1470 log_err(">>> Loading program error.\n"
1471 ">>> Verifier output:\n%s\n-------\n", bpf_log_buf);
1472 }
1473
1474 return ret;
1475}
1476
1477static int load_sysctl_prog_file(struct sysctl_test *test)
1478{
1479 struct bpf_prog_load_attr attr;
1480 struct bpf_object *obj;
1481 int prog_fd;
1482
1483 memset(&attr, 0, sizeof(struct bpf_prog_load_attr));
1484 attr.file = test->prog_file;
1485 attr.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL;
1486
1487 if (bpf_prog_load_xattr(&attr, &obj, &prog_fd)) {
1488 if (test->result != LOAD_REJECT)
1489 log_err(">>> Loading program (%s) error.\n",
1490 test->prog_file);
1491 return -1;
1492 }
1493
1494 return prog_fd;
1495}
1496
1497static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path)
1498{
1499 return test->prog_file
1500 ? load_sysctl_prog_file(test)
1501 : load_sysctl_prog_insns(test, sysctl_path);
1502}
1503
1504static int access_sysctl(const char *sysctl_path,
1505 const struct sysctl_test *test)
1506{
1507 int err = 0;
1508 int fd;
1509
1510 fd = open(sysctl_path, test->open_flags | O_CLOEXEC);
1511 if (fd < 0)
1512 return fd;
1513
1514 if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) {
1515 log_err("lseek(%d) failed", test->seek);
1516 goto err;
1517 }
1518
1519 if (test->open_flags == O_RDONLY) {
1520 char buf[128];
1521
1522 if (read(fd, buf, sizeof(buf)) == -1)
1523 goto err;
1524 if (test->oldval &&
1525 strncmp(buf, test->oldval, strlen(test->oldval))) {
1526 log_err("Read value %s != %s", buf, test->oldval);
1527 goto err;
1528 }
1529 } else if (test->open_flags == O_WRONLY) {
1530 if (!test->newval) {
1531 log_err("New value for sysctl is not set");
1532 goto err;
1533 }
1534 if (write(fd, test->newval, strlen(test->newval)) == -1)
1535 goto err;
1536 } else {
1537 log_err("Unexpected sysctl access: neither read nor write");
1538 goto err;
1539 }
1540
1541 goto out;
1542err:
1543 err = -1;
1544out:
1545 close(fd);
1546 return err;
1547}
1548
1549static int run_test_case(int cgfd, struct sysctl_test *test)
1550{
1551 enum bpf_attach_type atype = test->attach_type;
1552 char sysctl_path[128];
1553 int progfd = -1;
1554 int err = 0;
1555
1556 printf("Test case: %s .. ", test->descr);
1557
1558 snprintf(sysctl_path, sizeof(sysctl_path), "/proc/sys/%s",
1559 test->sysctl);
1560
1561 progfd = load_sysctl_prog(test, sysctl_path);
1562 if (progfd < 0) {
1563 if (test->result == LOAD_REJECT)
1564 goto out;
1565 else
1566 goto err;
1567 }
1568
1569 if (bpf_prog_attach(progfd, cgfd, atype, BPF_F_ALLOW_OVERRIDE) == -1) {
1570 if (test->result == ATTACH_REJECT)
1571 goto out;
1572 else
1573 goto err;
1574 }
1575
1576 errno = 0;
1577 if (access_sysctl(sysctl_path, test) == -1) {
1578 if (test->result == OP_EPERM && errno == EPERM)
1579 goto out;
1580 else
1581 goto err;
1582 }
1583
1584 if (test->result != SUCCESS) {
1585 log_err("Unexpected success");
1586 goto err;
1587 }
1588
1589 goto out;
1590err:
1591 err = -1;
1592out:
1593
1594 if (progfd != -1)
1595 bpf_prog_detach(cgfd, atype);
1596 close(progfd);
1597 printf("[%s]\n", err ? "FAIL" : "PASS");
1598 return err;
1599}
1600
1601static int run_tests(int cgfd)
1602{
1603 int passes = 0;
1604 int fails = 0;
1605 int i;
1606
1607 for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1608 if (run_test_case(cgfd, &tests[i]))
1609 ++fails;
1610 else
1611 ++passes;
1612 }
1613 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1614 return fails ? -1 : 0;
1615}
1616
1617int main(int argc, char **argv)
1618{
1619 int cgfd = -1;
1620 int err = 0;
1621
1622 cgfd = cgroup_setup_and_join(CG_PATH);
1623 if (cgfd < 0)
1624 goto err;
1625
1626 if (run_tests(cgfd))
1627 goto err;
1628
1629 goto out;
1630err:
1631 err = -1;
1632out:
1633 close(cgfd);
1634 cleanup_cgroup_environment();
1635 return err;
1636}
1637