treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / tools / testing / selftests / bpf / test_sysctl.c
blobd196e2a4a6e04d3be7b090bf4723218f57ad2f01
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Facebook
4 #include <fcntl.h>
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
11 #include <linux/filter.h>
13 #include <bpf/bpf.h>
14 #include <bpf/libbpf.h>
16 #include <bpf/bpf_endian.h>
17 #include "bpf_rlimit.h"
18 #include "bpf_util.h"
19 #include "cgroup_helpers.h"
21 #define CG_PATH "/foo"
22 #define MAX_INSNS 512
23 #define FIXUP_SYSCTL_VALUE 0
25 char bpf_log_buf[BPF_LOG_BUF_SIZE];
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;
46 static struct sysctl_test tests[] = {
48 .descr = "sysctl wrong attach_type",
49 .insns = {
50 BPF_MOV64_IMM(BPF_REG_0, 1),
51 BPF_EXIT_INSN(),
53 .attach_type = 0,
54 .sysctl = "kernel/ostype",
55 .open_flags = O_RDONLY,
56 .result = ATTACH_REJECT,
59 .descr = "sysctl:read allow all",
60 .insns = {
61 BPF_MOV64_IMM(BPF_REG_0, 1),
62 BPF_EXIT_INSN(),
64 .attach_type = BPF_CGROUP_SYSCTL,
65 .sysctl = "kernel/ostype",
66 .open_flags = O_RDONLY,
67 .result = SUCCESS,
70 .descr = "sysctl:read deny all",
71 .insns = {
72 BPF_MOV64_IMM(BPF_REG_0, 0),
73 BPF_EXIT_INSN(),
75 .attach_type = BPF_CGROUP_SYSCTL,
76 .sysctl = "kernel/ostype",
77 .open_flags = O_RDONLY,
78 .result = OP_EPERM,
81 .descr = "ctx:write sysctl:read read ok",
82 .insns = {
83 /* If (write) */
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),
88 /* return DENY; */
89 BPF_MOV64_IMM(BPF_REG_0, 0),
90 BPF_JMP_A(1),
92 /* else return ALLOW; */
93 BPF_MOV64_IMM(BPF_REG_0, 1),
94 BPF_EXIT_INSN(),
96 .attach_type = BPF_CGROUP_SYSCTL,
97 .sysctl = "kernel/ostype",
98 .open_flags = O_RDONLY,
99 .result = SUCCESS,
102 .descr = "ctx:write sysctl:write read ok",
103 .insns = {
104 /* If (write) */
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),
109 /* return DENY; */
110 BPF_MOV64_IMM(BPF_REG_0, 0),
111 BPF_JMP_A(1),
113 /* else return ALLOW; */
114 BPF_MOV64_IMM(BPF_REG_0, 1),
115 BPF_EXIT_INSN(),
117 .attach_type = BPF_CGROUP_SYSCTL,
118 .sysctl = "kernel/domainname",
119 .open_flags = O_WRONLY,
120 .newval = "(none)", /* same as default, should fail anyway */
121 .result = OP_EPERM,
124 .descr = "ctx:write sysctl:write read ok narrow",
125 .insns = {
126 /* u64 w = (u16)write & 1; */
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 /* return 1 - w; */
136 BPF_MOV64_IMM(BPF_REG_0, 1),
137 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_7),
138 BPF_EXIT_INSN(),
140 .attach_type = BPF_CGROUP_SYSCTL,
141 .sysctl = "kernel/domainname",
142 .open_flags = O_WRONLY,
143 .newval = "(none)", /* same as default, should fail anyway */
144 .result = OP_EPERM,
147 .descr = "ctx:write sysctl:read write reject",
148 .insns = {
149 /* write = X */
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(),
156 .attach_type = BPF_CGROUP_SYSCTL,
157 .sysctl = "kernel/ostype",
158 .open_flags = O_RDONLY,
159 .result = LOAD_REJECT,
162 .descr = "ctx:file_pos sysctl:read read ok",
163 .insns = {
164 /* If (file_pos == X) */
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),
169 /* return ALLOW; */
170 BPF_MOV64_IMM(BPF_REG_0, 1),
171 BPF_JMP_A(1),
173 /* else return DENY; */
174 BPF_MOV64_IMM(BPF_REG_0, 0),
175 BPF_EXIT_INSN(),
177 .attach_type = BPF_CGROUP_SYSCTL,
178 .sysctl = "kernel/ostype",
179 .open_flags = O_RDONLY,
180 .seek = 3,
181 .result = SUCCESS,
184 .descr = "ctx:file_pos sysctl:read read ok narrow",
185 .insns = {
186 /* If (file_pos == X) */
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),
196 /* return ALLOW; */
197 BPF_MOV64_IMM(BPF_REG_0, 1),
198 BPF_JMP_A(1),
200 /* else return DENY; */
201 BPF_MOV64_IMM(BPF_REG_0, 0),
202 BPF_EXIT_INSN(),
204 .attach_type = BPF_CGROUP_SYSCTL,
205 .sysctl = "kernel/ostype",
206 .open_flags = O_RDONLY,
207 .seek = 4,
208 .result = SUCCESS,
211 .descr = "ctx:file_pos sysctl:read write ok",
212 .insns = {
213 /* file_pos = X */
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(),
220 .attach_type = BPF_CGROUP_SYSCTL,
221 .sysctl = "kernel/ostype",
222 .open_flags = O_RDONLY,
223 .oldval = "nux\n",
224 .result = SUCCESS,
227 .descr = "sysctl_get_name sysctl_value:base ok",
228 .insns = {
229 /* sysctl_get_name arg2 (buf) */
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),
235 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
237 /* sysctl_get_name arg3 (buf_len) */
238 BPF_MOV64_IMM(BPF_REG_3, 8),
240 /* sysctl_get_name arg4 (flags) */
241 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
243 /* sysctl_get_name(ctx, buf, buf_len, flags) */
244 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
246 /* if (ret == expected && */
247 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6),
248 /* buf == "tcp_mem\0") */
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),
254 /* return ALLOW; */
255 BPF_MOV64_IMM(BPF_REG_0, 1),
256 BPF_JMP_A(1),
258 /* else return DENY; */
259 BPF_MOV64_IMM(BPF_REG_0, 0),
260 BPF_EXIT_INSN(),
262 .attach_type = BPF_CGROUP_SYSCTL,
263 .sysctl = "net/ipv4/tcp_mem",
264 .open_flags = O_RDONLY,
265 .result = SUCCESS,
268 .descr = "sysctl_get_name sysctl_value:base E2BIG truncated",
269 .insns = {
270 /* sysctl_get_name arg2 (buf) */
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),
276 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
278 /* sysctl_get_name arg3 (buf_len) too small */
279 BPF_MOV64_IMM(BPF_REG_3, 7),
281 /* sysctl_get_name arg4 (flags) */
282 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
284 /* sysctl_get_name(ctx, buf, buf_len, flags) */
285 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
287 /* if (ret == expected && */
288 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
290 /* buf[0:7] == "tcp_me\0") */
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),
296 /* return ALLOW; */
297 BPF_MOV64_IMM(BPF_REG_0, 1),
298 BPF_JMP_A(1),
300 /* else return DENY; */
301 BPF_MOV64_IMM(BPF_REG_0, 0),
302 BPF_EXIT_INSN(),
304 .attach_type = BPF_CGROUP_SYSCTL,
305 .sysctl = "net/ipv4/tcp_mem",
306 .open_flags = O_RDONLY,
307 .result = SUCCESS,
310 .descr = "sysctl_get_name sysctl:full ok",
311 .insns = {
312 /* sysctl_get_name arg2 (buf) */
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),
320 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
322 /* sysctl_get_name arg3 (buf_len) */
323 BPF_MOV64_IMM(BPF_REG_3, 17),
325 /* sysctl_get_name arg4 (flags) */
326 BPF_MOV64_IMM(BPF_REG_4, 0),
328 /* sysctl_get_name(ctx, buf, buf_len, flags) */
329 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
331 /* if (ret == expected && */
332 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14),
334 /* buf[0:8] == "net/ipv4" && */
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),
340 /* buf[8:16] == "/tcp_mem" && */
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),
346 /* buf[16:24] == "\0") */
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),
351 /* return ALLOW; */
352 BPF_MOV64_IMM(BPF_REG_0, 1),
353 BPF_JMP_A(1),
355 /* else return DENY; */
356 BPF_MOV64_IMM(BPF_REG_0, 0),
357 BPF_EXIT_INSN(),
359 .attach_type = BPF_CGROUP_SYSCTL,
360 .sysctl = "net/ipv4/tcp_mem",
361 .open_flags = O_RDONLY,
362 .result = SUCCESS,
365 .descr = "sysctl_get_name sysctl:full E2BIG truncated",
366 .insns = {
367 /* sysctl_get_name arg2 (buf) */
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),
374 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
376 /* sysctl_get_name arg3 (buf_len) */
377 BPF_MOV64_IMM(BPF_REG_3, 16),
379 /* sysctl_get_name arg4 (flags) */
380 BPF_MOV64_IMM(BPF_REG_4, 0),
382 /* sysctl_get_name(ctx, buf, buf_len, flags) */
383 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
385 /* if (ret == expected && */
386 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10),
388 /* buf[0:8] == "net/ipv4" && */
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),
394 /* buf[8:16] == "/tcp_me\0") */
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),
400 /* return ALLOW; */
401 BPF_MOV64_IMM(BPF_REG_0, 1),
402 BPF_JMP_A(1),
404 /* else return DENY; */
405 BPF_MOV64_IMM(BPF_REG_0, 0),
406 BPF_EXIT_INSN(),
408 .attach_type = BPF_CGROUP_SYSCTL,
409 .sysctl = "net/ipv4/tcp_mem",
410 .open_flags = O_RDONLY,
411 .result = SUCCESS,
414 .descr = "sysctl_get_name sysctl:full E2BIG truncated small",
415 .insns = {
416 /* sysctl_get_name arg2 (buf) */
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),
422 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
424 /* sysctl_get_name arg3 (buf_len) */
425 BPF_MOV64_IMM(BPF_REG_3, 7),
427 /* sysctl_get_name arg4 (flags) */
428 BPF_MOV64_IMM(BPF_REG_4, 0),
430 /* sysctl_get_name(ctx, buf, buf_len, flags) */
431 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
433 /* if (ret == expected && */
434 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
436 /* buf[0:8] == "net/ip\0") */
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),
442 /* return ALLOW; */
443 BPF_MOV64_IMM(BPF_REG_0, 1),
444 BPF_JMP_A(1),
446 /* else return DENY; */
447 BPF_MOV64_IMM(BPF_REG_0, 0),
448 BPF_EXIT_INSN(),
450 .attach_type = BPF_CGROUP_SYSCTL,
451 .sysctl = "net/ipv4/tcp_mem",
452 .open_flags = O_RDONLY,
453 .result = SUCCESS,
456 .descr = "sysctl_get_current_value sysctl:read ok, gt",
457 .insns = {
458 /* sysctl_get_current_value arg2 (buf) */
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),
463 /* sysctl_get_current_value arg3 (buf_len) */
464 BPF_MOV64_IMM(BPF_REG_3, 8),
466 /* sysctl_get_current_value(ctx, buf, buf_len) */
467 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
469 /* if (ret == expected && */
470 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
472 /* buf[0:6] == "Linux\n\0") */
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),
478 /* return ALLOW; */
479 BPF_MOV64_IMM(BPF_REG_0, 1),
480 BPF_JMP_A(1),
482 /* else return DENY; */
483 BPF_MOV64_IMM(BPF_REG_0, 0),
484 BPF_EXIT_INSN(),
486 .attach_type = BPF_CGROUP_SYSCTL,
487 .sysctl = "kernel/ostype",
488 .open_flags = O_RDONLY,
489 .result = SUCCESS,
492 .descr = "sysctl_get_current_value sysctl:read ok, eq",
493 .insns = {
494 /* sysctl_get_current_value arg2 (buf) */
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),
500 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
502 /* sysctl_get_current_value arg3 (buf_len) */
503 BPF_MOV64_IMM(BPF_REG_3, 7),
505 /* sysctl_get_current_value(ctx, buf, buf_len) */
506 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
508 /* if (ret == expected && */
509 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
511 /* buf[0:6] == "Linux\n\0") */
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),
517 /* return ALLOW; */
518 BPF_MOV64_IMM(BPF_REG_0, 1),
519 BPF_JMP_A(1),
521 /* else return DENY; */
522 BPF_MOV64_IMM(BPF_REG_0, 0),
523 BPF_EXIT_INSN(),
525 .attach_type = BPF_CGROUP_SYSCTL,
526 .sysctl = "kernel/ostype",
527 .open_flags = O_RDONLY,
528 .result = SUCCESS,
531 .descr = "sysctl_get_current_value sysctl:read E2BIG truncated",
532 .insns = {
533 /* sysctl_get_current_value arg2 (buf) */
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),
539 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
541 /* sysctl_get_current_value arg3 (buf_len) */
542 BPF_MOV64_IMM(BPF_REG_3, 6),
544 /* sysctl_get_current_value(ctx, buf, buf_len) */
545 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
547 /* if (ret == expected && */
548 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
550 /* buf[0:6] == "Linux\0") */
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),
556 /* return ALLOW; */
557 BPF_MOV64_IMM(BPF_REG_0, 1),
558 BPF_JMP_A(1),
560 /* else return DENY; */
561 BPF_MOV64_IMM(BPF_REG_0, 0),
562 BPF_EXIT_INSN(),
564 .attach_type = BPF_CGROUP_SYSCTL,
565 .sysctl = "kernel/ostype",
566 .open_flags = O_RDONLY,
567 .result = SUCCESS,
570 .descr = "sysctl_get_current_value sysctl:read EINVAL",
571 .insns = {
572 /* sysctl_get_current_value arg2 (buf) */
573 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
574 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
576 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
578 /* sysctl_get_current_value arg3 (buf_len) */
579 BPF_MOV64_IMM(BPF_REG_3, 8),
581 /* sysctl_get_current_value(ctx, buf, buf_len) */
582 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
584 /* if (ret == expected && */
585 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4),
587 /* buf[0:8] is NUL-filled) */
588 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
589 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2),
591 /* return DENY; */
592 BPF_MOV64_IMM(BPF_REG_0, 0),
593 BPF_JMP_A(1),
595 /* else return ALLOW; */
596 BPF_MOV64_IMM(BPF_REG_0, 1),
597 BPF_EXIT_INSN(),
599 .attach_type = BPF_CGROUP_SYSCTL,
600 .sysctl = "net/ipv6/conf/lo/stable_secret", /* -EIO */
601 .open_flags = O_RDONLY,
602 .result = OP_EPERM,
605 .descr = "sysctl_get_current_value sysctl:write ok",
606 .fixup_value_insn = 6,
607 .insns = {
608 /* sysctl_get_current_value arg2 (buf) */
609 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
610 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
612 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
614 /* sysctl_get_current_value arg3 (buf_len) */
615 BPF_MOV64_IMM(BPF_REG_3, 8),
617 /* sysctl_get_current_value(ctx, buf, buf_len) */
618 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
620 /* if (ret == expected && */
621 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6),
623 /* buf[0:4] == expected) */
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),
628 /* return DENY; */
629 BPF_MOV64_IMM(BPF_REG_0, 0),
630 BPF_JMP_A(1),
632 /* else return ALLOW; */
633 BPF_MOV64_IMM(BPF_REG_0, 1),
634 BPF_EXIT_INSN(),
636 .attach_type = BPF_CGROUP_SYSCTL,
637 .sysctl = "net/ipv4/route/mtu_expires",
638 .open_flags = O_WRONLY,
639 .newval = "600", /* same as default, should fail anyway */
640 .result = OP_EPERM,
643 .descr = "sysctl_get_new_value sysctl:read EINVAL",
644 .insns = {
645 /* sysctl_get_new_value arg2 (buf) */
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),
651 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
653 /* sysctl_get_new_value arg3 (buf_len) */
654 BPF_MOV64_IMM(BPF_REG_3, 8),
656 /* sysctl_get_new_value(ctx, buf, buf_len) */
657 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
659 /* if (ret == expected) */
660 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
662 /* return ALLOW; */
663 BPF_MOV64_IMM(BPF_REG_0, 1),
664 BPF_JMP_A(1),
666 /* else return DENY; */
667 BPF_MOV64_IMM(BPF_REG_0, 0),
668 BPF_EXIT_INSN(),
670 .attach_type = BPF_CGROUP_SYSCTL,
671 .sysctl = "net/ipv4/tcp_mem",
672 .open_flags = O_RDONLY,
673 .result = SUCCESS,
676 .descr = "sysctl_get_new_value sysctl:write ok",
677 .insns = {
678 /* sysctl_get_new_value arg2 (buf) */
679 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
680 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
682 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
684 /* sysctl_get_new_value arg3 (buf_len) */
685 BPF_MOV64_IMM(BPF_REG_3, 4),
687 /* sysctl_get_new_value(ctx, buf, buf_len) */
688 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
690 /* if (ret == expected && */
691 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
693 /* buf[0:4] == "606\0") */
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),
698 /* return DENY; */
699 BPF_MOV64_IMM(BPF_REG_0, 0),
700 BPF_JMP_A(1),
702 /* else return ALLOW; */
703 BPF_MOV64_IMM(BPF_REG_0, 1),
704 BPF_EXIT_INSN(),
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,
713 .descr = "sysctl_get_new_value sysctl:write ok long",
714 .insns = {
715 /* sysctl_get_new_value arg2 (buf) */
716 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
717 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
719 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
721 /* sysctl_get_new_value arg3 (buf_len) */
722 BPF_MOV64_IMM(BPF_REG_3, 24),
724 /* sysctl_get_new_value(ctx, buf, buf_len) */
725 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
727 /* if (ret == expected && */
728 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14),
730 /* buf[0:8] == "3000000 " && */
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),
736 /* buf[8:16] == "4000000 " && */
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),
742 /* buf[16:24] == "6000000\0") */
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),
748 /* return DENY; */
749 BPF_MOV64_IMM(BPF_REG_0, 0),
750 BPF_JMP_A(1),
752 /* else return ALLOW; */
753 BPF_MOV64_IMM(BPF_REG_0, 1),
754 BPF_EXIT_INSN(),
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,
763 .descr = "sysctl_get_new_value sysctl:write E2BIG",
764 .insns = {
765 /* sysctl_get_new_value arg2 (buf) */
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),
771 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
773 /* sysctl_get_new_value arg3 (buf_len) */
774 BPF_MOV64_IMM(BPF_REG_3, 3),
776 /* sysctl_get_new_value(ctx, buf, buf_len) */
777 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
779 /* if (ret == expected && */
780 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4),
782 /* buf[0:3] == "60\0") */
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),
787 /* return DENY; */
788 BPF_MOV64_IMM(BPF_REG_0, 0),
789 BPF_JMP_A(1),
791 /* else return ALLOW; */
792 BPF_MOV64_IMM(BPF_REG_0, 1),
793 BPF_EXIT_INSN(),
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,
802 .descr = "sysctl_set_new_value sysctl:read EINVAL",
803 .insns = {
804 /* sysctl_set_new_value arg2 (buf) */
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),
811 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
813 /* sysctl_set_new_value arg3 (buf_len) */
814 BPF_MOV64_IMM(BPF_REG_3, 3),
816 /* sysctl_set_new_value(ctx, buf, buf_len) */
817 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
819 /* if (ret == expected) */
820 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
822 /* return ALLOW; */
823 BPF_MOV64_IMM(BPF_REG_0, 1),
824 BPF_JMP_A(1),
826 /* else return DENY; */
827 BPF_MOV64_IMM(BPF_REG_0, 0),
828 BPF_EXIT_INSN(),
830 .attach_type = BPF_CGROUP_SYSCTL,
831 .sysctl = "net/ipv4/route/mtu_expires",
832 .open_flags = O_RDONLY,
833 .result = SUCCESS,
836 .descr = "sysctl_set_new_value sysctl:write ok",
837 .fixup_value_insn = 2,
838 .insns = {
839 /* sysctl_set_new_value arg2 (buf) */
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),
845 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
847 /* sysctl_set_new_value arg3 (buf_len) */
848 BPF_MOV64_IMM(BPF_REG_3, 3),
850 /* sysctl_set_new_value(ctx, buf, buf_len) */
851 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
853 /* if (ret == expected) */
854 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
856 /* return ALLOW; */
857 BPF_MOV64_IMM(BPF_REG_0, 1),
858 BPF_JMP_A(1),
860 /* else return DENY; */
861 BPF_MOV64_IMM(BPF_REG_0, 0),
862 BPF_EXIT_INSN(),
864 .attach_type = BPF_CGROUP_SYSCTL,
865 .sysctl = "net/ipv4/route/mtu_expires",
866 .open_flags = O_WRONLY,
867 .newval = "606",
868 .result = SUCCESS,
871 "bpf_strtoul one number string",
872 .insns = {
873 /* arg1 (buf) */
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),
880 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
882 /* arg2 (buf_len) */
883 BPF_MOV64_IMM(BPF_REG_2, 4),
885 /* arg3 (flags) */
886 BPF_MOV64_IMM(BPF_REG_3, 0),
888 /* arg4 (res) */
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),
893 BPF_EMIT_CALL(BPF_FUNC_strtoul),
895 /* if (ret == expected && */
896 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
897 /* res == expected) */
898 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
899 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 2),
901 /* return ALLOW; */
902 BPF_MOV64_IMM(BPF_REG_0, 1),
903 BPF_JMP_A(1),
905 /* else return DENY; */
906 BPF_MOV64_IMM(BPF_REG_0, 0),
907 BPF_EXIT_INSN(),
909 .attach_type = BPF_CGROUP_SYSCTL,
910 .sysctl = "net/ipv4/route/mtu_expires",
911 .open_flags = O_RDONLY,
912 .result = SUCCESS,
915 "bpf_strtoul multi number string",
916 .insns = {
917 /* arg1 (buf) */
918 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
919 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
920 /* "600 602\0" */
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),
926 /* arg2 (buf_len) */
927 BPF_MOV64_IMM(BPF_REG_2, 8),
929 /* arg3 (flags) */
930 BPF_MOV64_IMM(BPF_REG_3, 0),
932 /* arg4 (res) */
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),
937 BPF_EMIT_CALL(BPF_FUNC_strtoul),
939 /* if (ret == expected && */
940 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18),
941 /* res == expected) */
942 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
943 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 16),
945 /* arg1 (buf) */
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),
951 /* arg2 (buf_len) */
952 BPF_MOV64_IMM(BPF_REG_2, 8),
953 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0),
955 /* arg3 (flags) */
956 BPF_MOV64_IMM(BPF_REG_3, 0),
958 /* arg4 (res) */
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),
963 BPF_EMIT_CALL(BPF_FUNC_strtoul),
965 /* if (ret == expected && */
966 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
967 /* res == expected) */
968 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
969 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 602, 2),
971 /* return ALLOW; */
972 BPF_MOV64_IMM(BPF_REG_0, 1),
973 BPF_JMP_A(1),
975 /* else return DENY; */
976 BPF_MOV64_IMM(BPF_REG_0, 0),
977 BPF_EXIT_INSN(),
979 .attach_type = BPF_CGROUP_SYSCTL,
980 .sysctl = "net/ipv4/tcp_mem",
981 .open_flags = O_RDONLY,
982 .result = SUCCESS,
985 "bpf_strtoul buf_len = 0, reject",
986 .insns = {
987 /* arg1 (buf) */
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),
994 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
996 /* arg2 (buf_len) */
997 BPF_MOV64_IMM(BPF_REG_2, 0),
999 /* arg3 (flags) */
1000 BPF_MOV64_IMM(BPF_REG_3, 0),
1002 /* arg4 (res) */
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),
1007 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1009 BPF_MOV64_IMM(BPF_REG_0, 1),
1010 BPF_EXIT_INSN(),
1012 .attach_type = BPF_CGROUP_SYSCTL,
1013 .sysctl = "net/ipv4/route/mtu_expires",
1014 .open_flags = O_RDONLY,
1015 .result = LOAD_REJECT,
1018 "bpf_strtoul supported base, ok",
1019 .insns = {
1020 /* arg1 (buf) */
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),
1027 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1029 /* arg2 (buf_len) */
1030 BPF_MOV64_IMM(BPF_REG_2, 4),
1032 /* arg3 (flags) */
1033 BPF_MOV64_IMM(BPF_REG_3, 8),
1035 /* arg4 (res) */
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),
1040 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1042 /* if (ret == expected && */
1043 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1044 /* res == expected) */
1045 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1046 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 63, 2),
1048 /* return ALLOW; */
1049 BPF_MOV64_IMM(BPF_REG_0, 1),
1050 BPF_JMP_A(1),
1052 /* else return DENY; */
1053 BPF_MOV64_IMM(BPF_REG_0, 0),
1054 BPF_EXIT_INSN(),
1056 .attach_type = BPF_CGROUP_SYSCTL,
1057 .sysctl = "net/ipv4/route/mtu_expires",
1058 .open_flags = O_RDONLY,
1059 .result = SUCCESS,
1062 "bpf_strtoul unsupported base, EINVAL",
1063 .insns = {
1064 /* arg1 (buf) */
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),
1071 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1073 /* arg2 (buf_len) */
1074 BPF_MOV64_IMM(BPF_REG_2, 4),
1076 /* arg3 (flags) */
1077 BPF_MOV64_IMM(BPF_REG_3, 3),
1079 /* arg4 (res) */
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),
1084 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1086 /* if (ret == expected) */
1087 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1089 /* return ALLOW; */
1090 BPF_MOV64_IMM(BPF_REG_0, 1),
1091 BPF_JMP_A(1),
1093 /* else return DENY; */
1094 BPF_MOV64_IMM(BPF_REG_0, 0),
1095 BPF_EXIT_INSN(),
1097 .attach_type = BPF_CGROUP_SYSCTL,
1098 .sysctl = "net/ipv4/route/mtu_expires",
1099 .open_flags = O_RDONLY,
1100 .result = SUCCESS,
1103 "bpf_strtoul buf with spaces only, EINVAL",
1104 .insns = {
1105 /* arg1 (buf) */
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),
1112 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1114 /* arg2 (buf_len) */
1115 BPF_MOV64_IMM(BPF_REG_2, 4),
1117 /* arg3 (flags) */
1118 BPF_MOV64_IMM(BPF_REG_3, 0),
1120 /* arg4 (res) */
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),
1125 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1127 /* if (ret == expected) */
1128 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1130 /* return ALLOW; */
1131 BPF_MOV64_IMM(BPF_REG_0, 1),
1132 BPF_JMP_A(1),
1134 /* else return DENY; */
1135 BPF_MOV64_IMM(BPF_REG_0, 0),
1136 BPF_EXIT_INSN(),
1138 .attach_type = BPF_CGROUP_SYSCTL,
1139 .sysctl = "net/ipv4/route/mtu_expires",
1140 .open_flags = O_RDONLY,
1141 .result = SUCCESS,
1144 "bpf_strtoul negative number, EINVAL",
1145 .insns = {
1146 /* arg1 (buf) */
1147 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1148 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1149 /* " -6\0" */
1150 BPF_MOV64_IMM(BPF_REG_0,
1151 bpf_ntohl(0x0a2d3600)),
1152 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1154 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1156 /* arg2 (buf_len) */
1157 BPF_MOV64_IMM(BPF_REG_2, 4),
1159 /* arg3 (flags) */
1160 BPF_MOV64_IMM(BPF_REG_3, 0),
1162 /* arg4 (res) */
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),
1167 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1169 /* if (ret == expected) */
1170 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1172 /* return ALLOW; */
1173 BPF_MOV64_IMM(BPF_REG_0, 1),
1174 BPF_JMP_A(1),
1176 /* else return DENY; */
1177 BPF_MOV64_IMM(BPF_REG_0, 0),
1178 BPF_EXIT_INSN(),
1180 .attach_type = BPF_CGROUP_SYSCTL,
1181 .sysctl = "net/ipv4/route/mtu_expires",
1182 .open_flags = O_RDONLY,
1183 .result = SUCCESS,
1186 "bpf_strtol negative number, ok",
1187 .insns = {
1188 /* arg1 (buf) */
1189 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1190 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1191 /* " -6\0" */
1192 BPF_MOV64_IMM(BPF_REG_0,
1193 bpf_ntohl(0x0a2d3600)),
1194 BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1196 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1198 /* arg2 (buf_len) */
1199 BPF_MOV64_IMM(BPF_REG_2, 4),
1201 /* arg3 (flags) */
1202 BPF_MOV64_IMM(BPF_REG_3, 10),
1204 /* arg4 (res) */
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),
1209 BPF_EMIT_CALL(BPF_FUNC_strtol),
1211 /* if (ret == expected && */
1212 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1213 /* res == expected) */
1214 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1215 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -6, 2),
1217 /* return ALLOW; */
1218 BPF_MOV64_IMM(BPF_REG_0, 1),
1219 BPF_JMP_A(1),
1221 /* else return DENY; */
1222 BPF_MOV64_IMM(BPF_REG_0, 0),
1223 BPF_EXIT_INSN(),
1225 .attach_type = BPF_CGROUP_SYSCTL,
1226 .sysctl = "net/ipv4/route/mtu_expires",
1227 .open_flags = O_RDONLY,
1228 .result = SUCCESS,
1231 "bpf_strtol hex number, ok",
1232 .insns = {
1233 /* arg1 (buf) */
1234 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1235 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1236 /* "0xfe" */
1237 BPF_MOV64_IMM(BPF_REG_0,
1238 bpf_ntohl(0x30786665)),
1239 BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1241 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1243 /* arg2 (buf_len) */
1244 BPF_MOV64_IMM(BPF_REG_2, 4),
1246 /* arg3 (flags) */
1247 BPF_MOV64_IMM(BPF_REG_3, 0),
1249 /* arg4 (res) */
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),
1254 BPF_EMIT_CALL(BPF_FUNC_strtol),
1256 /* if (ret == expected && */
1257 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
1258 /* res == expected) */
1259 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1260 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 254, 2),
1262 /* return ALLOW; */
1263 BPF_MOV64_IMM(BPF_REG_0, 1),
1264 BPF_JMP_A(1),
1266 /* else return DENY; */
1267 BPF_MOV64_IMM(BPF_REG_0, 0),
1268 BPF_EXIT_INSN(),
1270 .attach_type = BPF_CGROUP_SYSCTL,
1271 .sysctl = "net/ipv4/route/mtu_expires",
1272 .open_flags = O_RDONLY,
1273 .result = SUCCESS,
1276 "bpf_strtol max long",
1277 .insns = {
1278 /* arg1 (buf) 9223372036854775807 */
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),
1291 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1293 /* arg2 (buf_len) */
1294 BPF_MOV64_IMM(BPF_REG_2, 19),
1296 /* arg3 (flags) */
1297 BPF_MOV64_IMM(BPF_REG_3, 0),
1299 /* arg4 (res) */
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),
1304 BPF_EMIT_CALL(BPF_FUNC_strtol),
1306 /* if (ret == expected && */
1307 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 19, 6),
1308 /* res == expected) */
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),
1313 /* return ALLOW; */
1314 BPF_MOV64_IMM(BPF_REG_0, 1),
1315 BPF_JMP_A(1),
1317 /* else return DENY; */
1318 BPF_MOV64_IMM(BPF_REG_0, 0),
1319 BPF_EXIT_INSN(),
1321 .attach_type = BPF_CGROUP_SYSCTL,
1322 .sysctl = "net/ipv4/route/mtu_expires",
1323 .open_flags = O_RDONLY,
1324 .result = SUCCESS,
1327 "bpf_strtol overflow, ERANGE",
1328 .insns = {
1329 /* arg1 (buf) 9223372036854775808 */
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),
1342 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1344 /* arg2 (buf_len) */
1345 BPF_MOV64_IMM(BPF_REG_2, 19),
1347 /* arg3 (flags) */
1348 BPF_MOV64_IMM(BPF_REG_3, 0),
1350 /* arg4 (res) */
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),
1355 BPF_EMIT_CALL(BPF_FUNC_strtol),
1357 /* if (ret == expected) */
1358 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2),
1360 /* return ALLOW; */
1361 BPF_MOV64_IMM(BPF_REG_0, 1),
1362 BPF_JMP_A(1),
1364 /* else return DENY; */
1365 BPF_MOV64_IMM(BPF_REG_0, 0),
1366 BPF_EXIT_INSN(),
1368 .attach_type = BPF_CGROUP_SYSCTL,
1369 .sysctl = "net/ipv4/route/mtu_expires",
1370 .open_flags = O_RDONLY,
1371 .result = SUCCESS,
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,
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,
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,
1400 static size_t probe_prog_length(const struct bpf_insn *fp)
1402 size_t len;
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;
1410 static int fixup_sysctl_value(const char *buf, size_t buf_len,
1411 struct bpf_insn *prog, size_t insn_num)
1413 union {
1414 uint8_t raw[sizeof(uint64_t)];
1415 uint64_t num;
1416 } value = {};
1418 if (buf_len > sizeof(value)) {
1419 log_err("Value is too big (%zd) to use in fixup", buf_len);
1420 return -1;
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;
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);
1431 return 0;
1434 static int load_sysctl_prog_insns(struct sysctl_test *test,
1435 const char *sysctl_path)
1437 struct bpf_insn *prog = test->insns;
1438 struct bpf_load_program_attr attr;
1439 int ret;
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";
1447 if (test->fixup_value_insn) {
1448 char buf[128];
1449 ssize_t len;
1450 int fd;
1452 fd = open(sysctl_path, O_RDONLY | O_CLOEXEC);
1453 if (fd < 0) {
1454 log_err("open(%s) failed", sysctl_path);
1455 return -1;
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;
1463 close(fd);
1464 if (fixup_sysctl_value(buf, len, prog, test->fixup_value_insn))
1465 return -1;
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);
1474 return ret;
1477 static int load_sysctl_prog_file(struct sysctl_test *test)
1479 struct bpf_prog_load_attr attr;
1480 struct bpf_object *obj;
1481 int prog_fd;
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;
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;
1494 return prog_fd;
1497 static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path)
1499 return test->prog_file
1500 ? load_sysctl_prog_file(test)
1501 : load_sysctl_prog_insns(test, sysctl_path);
1504 static int access_sysctl(const char *sysctl_path,
1505 const struct sysctl_test *test)
1507 int err = 0;
1508 int fd;
1510 fd = open(sysctl_path, test->open_flags | O_CLOEXEC);
1511 if (fd < 0)
1512 return fd;
1514 if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) {
1515 log_err("lseek(%d) failed", test->seek);
1516 goto err;
1519 if (test->open_flags == O_RDONLY) {
1520 char buf[128];
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;
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;
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;
1541 goto out;
1542 err:
1543 err = -1;
1544 out:
1545 close(fd);
1546 return err;
1549 static int run_test_case(int cgfd, struct sysctl_test *test)
1551 enum bpf_attach_type atype = test->attach_type;
1552 char sysctl_path[128];
1553 int progfd = -1;
1554 int err = 0;
1556 printf("Test case: %s .. ", test->descr);
1558 snprintf(sysctl_path, sizeof(sysctl_path), "/proc/sys/%s",
1559 test->sysctl);
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;
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;
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;
1584 if (test->result != SUCCESS) {
1585 log_err("Unexpected success");
1586 goto err;
1589 goto out;
1590 err:
1591 err = -1;
1592 out:
1593 /* Detaching w/o checking return code: best effort attempt. */
1594 if (progfd != -1)
1595 bpf_prog_detach(cgfd, atype);
1596 close(progfd);
1597 printf("[%s]\n", err ? "FAIL" : "PASS");
1598 return err;
1601 static int run_tests(int cgfd)
1603 int passes = 0;
1604 int fails = 0;
1605 int i;
1607 for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1608 if (run_test_case(cgfd, &tests[i]))
1609 ++fails;
1610 else
1611 ++passes;
1613 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1614 return fails ? -1 : 0;
1617 int main(int argc, char **argv)
1619 int cgfd = -1;
1620 int err = 0;
1622 if (setup_cgroup_environment())
1623 goto err;
1625 cgfd = create_and_get_cgroup(CG_PATH);
1626 if (cgfd < 0)
1627 goto err;
1629 if (join_cgroup(CG_PATH))
1630 goto err;
1632 if (run_tests(cgfd))
1633 goto err;
1635 goto out;
1636 err:
1637 err = -1;
1638 out:
1639 close(cgfd);
1640 cleanup_cgroup_environment();
1641 return err;