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