staging: rtl8192u: remove redundant assignment to pointer crypt
[linux/fpc-iii.git] / tools / testing / selftests / bpf / test_sysctl.c
bloba3bebd7c68ddc6262c5eaf6021bd8c8304b6a006
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_rlimit.h"
17 #include "bpf_util.h"
18 #include "cgroup_helpers.h"
20 #define CG_PATH "/foo"
21 #define MAX_INSNS 512
22 #define FIXUP_SYSCTL_VALUE 0
24 char bpf_log_buf[BPF_LOG_BUF_SIZE];
26 struct 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;
44 static struct sysctl_test tests[] = {
46 .descr = "sysctl wrong attach_type",
47 .insns = {
48 BPF_MOV64_IMM(BPF_REG_0, 1),
49 BPF_EXIT_INSN(),
51 .attach_type = 0,
52 .sysctl = "kernel/ostype",
53 .open_flags = O_RDONLY,
54 .result = ATTACH_REJECT,
57 .descr = "sysctl:read allow all",
58 .insns = {
59 BPF_MOV64_IMM(BPF_REG_0, 1),
60 BPF_EXIT_INSN(),
62 .attach_type = BPF_CGROUP_SYSCTL,
63 .sysctl = "kernel/ostype",
64 .open_flags = O_RDONLY,
65 .result = SUCCESS,
68 .descr = "sysctl:read deny all",
69 .insns = {
70 BPF_MOV64_IMM(BPF_REG_0, 0),
71 BPF_EXIT_INSN(),
73 .attach_type = BPF_CGROUP_SYSCTL,
74 .sysctl = "kernel/ostype",
75 .open_flags = O_RDONLY,
76 .result = OP_EPERM,
79 .descr = "ctx:write sysctl:read read ok",
80 .insns = {
81 /* If (write) */
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),
86 /* return DENY; */
87 BPF_MOV64_IMM(BPF_REG_0, 0),
88 BPF_JMP_A(1),
90 /* else return ALLOW; */
91 BPF_MOV64_IMM(BPF_REG_0, 1),
92 BPF_EXIT_INSN(),
94 .attach_type = BPF_CGROUP_SYSCTL,
95 .sysctl = "kernel/ostype",
96 .open_flags = O_RDONLY,
97 .result = SUCCESS,
100 .descr = "ctx:write sysctl:write read ok",
101 .insns = {
102 /* If (write) */
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),
107 /* return DENY; */
108 BPF_MOV64_IMM(BPF_REG_0, 0),
109 BPF_JMP_A(1),
111 /* else return ALLOW; */
112 BPF_MOV64_IMM(BPF_REG_0, 1),
113 BPF_EXIT_INSN(),
115 .attach_type = BPF_CGROUP_SYSCTL,
116 .sysctl = "kernel/domainname",
117 .open_flags = O_WRONLY,
118 .newval = "(none)", /* same as default, should fail anyway */
119 .result = OP_EPERM,
122 .descr = "ctx:write sysctl:read write reject",
123 .insns = {
124 /* write = X */
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(),
131 .attach_type = BPF_CGROUP_SYSCTL,
132 .sysctl = "kernel/ostype",
133 .open_flags = O_RDONLY,
134 .result = LOAD_REJECT,
137 .descr = "ctx:file_pos sysctl:read read ok",
138 .insns = {
139 /* If (file_pos == X) */
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),
144 /* return ALLOW; */
145 BPF_MOV64_IMM(BPF_REG_0, 1),
146 BPF_JMP_A(1),
148 /* else return DENY; */
149 BPF_MOV64_IMM(BPF_REG_0, 0),
150 BPF_EXIT_INSN(),
152 .attach_type = BPF_CGROUP_SYSCTL,
153 .sysctl = "kernel/ostype",
154 .open_flags = O_RDONLY,
155 .result = SUCCESS,
158 .descr = "ctx:file_pos sysctl:read read ok narrow",
159 .insns = {
160 /* If (file_pos == X) */
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),
165 /* return ALLOW; */
166 BPF_MOV64_IMM(BPF_REG_0, 1),
167 BPF_JMP_A(1),
169 /* else return DENY; */
170 BPF_MOV64_IMM(BPF_REG_0, 0),
171 BPF_EXIT_INSN(),
173 .attach_type = BPF_CGROUP_SYSCTL,
174 .sysctl = "kernel/ostype",
175 .open_flags = O_RDONLY,
176 .result = SUCCESS,
179 .descr = "ctx:file_pos sysctl:read write ok",
180 .insns = {
181 /* file_pos = X */
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(),
188 .attach_type = BPF_CGROUP_SYSCTL,
189 .sysctl = "kernel/ostype",
190 .open_flags = O_RDONLY,
191 .oldval = "nux\n",
192 .result = SUCCESS,
195 .descr = "sysctl_get_name sysctl_value:base ok",
196 .insns = {
197 /* sysctl_get_name arg2 (buf) */
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),
203 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
205 /* sysctl_get_name arg3 (buf_len) */
206 BPF_MOV64_IMM(BPF_REG_3, 8),
208 /* sysctl_get_name arg4 (flags) */
209 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
211 /* sysctl_get_name(ctx, buf, buf_len, flags) */
212 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
214 /* if (ret == expected && */
215 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6),
216 /* buf == "tcp_mem\0") */
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),
221 /* return ALLOW; */
222 BPF_MOV64_IMM(BPF_REG_0, 1),
223 BPF_JMP_A(1),
225 /* else return DENY; */
226 BPF_MOV64_IMM(BPF_REG_0, 0),
227 BPF_EXIT_INSN(),
229 .attach_type = BPF_CGROUP_SYSCTL,
230 .sysctl = "net/ipv4/tcp_mem",
231 .open_flags = O_RDONLY,
232 .result = SUCCESS,
235 .descr = "sysctl_get_name sysctl_value:base E2BIG truncated",
236 .insns = {
237 /* sysctl_get_name arg2 (buf) */
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),
243 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
245 /* sysctl_get_name arg3 (buf_len) too small */
246 BPF_MOV64_IMM(BPF_REG_3, 7),
248 /* sysctl_get_name arg4 (flags) */
249 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
251 /* sysctl_get_name(ctx, buf, buf_len, flags) */
252 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
254 /* if (ret == expected && */
255 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
257 /* buf[0:7] == "tcp_me\0") */
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),
262 /* return ALLOW; */
263 BPF_MOV64_IMM(BPF_REG_0, 1),
264 BPF_JMP_A(1),
266 /* else return DENY; */
267 BPF_MOV64_IMM(BPF_REG_0, 0),
268 BPF_EXIT_INSN(),
270 .attach_type = BPF_CGROUP_SYSCTL,
271 .sysctl = "net/ipv4/tcp_mem",
272 .open_flags = O_RDONLY,
273 .result = SUCCESS,
276 .descr = "sysctl_get_name sysctl:full ok",
277 .insns = {
278 /* sysctl_get_name arg2 (buf) */
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),
286 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
288 /* sysctl_get_name arg3 (buf_len) */
289 BPF_MOV64_IMM(BPF_REG_3, 17),
291 /* sysctl_get_name arg4 (flags) */
292 BPF_MOV64_IMM(BPF_REG_4, 0),
294 /* sysctl_get_name(ctx, buf, buf_len, flags) */
295 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
297 /* if (ret == expected && */
298 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14),
300 /* buf[0:8] == "net/ipv4" && */
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),
305 /* buf[8:16] == "/tcp_mem" && */
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),
310 /* buf[16:24] == "\0") */
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),
315 /* return ALLOW; */
316 BPF_MOV64_IMM(BPF_REG_0, 1),
317 BPF_JMP_A(1),
319 /* else return DENY; */
320 BPF_MOV64_IMM(BPF_REG_0, 0),
321 BPF_EXIT_INSN(),
323 .attach_type = BPF_CGROUP_SYSCTL,
324 .sysctl = "net/ipv4/tcp_mem",
325 .open_flags = O_RDONLY,
326 .result = SUCCESS,
329 .descr = "sysctl_get_name sysctl:full E2BIG truncated",
330 .insns = {
331 /* sysctl_get_name arg2 (buf) */
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),
338 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
340 /* sysctl_get_name arg3 (buf_len) */
341 BPF_MOV64_IMM(BPF_REG_3, 16),
343 /* sysctl_get_name arg4 (flags) */
344 BPF_MOV64_IMM(BPF_REG_4, 0),
346 /* sysctl_get_name(ctx, buf, buf_len, flags) */
347 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
349 /* if (ret == expected && */
350 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10),
352 /* buf[0:8] == "net/ipv4" && */
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),
357 /* buf[8:16] == "/tcp_me\0") */
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),
362 /* return ALLOW; */
363 BPF_MOV64_IMM(BPF_REG_0, 1),
364 BPF_JMP_A(1),
366 /* else return DENY; */
367 BPF_MOV64_IMM(BPF_REG_0, 0),
368 BPF_EXIT_INSN(),
370 .attach_type = BPF_CGROUP_SYSCTL,
371 .sysctl = "net/ipv4/tcp_mem",
372 .open_flags = O_RDONLY,
373 .result = SUCCESS,
376 .descr = "sysctl_get_name sysctl:full E2BIG truncated small",
377 .insns = {
378 /* sysctl_get_name arg2 (buf) */
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),
384 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
386 /* sysctl_get_name arg3 (buf_len) */
387 BPF_MOV64_IMM(BPF_REG_3, 7),
389 /* sysctl_get_name arg4 (flags) */
390 BPF_MOV64_IMM(BPF_REG_4, 0),
392 /* sysctl_get_name(ctx, buf, buf_len, flags) */
393 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
395 /* if (ret == expected && */
396 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
398 /* buf[0:8] == "net/ip\0") */
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),
403 /* return ALLOW; */
404 BPF_MOV64_IMM(BPF_REG_0, 1),
405 BPF_JMP_A(1),
407 /* else return DENY; */
408 BPF_MOV64_IMM(BPF_REG_0, 0),
409 BPF_EXIT_INSN(),
411 .attach_type = BPF_CGROUP_SYSCTL,
412 .sysctl = "net/ipv4/tcp_mem",
413 .open_flags = O_RDONLY,
414 .result = SUCCESS,
417 .descr = "sysctl_get_current_value sysctl:read ok, gt",
418 .insns = {
419 /* sysctl_get_current_value arg2 (buf) */
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),
424 /* sysctl_get_current_value arg3 (buf_len) */
425 BPF_MOV64_IMM(BPF_REG_3, 8),
427 /* sysctl_get_current_value(ctx, buf, buf_len) */
428 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
430 /* if (ret == expected && */
431 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
433 /* buf[0:6] == "Linux\n\0") */
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),
438 /* return ALLOW; */
439 BPF_MOV64_IMM(BPF_REG_0, 1),
440 BPF_JMP_A(1),
442 /* else return DENY; */
443 BPF_MOV64_IMM(BPF_REG_0, 0),
444 BPF_EXIT_INSN(),
446 .attach_type = BPF_CGROUP_SYSCTL,
447 .sysctl = "kernel/ostype",
448 .open_flags = O_RDONLY,
449 .result = SUCCESS,
452 .descr = "sysctl_get_current_value sysctl:read ok, eq",
453 .insns = {
454 /* sysctl_get_current_value arg2 (buf) */
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),
460 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
462 /* sysctl_get_current_value arg3 (buf_len) */
463 BPF_MOV64_IMM(BPF_REG_3, 7),
465 /* sysctl_get_current_value(ctx, buf, buf_len) */
466 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
468 /* if (ret == expected && */
469 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
471 /* buf[0:6] == "Linux\n\0") */
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),
476 /* return ALLOW; */
477 BPF_MOV64_IMM(BPF_REG_0, 1),
478 BPF_JMP_A(1),
480 /* else return DENY; */
481 BPF_MOV64_IMM(BPF_REG_0, 0),
482 BPF_EXIT_INSN(),
484 .attach_type = BPF_CGROUP_SYSCTL,
485 .sysctl = "kernel/ostype",
486 .open_flags = O_RDONLY,
487 .result = SUCCESS,
490 .descr = "sysctl_get_current_value sysctl:read E2BIG truncated",
491 .insns = {
492 /* sysctl_get_current_value arg2 (buf) */
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),
498 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
500 /* sysctl_get_current_value arg3 (buf_len) */
501 BPF_MOV64_IMM(BPF_REG_3, 6),
503 /* sysctl_get_current_value(ctx, buf, buf_len) */
504 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
506 /* if (ret == expected && */
507 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
509 /* buf[0:6] == "Linux\0") */
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),
514 /* return ALLOW; */
515 BPF_MOV64_IMM(BPF_REG_0, 1),
516 BPF_JMP_A(1),
518 /* else return DENY; */
519 BPF_MOV64_IMM(BPF_REG_0, 0),
520 BPF_EXIT_INSN(),
522 .attach_type = BPF_CGROUP_SYSCTL,
523 .sysctl = "kernel/ostype",
524 .open_flags = O_RDONLY,
525 .result = SUCCESS,
528 .descr = "sysctl_get_current_value sysctl:read EINVAL",
529 .insns = {
530 /* sysctl_get_current_value arg2 (buf) */
531 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
532 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
534 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
536 /* sysctl_get_current_value arg3 (buf_len) */
537 BPF_MOV64_IMM(BPF_REG_3, 8),
539 /* sysctl_get_current_value(ctx, buf, buf_len) */
540 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
542 /* if (ret == expected && */
543 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4),
545 /* buf[0:8] is NUL-filled) */
546 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
547 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2),
549 /* return DENY; */
550 BPF_MOV64_IMM(BPF_REG_0, 0),
551 BPF_JMP_A(1),
553 /* else return ALLOW; */
554 BPF_MOV64_IMM(BPF_REG_0, 1),
555 BPF_EXIT_INSN(),
557 .attach_type = BPF_CGROUP_SYSCTL,
558 .sysctl = "net/ipv6/conf/lo/stable_secret", /* -EIO */
559 .open_flags = O_RDONLY,
560 .result = OP_EPERM,
563 .descr = "sysctl_get_current_value sysctl:write ok",
564 .fixup_value_insn = 6,
565 .insns = {
566 /* sysctl_get_current_value arg2 (buf) */
567 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
568 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
570 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
572 /* sysctl_get_current_value arg3 (buf_len) */
573 BPF_MOV64_IMM(BPF_REG_3, 8),
575 /* sysctl_get_current_value(ctx, buf, buf_len) */
576 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
578 /* if (ret == expected && */
579 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6),
581 /* buf[0:4] == expected) */
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),
586 /* return DENY; */
587 BPF_MOV64_IMM(BPF_REG_0, 0),
588 BPF_JMP_A(1),
590 /* else return ALLOW; */
591 BPF_MOV64_IMM(BPF_REG_0, 1),
592 BPF_EXIT_INSN(),
594 .attach_type = BPF_CGROUP_SYSCTL,
595 .sysctl = "net/ipv4/route/mtu_expires",
596 .open_flags = O_WRONLY,
597 .newval = "600", /* same as default, should fail anyway */
598 .result = OP_EPERM,
601 .descr = "sysctl_get_new_value sysctl:read EINVAL",
602 .insns = {
603 /* sysctl_get_new_value arg2 (buf) */
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),
609 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
611 /* sysctl_get_new_value arg3 (buf_len) */
612 BPF_MOV64_IMM(BPF_REG_3, 8),
614 /* sysctl_get_new_value(ctx, buf, buf_len) */
615 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
617 /* if (ret == expected) */
618 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
620 /* return ALLOW; */
621 BPF_MOV64_IMM(BPF_REG_0, 1),
622 BPF_JMP_A(1),
624 /* else return DENY; */
625 BPF_MOV64_IMM(BPF_REG_0, 0),
626 BPF_EXIT_INSN(),
628 .attach_type = BPF_CGROUP_SYSCTL,
629 .sysctl = "net/ipv4/tcp_mem",
630 .open_flags = O_RDONLY,
631 .result = SUCCESS,
634 .descr = "sysctl_get_new_value sysctl:write ok",
635 .insns = {
636 /* sysctl_get_new_value arg2 (buf) */
637 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
638 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
640 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
642 /* sysctl_get_new_value arg3 (buf_len) */
643 BPF_MOV64_IMM(BPF_REG_3, 4),
645 /* sysctl_get_new_value(ctx, buf, buf_len) */
646 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
648 /* if (ret == expected && */
649 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
651 /* buf[0:4] == "606\0") */
652 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
653 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0x00363036, 2),
655 /* return DENY; */
656 BPF_MOV64_IMM(BPF_REG_0, 0),
657 BPF_JMP_A(1),
659 /* else return ALLOW; */
660 BPF_MOV64_IMM(BPF_REG_0, 1),
661 BPF_EXIT_INSN(),
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,
670 .descr = "sysctl_get_new_value sysctl:write ok long",
671 .insns = {
672 /* sysctl_get_new_value arg2 (buf) */
673 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
674 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
676 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
678 /* sysctl_get_new_value arg3 (buf_len) */
679 BPF_MOV64_IMM(BPF_REG_3, 24),
681 /* sysctl_get_new_value(ctx, buf, buf_len) */
682 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
684 /* if (ret == expected && */
685 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14),
687 /* buf[0:8] == "3000000 " && */
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),
692 /* buf[8:16] == "4000000 " && */
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),
697 /* buf[16:24] == "6000000\0") */
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),
702 /* return DENY; */
703 BPF_MOV64_IMM(BPF_REG_0, 0),
704 BPF_JMP_A(1),
706 /* else return ALLOW; */
707 BPF_MOV64_IMM(BPF_REG_0, 1),
708 BPF_EXIT_INSN(),
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,
717 .descr = "sysctl_get_new_value sysctl:write E2BIG",
718 .insns = {
719 /* sysctl_get_new_value arg2 (buf) */
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),
725 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
727 /* sysctl_get_new_value arg3 (buf_len) */
728 BPF_MOV64_IMM(BPF_REG_3, 3),
730 /* sysctl_get_new_value(ctx, buf, buf_len) */
731 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
733 /* if (ret == expected && */
734 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4),
736 /* buf[0:3] == "60\0") */
737 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
738 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0x003036, 2),
740 /* return DENY; */
741 BPF_MOV64_IMM(BPF_REG_0, 0),
742 BPF_JMP_A(1),
744 /* else return ALLOW; */
745 BPF_MOV64_IMM(BPF_REG_0, 1),
746 BPF_EXIT_INSN(),
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,
755 .descr = "sysctl_set_new_value sysctl:read EINVAL",
756 .insns = {
757 /* sysctl_set_new_value arg2 (buf) */
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),
763 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
765 /* sysctl_set_new_value arg3 (buf_len) */
766 BPF_MOV64_IMM(BPF_REG_3, 3),
768 /* sysctl_set_new_value(ctx, buf, buf_len) */
769 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
771 /* if (ret == expected) */
772 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
774 /* return ALLOW; */
775 BPF_MOV64_IMM(BPF_REG_0, 1),
776 BPF_JMP_A(1),
778 /* else return DENY; */
779 BPF_MOV64_IMM(BPF_REG_0, 0),
780 BPF_EXIT_INSN(),
782 .attach_type = BPF_CGROUP_SYSCTL,
783 .sysctl = "net/ipv4/route/mtu_expires",
784 .open_flags = O_RDONLY,
785 .result = SUCCESS,
788 .descr = "sysctl_set_new_value sysctl:write ok",
789 .fixup_value_insn = 2,
790 .insns = {
791 /* sysctl_set_new_value arg2 (buf) */
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),
797 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
799 /* sysctl_set_new_value arg3 (buf_len) */
800 BPF_MOV64_IMM(BPF_REG_3, 3),
802 /* sysctl_set_new_value(ctx, buf, buf_len) */
803 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
805 /* if (ret == expected) */
806 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
808 /* return ALLOW; */
809 BPF_MOV64_IMM(BPF_REG_0, 1),
810 BPF_JMP_A(1),
812 /* else return DENY; */
813 BPF_MOV64_IMM(BPF_REG_0, 0),
814 BPF_EXIT_INSN(),
816 .attach_type = BPF_CGROUP_SYSCTL,
817 .sysctl = "net/ipv4/route/mtu_expires",
818 .open_flags = O_WRONLY,
819 .newval = "606",
820 .result = SUCCESS,
823 "bpf_strtoul one number string",
824 .insns = {
825 /* arg1 (buf) */
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),
831 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
833 /* arg2 (buf_len) */
834 BPF_MOV64_IMM(BPF_REG_2, 4),
836 /* arg3 (flags) */
837 BPF_MOV64_IMM(BPF_REG_3, 0),
839 /* arg4 (res) */
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),
844 BPF_EMIT_CALL(BPF_FUNC_strtoul),
846 /* if (ret == expected && */
847 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
848 /* res == expected) */
849 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
850 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 2),
852 /* return ALLOW; */
853 BPF_MOV64_IMM(BPF_REG_0, 1),
854 BPF_JMP_A(1),
856 /* else return DENY; */
857 BPF_MOV64_IMM(BPF_REG_0, 0),
858 BPF_EXIT_INSN(),
860 .attach_type = BPF_CGROUP_SYSCTL,
861 .sysctl = "net/ipv4/route/mtu_expires",
862 .open_flags = O_RDONLY,
863 .result = SUCCESS,
866 "bpf_strtoul multi number string",
867 .insns = {
868 /* arg1 (buf) */
869 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
870 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
871 /* "600 602\0" */
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),
876 /* arg2 (buf_len) */
877 BPF_MOV64_IMM(BPF_REG_2, 8),
879 /* arg3 (flags) */
880 BPF_MOV64_IMM(BPF_REG_3, 0),
882 /* arg4 (res) */
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),
887 BPF_EMIT_CALL(BPF_FUNC_strtoul),
889 /* if (ret == expected && */
890 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18),
891 /* res == expected) */
892 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
893 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 16),
895 /* arg1 (buf) */
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),
901 /* arg2 (buf_len) */
902 BPF_MOV64_IMM(BPF_REG_2, 8),
903 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0),
905 /* arg3 (flags) */
906 BPF_MOV64_IMM(BPF_REG_3, 0),
908 /* arg4 (res) */
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),
913 BPF_EMIT_CALL(BPF_FUNC_strtoul),
915 /* if (ret == expected && */
916 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
917 /* res == expected) */
918 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
919 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 602, 2),
921 /* return ALLOW; */
922 BPF_MOV64_IMM(BPF_REG_0, 1),
923 BPF_JMP_A(1),
925 /* else return DENY; */
926 BPF_MOV64_IMM(BPF_REG_0, 0),
927 BPF_EXIT_INSN(),
929 .attach_type = BPF_CGROUP_SYSCTL,
930 .sysctl = "net/ipv4/tcp_mem",
931 .open_flags = O_RDONLY,
932 .result = SUCCESS,
935 "bpf_strtoul buf_len = 0, reject",
936 .insns = {
937 /* arg1 (buf) */
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),
943 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
945 /* arg2 (buf_len) */
946 BPF_MOV64_IMM(BPF_REG_2, 0),
948 /* arg3 (flags) */
949 BPF_MOV64_IMM(BPF_REG_3, 0),
951 /* arg4 (res) */
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),
956 BPF_EMIT_CALL(BPF_FUNC_strtoul),
958 BPF_MOV64_IMM(BPF_REG_0, 1),
959 BPF_EXIT_INSN(),
961 .attach_type = BPF_CGROUP_SYSCTL,
962 .sysctl = "net/ipv4/route/mtu_expires",
963 .open_flags = O_RDONLY,
964 .result = LOAD_REJECT,
967 "bpf_strtoul supported base, ok",
968 .insns = {
969 /* arg1 (buf) */
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),
975 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
977 /* arg2 (buf_len) */
978 BPF_MOV64_IMM(BPF_REG_2, 4),
980 /* arg3 (flags) */
981 BPF_MOV64_IMM(BPF_REG_3, 8),
983 /* arg4 (res) */
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),
988 BPF_EMIT_CALL(BPF_FUNC_strtoul),
990 /* if (ret == expected && */
991 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
992 /* res == expected) */
993 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
994 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 63, 2),
996 /* return ALLOW; */
997 BPF_MOV64_IMM(BPF_REG_0, 1),
998 BPF_JMP_A(1),
1000 /* else return DENY; */
1001 BPF_MOV64_IMM(BPF_REG_0, 0),
1002 BPF_EXIT_INSN(),
1004 .attach_type = BPF_CGROUP_SYSCTL,
1005 .sysctl = "net/ipv4/route/mtu_expires",
1006 .open_flags = O_RDONLY,
1007 .result = SUCCESS,
1010 "bpf_strtoul unsupported base, EINVAL",
1011 .insns = {
1012 /* arg1 (buf) */
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),
1018 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1020 /* arg2 (buf_len) */
1021 BPF_MOV64_IMM(BPF_REG_2, 4),
1023 /* arg3 (flags) */
1024 BPF_MOV64_IMM(BPF_REG_3, 3),
1026 /* arg4 (res) */
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),
1031 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1033 /* if (ret == expected) */
1034 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1036 /* return ALLOW; */
1037 BPF_MOV64_IMM(BPF_REG_0, 1),
1038 BPF_JMP_A(1),
1040 /* else return DENY; */
1041 BPF_MOV64_IMM(BPF_REG_0, 0),
1042 BPF_EXIT_INSN(),
1044 .attach_type = BPF_CGROUP_SYSCTL,
1045 .sysctl = "net/ipv4/route/mtu_expires",
1046 .open_flags = O_RDONLY,
1047 .result = SUCCESS,
1050 "bpf_strtoul buf with spaces only, EINVAL",
1051 .insns = {
1052 /* arg1 (buf) */
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),
1058 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1060 /* arg2 (buf_len) */
1061 BPF_MOV64_IMM(BPF_REG_2, 4),
1063 /* arg3 (flags) */
1064 BPF_MOV64_IMM(BPF_REG_3, 0),
1066 /* arg4 (res) */
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),
1071 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1073 /* if (ret == expected) */
1074 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1076 /* return ALLOW; */
1077 BPF_MOV64_IMM(BPF_REG_0, 1),
1078 BPF_JMP_A(1),
1080 /* else return DENY; */
1081 BPF_MOV64_IMM(BPF_REG_0, 0),
1082 BPF_EXIT_INSN(),
1084 .attach_type = BPF_CGROUP_SYSCTL,
1085 .sysctl = "net/ipv4/route/mtu_expires",
1086 .open_flags = O_RDONLY,
1087 .result = SUCCESS,
1090 "bpf_strtoul negative number, EINVAL",
1091 .insns = {
1092 /* arg1 (buf) */
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), /* " -6\0" */
1096 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1098 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1100 /* arg2 (buf_len) */
1101 BPF_MOV64_IMM(BPF_REG_2, 4),
1103 /* arg3 (flags) */
1104 BPF_MOV64_IMM(BPF_REG_3, 0),
1106 /* arg4 (res) */
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),
1111 BPF_EMIT_CALL(BPF_FUNC_strtoul),
1113 /* if (ret == expected) */
1114 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1116 /* return ALLOW; */
1117 BPF_MOV64_IMM(BPF_REG_0, 1),
1118 BPF_JMP_A(1),
1120 /* else return DENY; */
1121 BPF_MOV64_IMM(BPF_REG_0, 0),
1122 BPF_EXIT_INSN(),
1124 .attach_type = BPF_CGROUP_SYSCTL,
1125 .sysctl = "net/ipv4/route/mtu_expires",
1126 .open_flags = O_RDONLY,
1127 .result = SUCCESS,
1130 "bpf_strtol negative number, ok",
1131 .insns = {
1132 /* arg1 (buf) */
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), /* " -6\0" */
1136 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1138 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1140 /* arg2 (buf_len) */
1141 BPF_MOV64_IMM(BPF_REG_2, 4),
1143 /* arg3 (flags) */
1144 BPF_MOV64_IMM(BPF_REG_3, 10),
1146 /* arg4 (res) */
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),
1151 BPF_EMIT_CALL(BPF_FUNC_strtol),
1153 /* if (ret == expected && */
1154 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1155 /* res == expected) */
1156 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1157 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -6, 2),
1159 /* return ALLOW; */
1160 BPF_MOV64_IMM(BPF_REG_0, 1),
1161 BPF_JMP_A(1),
1163 /* else return DENY; */
1164 BPF_MOV64_IMM(BPF_REG_0, 0),
1165 BPF_EXIT_INSN(),
1167 .attach_type = BPF_CGROUP_SYSCTL,
1168 .sysctl = "net/ipv4/route/mtu_expires",
1169 .open_flags = O_RDONLY,
1170 .result = SUCCESS,
1173 "bpf_strtol hex number, ok",
1174 .insns = {
1175 /* arg1 (buf) */
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), /* "0xfe" */
1179 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1181 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1183 /* arg2 (buf_len) */
1184 BPF_MOV64_IMM(BPF_REG_2, 4),
1186 /* arg3 (flags) */
1187 BPF_MOV64_IMM(BPF_REG_3, 0),
1189 /* arg4 (res) */
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),
1194 BPF_EMIT_CALL(BPF_FUNC_strtol),
1196 /* if (ret == expected && */
1197 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
1198 /* res == expected) */
1199 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1200 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 254, 2),
1202 /* return ALLOW; */
1203 BPF_MOV64_IMM(BPF_REG_0, 1),
1204 BPF_JMP_A(1),
1206 /* else return DENY; */
1207 BPF_MOV64_IMM(BPF_REG_0, 0),
1208 BPF_EXIT_INSN(),
1210 .attach_type = BPF_CGROUP_SYSCTL,
1211 .sysctl = "net/ipv4/route/mtu_expires",
1212 .open_flags = O_RDONLY,
1213 .result = SUCCESS,
1216 "bpf_strtol max long",
1217 .insns = {
1218 /* arg1 (buf) 9223372036854775807 */
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),
1228 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1230 /* arg2 (buf_len) */
1231 BPF_MOV64_IMM(BPF_REG_2, 19),
1233 /* arg3 (flags) */
1234 BPF_MOV64_IMM(BPF_REG_3, 0),
1236 /* arg4 (res) */
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),
1241 BPF_EMIT_CALL(BPF_FUNC_strtol),
1243 /* if (ret == expected && */
1244 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 19, 6),
1245 /* res == expected) */
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),
1250 /* return ALLOW; */
1251 BPF_MOV64_IMM(BPF_REG_0, 1),
1252 BPF_JMP_A(1),
1254 /* else return DENY; */
1255 BPF_MOV64_IMM(BPF_REG_0, 0),
1256 BPF_EXIT_INSN(),
1258 .attach_type = BPF_CGROUP_SYSCTL,
1259 .sysctl = "net/ipv4/route/mtu_expires",
1260 .open_flags = O_RDONLY,
1261 .result = SUCCESS,
1264 "bpf_strtol overflow, ERANGE",
1265 .insns = {
1266 /* arg1 (buf) 9223372036854775808 */
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),
1276 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1278 /* arg2 (buf_len) */
1279 BPF_MOV64_IMM(BPF_REG_2, 19),
1281 /* arg3 (flags) */
1282 BPF_MOV64_IMM(BPF_REG_3, 0),
1284 /* arg4 (res) */
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),
1289 BPF_EMIT_CALL(BPF_FUNC_strtol),
1291 /* if (ret == expected) */
1292 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2),
1294 /* return ALLOW; */
1295 BPF_MOV64_IMM(BPF_REG_0, 1),
1296 BPF_JMP_A(1),
1298 /* else return DENY; */
1299 BPF_MOV64_IMM(BPF_REG_0, 0),
1300 BPF_EXIT_INSN(),
1302 .attach_type = BPF_CGROUP_SYSCTL,
1303 .sysctl = "net/ipv4/route/mtu_expires",
1304 .open_flags = O_RDONLY,
1305 .result = SUCCESS,
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,
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,
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,
1334 static size_t probe_prog_length(const struct bpf_insn *fp)
1336 size_t len;
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;
1344 static int fixup_sysctl_value(const char *buf, size_t buf_len,
1345 struct bpf_insn *prog, size_t insn_num)
1347 uint32_t value_num = 0;
1348 uint8_t c, i;
1350 if (buf_len > sizeof(value_num)) {
1351 log_err("Value is too big (%zd) to use in fixup", buf_len);
1352 return -1;
1355 for (i = 0; i < buf_len; ++i) {
1356 c = buf[i];
1357 value_num |= (c << i * 8);
1360 prog[insn_num].imm = value_num;
1362 return 0;
1365 static int load_sysctl_prog_insns(struct sysctl_test *test,
1366 const char *sysctl_path)
1368 struct bpf_insn *prog = test->insns;
1369 struct bpf_load_program_attr attr;
1370 int ret;
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";
1378 if (test->fixup_value_insn) {
1379 char buf[128];
1380 ssize_t len;
1381 int fd;
1383 fd = open(sysctl_path, O_RDONLY | O_CLOEXEC);
1384 if (fd < 0) {
1385 log_err("open(%s) failed", sysctl_path);
1386 return -1;
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;
1394 close(fd);
1395 if (fixup_sysctl_value(buf, len, prog, test->fixup_value_insn))
1396 return -1;
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);
1405 return ret;
1408 static int load_sysctl_prog_file(struct sysctl_test *test)
1410 struct bpf_prog_load_attr attr;
1411 struct bpf_object *obj;
1412 int prog_fd;
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;
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;
1425 return prog_fd;
1428 static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path)
1430 return test->prog_file
1431 ? load_sysctl_prog_file(test)
1432 : load_sysctl_prog_insns(test, sysctl_path);
1435 static int access_sysctl(const char *sysctl_path,
1436 const struct sysctl_test *test)
1438 int err = 0;
1439 int fd;
1441 fd = open(sysctl_path, test->open_flags | O_CLOEXEC);
1442 if (fd < 0)
1443 return fd;
1445 if (test->open_flags == O_RDONLY) {
1446 char buf[128];
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;
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;
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;
1467 goto out;
1468 err:
1469 err = -1;
1470 out:
1471 close(fd);
1472 return err;
1475 static int run_test_case(int cgfd, struct sysctl_test *test)
1477 enum bpf_attach_type atype = test->attach_type;
1478 char sysctl_path[128];
1479 int progfd = -1;
1480 int err = 0;
1482 printf("Test case: %s .. ", test->descr);
1484 snprintf(sysctl_path, sizeof(sysctl_path), "/proc/sys/%s",
1485 test->sysctl);
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;
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;
1502 if (access_sysctl(sysctl_path, test) == -1) {
1503 if (test->result == OP_EPERM && errno == EPERM)
1504 goto out;
1505 else
1506 goto err;
1509 if (test->result != SUCCESS) {
1510 log_err("Unexpected failure");
1511 goto err;
1514 goto out;
1515 err:
1516 err = -1;
1517 out:
1518 /* Detaching w/o checking return code: best effort attempt. */
1519 if (progfd != -1)
1520 bpf_prog_detach(cgfd, atype);
1521 close(progfd);
1522 printf("[%s]\n", err ? "FAIL" : "PASS");
1523 return err;
1526 static int run_tests(int cgfd)
1528 int passes = 0;
1529 int fails = 0;
1530 int i;
1532 for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1533 if (run_test_case(cgfd, &tests[i]))
1534 ++fails;
1535 else
1536 ++passes;
1538 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1539 return fails ? -1 : 0;
1542 int main(int argc, char **argv)
1544 int cgfd = -1;
1545 int err = 0;
1547 if (setup_cgroup_environment())
1548 goto err;
1550 cgfd = create_and_get_cgroup(CG_PATH);
1551 if (cgfd < 0)
1552 goto err;
1554 if (join_cgroup(CG_PATH))
1555 goto err;
1557 if (run_tests(cgfd))
1558 goto err;
1560 goto out;
1561 err:
1562 err = -1;
1563 out:
1564 close(cgfd);
1565 cleanup_cgroup_environment();
1566 return err;