1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019 Facebook
11 #include <linux/filter.h>
14 #include <bpf/libbpf.h>
16 #include "bpf_endian.h"
17 #include "bpf_rlimit.h"
19 #include "cgroup_helpers.h"
21 #define CG_PATH "/foo"
23 #define FIXUP_SYSCTL_VALUE 0
25 char bpf_log_buf
[BPF_LOG_BUF_SIZE
];
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
;
46 static struct sysctl_test tests
[] = {
48 .descr
= "sysctl wrong attach_type",
50 BPF_MOV64_IMM(BPF_REG_0
, 1),
54 .sysctl
= "kernel/ostype",
55 .open_flags
= O_RDONLY
,
56 .result
= ATTACH_REJECT
,
59 .descr
= "sysctl:read allow all",
61 BPF_MOV64_IMM(BPF_REG_0
, 1),
64 .attach_type
= BPF_CGROUP_SYSCTL
,
65 .sysctl
= "kernel/ostype",
66 .open_flags
= O_RDONLY
,
70 .descr
= "sysctl:read deny all",
72 BPF_MOV64_IMM(BPF_REG_0
, 0),
75 .attach_type
= BPF_CGROUP_SYSCTL
,
76 .sysctl
= "kernel/ostype",
77 .open_flags
= O_RDONLY
,
81 .descr
= "ctx:write sysctl:read read ok",
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),
89 BPF_MOV64_IMM(BPF_REG_0
, 0),
92 /* else return ALLOW; */
93 BPF_MOV64_IMM(BPF_REG_0
, 1),
96 .attach_type
= BPF_CGROUP_SYSCTL
,
97 .sysctl
= "kernel/ostype",
98 .open_flags
= O_RDONLY
,
102 .descr
= "ctx:write sysctl:write read ok",
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),
110 BPF_MOV64_IMM(BPF_REG_0
, 0),
113 /* else return ALLOW; */
114 BPF_MOV64_IMM(BPF_REG_0
, 1),
117 .attach_type
= BPF_CGROUP_SYSCTL
,
118 .sysctl
= "kernel/domainname",
119 .open_flags
= O_WRONLY
,
120 .newval
= "(none)", /* same as default, should fail anyway */
124 .descr
= "ctx:write sysctl:write read ok narrow",
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
)),
131 BPF_LDX_MEM(BPF_H
, BPF_REG_7
, BPF_REG_1
,
132 offsetof(struct bpf_sysctl
, write
) + 2),
134 BPF_ALU64_IMM(BPF_AND
, BPF_REG_7
, 1),
136 BPF_MOV64_IMM(BPF_REG_0
, 1),
137 BPF_ALU64_REG(BPF_SUB
, BPF_REG_0
, BPF_REG_7
),
140 .attach_type
= BPF_CGROUP_SYSCTL
,
141 .sysctl
= "kernel/domainname",
142 .open_flags
= O_WRONLY
,
143 .newval
= "(none)", /* same as default, should fail anyway */
147 .descr
= "ctx:write sysctl:read write reject",
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),
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",
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),
170 BPF_MOV64_IMM(BPF_REG_0
, 1),
173 /* else return DENY; */
174 BPF_MOV64_IMM(BPF_REG_0
, 0),
177 .attach_type
= BPF_CGROUP_SYSCTL
,
178 .sysctl
= "kernel/ostype",
179 .open_flags
= O_RDONLY
,
184 .descr
= "ctx:file_pos sysctl:read read ok narrow",
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
)),
191 BPF_LDX_MEM(BPF_B
, BPF_REG_7
, BPF_REG_1
,
192 offsetof(struct bpf_sysctl
, file_pos
) + 3),
194 BPF_JMP_IMM(BPF_JNE
, BPF_REG_7
, 4, 2),
197 BPF_MOV64_IMM(BPF_REG_0
, 1),
200 /* else return DENY; */
201 BPF_MOV64_IMM(BPF_REG_0
, 0),
204 .attach_type
= BPF_CGROUP_SYSCTL
,
205 .sysctl
= "kernel/ostype",
206 .open_flags
= O_RDONLY
,
211 .descr
= "ctx:file_pos sysctl:read write ok",
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),
220 .attach_type
= BPF_CGROUP_SYSCTL
,
221 .sysctl
= "kernel/ostype",
222 .open_flags
= O_RDONLY
,
227 .descr
= "sysctl_get_name sysctl_value:base ok",
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),
255 BPF_MOV64_IMM(BPF_REG_0
, 1),
258 /* else return DENY; */
259 BPF_MOV64_IMM(BPF_REG_0
, 0),
262 .attach_type
= BPF_CGROUP_SYSCTL
,
263 .sysctl
= "net/ipv4/tcp_mem",
264 .open_flags
= O_RDONLY
,
268 .descr
= "sysctl_get_name sysctl_value:base E2BIG truncated",
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),
297 BPF_MOV64_IMM(BPF_REG_0
, 1),
300 /* else return DENY; */
301 BPF_MOV64_IMM(BPF_REG_0
, 0),
304 .attach_type
= BPF_CGROUP_SYSCTL
,
305 .sysctl
= "net/ipv4/tcp_mem",
306 .open_flags
= O_RDONLY
,
310 .descr
= "sysctl_get_name sysctl:full ok",
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),
352 BPF_MOV64_IMM(BPF_REG_0
, 1),
355 /* else return DENY; */
356 BPF_MOV64_IMM(BPF_REG_0
, 0),
359 .attach_type
= BPF_CGROUP_SYSCTL
,
360 .sysctl
= "net/ipv4/tcp_mem",
361 .open_flags
= O_RDONLY
,
365 .descr
= "sysctl_get_name sysctl:full E2BIG truncated",
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),
401 BPF_MOV64_IMM(BPF_REG_0
, 1),
404 /* else return DENY; */
405 BPF_MOV64_IMM(BPF_REG_0
, 0),
408 .attach_type
= BPF_CGROUP_SYSCTL
,
409 .sysctl
= "net/ipv4/tcp_mem",
410 .open_flags
= O_RDONLY
,
414 .descr
= "sysctl_get_name sysctl:full E2BIG truncated small",
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),
443 BPF_MOV64_IMM(BPF_REG_0
, 1),
446 /* else return DENY; */
447 BPF_MOV64_IMM(BPF_REG_0
, 0),
450 .attach_type
= BPF_CGROUP_SYSCTL
,
451 .sysctl
= "net/ipv4/tcp_mem",
452 .open_flags
= O_RDONLY
,
456 .descr
= "sysctl_get_current_value sysctl:read ok, gt",
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),
479 BPF_MOV64_IMM(BPF_REG_0
, 1),
482 /* else return DENY; */
483 BPF_MOV64_IMM(BPF_REG_0
, 0),
486 .attach_type
= BPF_CGROUP_SYSCTL
,
487 .sysctl
= "kernel/ostype",
488 .open_flags
= O_RDONLY
,
492 .descr
= "sysctl_get_current_value sysctl:read ok, eq",
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),
518 BPF_MOV64_IMM(BPF_REG_0
, 1),
521 /* else return DENY; */
522 BPF_MOV64_IMM(BPF_REG_0
, 0),
525 .attach_type
= BPF_CGROUP_SYSCTL
,
526 .sysctl
= "kernel/ostype",
527 .open_flags
= O_RDONLY
,
531 .descr
= "sysctl_get_current_value sysctl:read E2BIG truncated",
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),
557 BPF_MOV64_IMM(BPF_REG_0
, 1),
560 /* else return DENY; */
561 BPF_MOV64_IMM(BPF_REG_0
, 0),
564 .attach_type
= BPF_CGROUP_SYSCTL
,
565 .sysctl
= "kernel/ostype",
566 .open_flags
= O_RDONLY
,
570 .descr
= "sysctl_get_current_value sysctl:read EINVAL",
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),
592 BPF_MOV64_IMM(BPF_REG_0
, 0),
595 /* else return ALLOW; */
596 BPF_MOV64_IMM(BPF_REG_0
, 1),
599 .attach_type
= BPF_CGROUP_SYSCTL
,
600 .sysctl
= "net/ipv6/conf/lo/stable_secret", /* -EIO */
601 .open_flags
= O_RDONLY
,
605 .descr
= "sysctl_get_current_value sysctl:write ok",
606 .fixup_value_insn
= 6,
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),
629 BPF_MOV64_IMM(BPF_REG_0
, 0),
632 /* else return ALLOW; */
633 BPF_MOV64_IMM(BPF_REG_0
, 1),
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 */
643 .descr
= "sysctl_get_new_value sysctl:read EINVAL",
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),
663 BPF_MOV64_IMM(BPF_REG_0
, 1),
666 /* else return DENY; */
667 BPF_MOV64_IMM(BPF_REG_0
, 0),
670 .attach_type
= BPF_CGROUP_SYSCTL
,
671 .sysctl
= "net/ipv4/tcp_mem",
672 .open_flags
= O_RDONLY
,
676 .descr
= "sysctl_get_new_value sysctl:write ok",
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),
699 BPF_MOV64_IMM(BPF_REG_0
, 0),
702 /* else return ALLOW; */
703 BPF_MOV64_IMM(BPF_REG_0
, 1),
706 .attach_type
= BPF_CGROUP_SYSCTL
,
707 .sysctl
= "net/ipv4/route/mtu_expires",
708 .open_flags
= O_WRONLY
,
713 .descr
= "sysctl_get_new_value sysctl:write ok long",
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),
749 BPF_MOV64_IMM(BPF_REG_0
, 0),
752 /* else return ALLOW; */
753 BPF_MOV64_IMM(BPF_REG_0
, 1),
756 .attach_type
= BPF_CGROUP_SYSCTL
,
757 .sysctl
= "net/ipv4/tcp_mem",
758 .open_flags
= O_WRONLY
,
759 .newval
= "3000000 4000000 6000000",
763 .descr
= "sysctl_get_new_value sysctl:write E2BIG",
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),
788 BPF_MOV64_IMM(BPF_REG_0
, 0),
791 /* else return ALLOW; */
792 BPF_MOV64_IMM(BPF_REG_0
, 1),
795 .attach_type
= BPF_CGROUP_SYSCTL
,
796 .sysctl
= "net/ipv4/route/mtu_expires",
797 .open_flags
= O_WRONLY
,
802 .descr
= "sysctl_set_new_value sysctl:read EINVAL",
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),
823 BPF_MOV64_IMM(BPF_REG_0
, 1),
826 /* else return DENY; */
827 BPF_MOV64_IMM(BPF_REG_0
, 0),
830 .attach_type
= BPF_CGROUP_SYSCTL
,
831 .sysctl
= "net/ipv4/route/mtu_expires",
832 .open_flags
= O_RDONLY
,
836 .descr
= "sysctl_set_new_value sysctl:write ok",
837 .fixup_value_insn
= 2,
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),
857 BPF_MOV64_IMM(BPF_REG_0
, 1),
860 /* else return DENY; */
861 BPF_MOV64_IMM(BPF_REG_0
, 0),
864 .attach_type
= BPF_CGROUP_SYSCTL
,
865 .sysctl
= "net/ipv4/route/mtu_expires",
866 .open_flags
= O_WRONLY
,
871 "bpf_strtoul one number string",
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
),
883 BPF_MOV64_IMM(BPF_REG_2
, 4),
886 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
902 BPF_MOV64_IMM(BPF_REG_0
, 1),
905 /* else return DENY; */
906 BPF_MOV64_IMM(BPF_REG_0
, 0),
909 .attach_type
= BPF_CGROUP_SYSCTL
,
910 .sysctl
= "net/ipv4/route/mtu_expires",
911 .open_flags
= O_RDONLY
,
915 "bpf_strtoul multi number string",
918 BPF_MOV64_REG(BPF_REG_7
, BPF_REG_10
),
919 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_7
, -8),
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
),
927 BPF_MOV64_IMM(BPF_REG_2
, 8),
930 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
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
),
952 BPF_MOV64_IMM(BPF_REG_2
, 8),
953 BPF_ALU64_REG(BPF_SUB
, BPF_REG_2
, BPF_REG_0
),
956 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
972 BPF_MOV64_IMM(BPF_REG_0
, 1),
975 /* else return DENY; */
976 BPF_MOV64_IMM(BPF_REG_0
, 0),
979 .attach_type
= BPF_CGROUP_SYSCTL
,
980 .sysctl
= "net/ipv4/tcp_mem",
981 .open_flags
= O_RDONLY
,
985 "bpf_strtoul buf_len = 0, reject",
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
),
997 BPF_MOV64_IMM(BPF_REG_2
, 0),
1000 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
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",
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),
1033 BPF_MOV64_IMM(BPF_REG_3
, 8),
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),
1049 BPF_MOV64_IMM(BPF_REG_0
, 1),
1052 /* else return DENY; */
1053 BPF_MOV64_IMM(BPF_REG_0
, 0),
1056 .attach_type
= BPF_CGROUP_SYSCTL
,
1057 .sysctl
= "net/ipv4/route/mtu_expires",
1058 .open_flags
= O_RDONLY
,
1062 "bpf_strtoul unsupported base, EINVAL",
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),
1077 BPF_MOV64_IMM(BPF_REG_3
, 3),
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),
1090 BPF_MOV64_IMM(BPF_REG_0
, 1),
1093 /* else return DENY; */
1094 BPF_MOV64_IMM(BPF_REG_0
, 0),
1097 .attach_type
= BPF_CGROUP_SYSCTL
,
1098 .sysctl
= "net/ipv4/route/mtu_expires",
1099 .open_flags
= O_RDONLY
,
1103 "bpf_strtoul buf with spaces only, EINVAL",
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),
1118 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
1131 BPF_MOV64_IMM(BPF_REG_0
, 1),
1134 /* else return DENY; */
1135 BPF_MOV64_IMM(BPF_REG_0
, 0),
1138 .attach_type
= BPF_CGROUP_SYSCTL
,
1139 .sysctl
= "net/ipv4/route/mtu_expires",
1140 .open_flags
= O_RDONLY
,
1144 "bpf_strtoul negative number, EINVAL",
1147 BPF_MOV64_REG(BPF_REG_7
, BPF_REG_10
),
1148 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_7
, -8),
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),
1160 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
1173 BPF_MOV64_IMM(BPF_REG_0
, 1),
1176 /* else return DENY; */
1177 BPF_MOV64_IMM(BPF_REG_0
, 0),
1180 .attach_type
= BPF_CGROUP_SYSCTL
,
1181 .sysctl
= "net/ipv4/route/mtu_expires",
1182 .open_flags
= O_RDONLY
,
1186 "bpf_strtol negative number, ok",
1189 BPF_MOV64_REG(BPF_REG_7
, BPF_REG_10
),
1190 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_7
, -8),
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),
1202 BPF_MOV64_IMM(BPF_REG_3
, 10),
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),
1218 BPF_MOV64_IMM(BPF_REG_0
, 1),
1221 /* else return DENY; */
1222 BPF_MOV64_IMM(BPF_REG_0
, 0),
1225 .attach_type
= BPF_CGROUP_SYSCTL
,
1226 .sysctl
= "net/ipv4/route/mtu_expires",
1227 .open_flags
= O_RDONLY
,
1231 "bpf_strtol hex number, ok",
1234 BPF_MOV64_REG(BPF_REG_7
, BPF_REG_10
),
1235 BPF_ALU64_IMM(BPF_ADD
, BPF_REG_7
, -8),
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),
1247 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
1263 BPF_MOV64_IMM(BPF_REG_0
, 1),
1266 /* else return DENY; */
1267 BPF_MOV64_IMM(BPF_REG_0
, 0),
1270 .attach_type
= BPF_CGROUP_SYSCTL
,
1271 .sysctl
= "net/ipv4/route/mtu_expires",
1272 .open_flags
= O_RDONLY
,
1276 "bpf_strtol max long",
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),
1297 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
1314 BPF_MOV64_IMM(BPF_REG_0
, 1),
1317 /* else return DENY; */
1318 BPF_MOV64_IMM(BPF_REG_0
, 0),
1321 .attach_type
= BPF_CGROUP_SYSCTL
,
1322 .sysctl
= "net/ipv4/route/mtu_expires",
1323 .open_flags
= O_RDONLY
,
1327 "bpf_strtol overflow, ERANGE",
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),
1348 BPF_MOV64_IMM(BPF_REG_3
, 0),
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),
1361 BPF_MOV64_IMM(BPF_REG_0
, 1),
1364 /* else return DENY; */
1365 BPF_MOV64_IMM(BPF_REG_0
, 0),
1368 .attach_type
= BPF_CGROUP_SYSCTL
,
1369 .sysctl
= "net/ipv4/route/mtu_expires",
1370 .open_flags
= O_RDONLY
,
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",
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
,
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
,
1400 static size_t probe_prog_length(const struct bpf_insn
*fp
)
1404 for (len
= MAX_INSNS
- 1; len
> 0; --len
)
1405 if (fp
[len
].code
!= 0 || fp
[len
].imm
!= 0)
1410 static int fixup_sysctl_value(const char *buf
, size_t buf_len
,
1411 struct bpf_insn
*prog
, size_t insn_num
)
1414 uint8_t raw
[sizeof(uint64_t)];
1418 if (buf_len
> sizeof(value
)) {
1419 log_err("Value is too big (%zd) to use in fixup", buf_len
);
1422 if (prog
[insn_num
].code
!= (BPF_LD
| BPF_DW
| BPF_IMM
)) {
1423 log_err("Can fixup only BPF_LD_IMM64 insns");
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);
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
;
1441 memset(&attr
, 0, sizeof(struct bpf_load_program_attr
));
1442 attr
.prog_type
= BPF_PROG_TYPE_CGROUP_SYSCTL
;
1444 attr
.insns_cnt
= probe_prog_length(attr
.insns
);
1445 attr
.license
= "GPL";
1447 if (test
->fixup_value_insn
) {
1452 fd
= open(sysctl_path
, O_RDONLY
| O_CLOEXEC
);
1454 log_err("open(%s) failed", sysctl_path
);
1457 len
= read(fd
, buf
, sizeof(buf
));
1459 log_err("read(%s) failed", sysctl_path
);
1464 if (fixup_sysctl_value(buf
, len
, prog
, test
->fixup_value_insn
))
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
);
1477 static int load_sysctl_prog_file(struct sysctl_test
*test
)
1479 struct bpf_prog_load_attr attr
;
1480 struct bpf_object
*obj
;
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",
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
)
1510 fd
= open(sysctl_path
, test
->open_flags
| O_CLOEXEC
);
1514 if (test
->seek
&& lseek(fd
, test
->seek
, SEEK_SET
) == -1) {
1515 log_err("lseek(%d) failed", test
->seek
);
1519 if (test
->open_flags
== O_RDONLY
) {
1522 if (read(fd
, buf
, sizeof(buf
)) == -1)
1525 strncmp(buf
, test
->oldval
, strlen(test
->oldval
))) {
1526 log_err("Read value %s != %s", buf
, test
->oldval
);
1529 } else if (test
->open_flags
== O_WRONLY
) {
1530 if (!test
->newval
) {
1531 log_err("New value for sysctl is not set");
1534 if (write(fd
, test
->newval
, strlen(test
->newval
)) == -1)
1537 log_err("Unexpected sysctl access: neither read nor write");
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];
1556 printf("Test case: %s .. ", test
->descr
);
1558 snprintf(sysctl_path
, sizeof(sysctl_path
), "/proc/sys/%s",
1561 progfd
= load_sysctl_prog(test
, sysctl_path
);
1563 if (test
->result
== LOAD_REJECT
)
1569 if (bpf_prog_attach(progfd
, cgfd
, atype
, BPF_F_ALLOW_OVERRIDE
) == -1) {
1570 if (test
->result
== ATTACH_REJECT
)
1577 if (access_sysctl(sysctl_path
, test
) == -1) {
1578 if (test
->result
== OP_EPERM
&& errno
== EPERM
)
1584 if (test
->result
!= SUCCESS
) {
1585 log_err("Unexpected success");
1593 /* Detaching w/o checking return code: best effort attempt. */
1595 bpf_prog_detach(cgfd
, atype
);
1597 printf("[%s]\n", err
? "FAIL" : "PASS");
1601 static int run_tests(int cgfd
)
1607 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
) {
1608 if (run_test_case(cgfd
, &tests
[i
]))
1613 printf("Summary: %d PASSED, %d FAILED\n", passes
, fails
);
1614 return fails
? -1 : 0;
1617 int main(int argc
, char **argv
)
1622 if (setup_cgroup_environment())
1625 cgfd
= create_and_get_cgroup(CG_PATH
);
1629 if (join_cgroup(CG_PATH
))
1632 if (run_tests(cgfd
))
1640 cleanup_cgroup_environment();