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