1634 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2019 Facebook3 4#include <fcntl.h>5#include <stdint.h>6#include <stdio.h>7#include <stdlib.h>8#include <string.h>9#include <unistd.h>10 11#include <linux/filter.h>12 13#include <bpf/bpf.h>14#include <bpf/libbpf.h>15 16#include <bpf/bpf_endian.h>17#include "bpf_util.h"18#include "cgroup_helpers.h"19#include "testing_helpers.h"20 21#define CG_PATH "/foo"22#define MAX_INSNS 51223#define FIXUP_SYSCTL_VALUE 024 25char bpf_log_buf[BPF_LOG_BUF_SIZE];26 27struct sysctl_test {28 const char *descr;29 size_t fixup_value_insn;30 struct bpf_insn insns[MAX_INSNS];31 const char *prog_file;32 enum bpf_attach_type attach_type;33 const char *sysctl;34 int open_flags;35 int seek;36 const char *newval;37 const char *oldval;38 enum {39 LOAD_REJECT,40 ATTACH_REJECT,41 OP_EPERM,42 SUCCESS,43 } result;44};45 46static struct sysctl_test tests[] = {47 {48 .descr = "sysctl wrong attach_type",49 .insns = {50 BPF_MOV64_IMM(BPF_REG_0, 1),51 BPF_EXIT_INSN(),52 },53 .attach_type = 0,54 .sysctl = "kernel/ostype",55 .open_flags = O_RDONLY,56 .result = ATTACH_REJECT,57 },58 {59 .descr = "sysctl:read allow all",60 .insns = {61 BPF_MOV64_IMM(BPF_REG_0, 1),62 BPF_EXIT_INSN(),63 },64 .attach_type = BPF_CGROUP_SYSCTL,65 .sysctl = "kernel/ostype",66 .open_flags = O_RDONLY,67 .result = SUCCESS,68 },69 {70 .descr = "sysctl:read deny all",71 .insns = {72 BPF_MOV64_IMM(BPF_REG_0, 0),73 BPF_EXIT_INSN(),74 },75 .attach_type = BPF_CGROUP_SYSCTL,76 .sysctl = "kernel/ostype",77 .open_flags = O_RDONLY,78 .result = OP_EPERM,79 },80 {81 .descr = "ctx:write sysctl:read read ok",82 .insns = {83 /* 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),87 88 /* return DENY; */89 BPF_MOV64_IMM(BPF_REG_0, 0),90 BPF_JMP_A(1),91 92 /* else return ALLOW; */93 BPF_MOV64_IMM(BPF_REG_0, 1),94 BPF_EXIT_INSN(),95 },96 .attach_type = BPF_CGROUP_SYSCTL,97 .sysctl = "kernel/ostype",98 .open_flags = O_RDONLY,99 .result = SUCCESS,100 },101 {102 .descr = "ctx:write sysctl:write read ok",103 .insns = {104 /* 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),108 109 /* return DENY; */110 BPF_MOV64_IMM(BPF_REG_0, 0),111 BPF_JMP_A(1),112 113 /* else return ALLOW; */114 BPF_MOV64_IMM(BPF_REG_0, 1),115 BPF_EXIT_INSN(),116 },117 .attach_type = BPF_CGROUP_SYSCTL,118 .sysctl = "kernel/domainname",119 .open_flags = O_WRONLY,120 .newval = "(none)", /* same as default, should fail anyway */121 .result = OP_EPERM,122 },123 {124 .descr = "ctx:write sysctl:write read ok narrow",125 .insns = {126 /* u64 w = (u16)write & 1; */127#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__128 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1,129 offsetof(struct bpf_sysctl, write)),130#else131 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1,132 offsetof(struct bpf_sysctl, write) + 2),133#endif134 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(),139 },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,145 },146 {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(),155 },156 .attach_type = BPF_CGROUP_SYSCTL,157 .sysctl = "kernel/ostype",158 .open_flags = O_RDONLY,159 .result = LOAD_REJECT,160 },161 {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),168 169 /* return ALLOW; */170 BPF_MOV64_IMM(BPF_REG_0, 1),171 BPF_JMP_A(1),172 173 /* else return DENY; */174 BPF_MOV64_IMM(BPF_REG_0, 0),175 BPF_EXIT_INSN(),176 },177 .attach_type = BPF_CGROUP_SYSCTL,178 .sysctl = "kernel/ostype",179 .open_flags = O_RDONLY,180 .seek = 3,181 .result = SUCCESS,182 },183 {184 .descr = "ctx:file_pos sysctl:read read ok narrow",185 .insns = {186 /* If (file_pos == X) */187#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__188 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,189 offsetof(struct bpf_sysctl, file_pos)),190#else191 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,192 offsetof(struct bpf_sysctl, file_pos) + 3),193#endif194 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2),195 196 /* return ALLOW; */197 BPF_MOV64_IMM(BPF_REG_0, 1),198 BPF_JMP_A(1),199 200 /* else return DENY; */201 BPF_MOV64_IMM(BPF_REG_0, 0),202 BPF_EXIT_INSN(),203 },204 .attach_type = BPF_CGROUP_SYSCTL,205 .sysctl = "kernel/ostype",206 .open_flags = O_RDONLY,207 .seek = 4,208 .result = SUCCESS,209 },210 {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(),219 },220 .attach_type = BPF_CGROUP_SYSCTL,221 .sysctl = "kernel/ostype",222 .open_flags = O_RDONLY,223 .oldval = "nux\n",224 .result = SUCCESS,225 },226 {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),234 235 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),236 237 /* sysctl_get_name arg3 (buf_len) */238 BPF_MOV64_IMM(BPF_REG_3, 8),239 240 /* sysctl_get_name arg4 (flags) */241 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),242 243 /* sysctl_get_name(ctx, buf, buf_len, flags) */244 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),245 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),253 254 /* return ALLOW; */255 BPF_MOV64_IMM(BPF_REG_0, 1),256 BPF_JMP_A(1),257 258 /* else return DENY; */259 BPF_MOV64_IMM(BPF_REG_0, 0),260 BPF_EXIT_INSN(),261 },262 .attach_type = BPF_CGROUP_SYSCTL,263 .sysctl = "net/ipv4/tcp_mem",264 .open_flags = O_RDONLY,265 .result = SUCCESS,266 },267 {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),275 276 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),277 278 /* sysctl_get_name arg3 (buf_len) too small */279 BPF_MOV64_IMM(BPF_REG_3, 7),280 281 /* sysctl_get_name arg4 (flags) */282 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),283 284 /* sysctl_get_name(ctx, buf, buf_len, flags) */285 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),286 287 /* if (ret == expected && */288 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),289 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),295 296 /* return ALLOW; */297 BPF_MOV64_IMM(BPF_REG_0, 1),298 BPF_JMP_A(1),299 300 /* else return DENY; */301 BPF_MOV64_IMM(BPF_REG_0, 0),302 BPF_EXIT_INSN(),303 },304 .attach_type = BPF_CGROUP_SYSCTL,305 .sysctl = "net/ipv4/tcp_mem",306 .open_flags = O_RDONLY,307 .result = SUCCESS,308 },309 {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),319 320 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),321 322 /* sysctl_get_name arg3 (buf_len) */323 BPF_MOV64_IMM(BPF_REG_3, 17),324 325 /* sysctl_get_name arg4 (flags) */326 BPF_MOV64_IMM(BPF_REG_4, 0),327 328 /* sysctl_get_name(ctx, buf, buf_len, flags) */329 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),330 331 /* if (ret == expected && */332 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14),333 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),339 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),345 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),350 351 /* return ALLOW; */352 BPF_MOV64_IMM(BPF_REG_0, 1),353 BPF_JMP_A(1),354 355 /* else return DENY; */356 BPF_MOV64_IMM(BPF_REG_0, 0),357 BPF_EXIT_INSN(),358 },359 .attach_type = BPF_CGROUP_SYSCTL,360 .sysctl = "net/ipv4/tcp_mem",361 .open_flags = O_RDONLY,362 .result = SUCCESS,363 },364 {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),373 374 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),375 376 /* sysctl_get_name arg3 (buf_len) */377 BPF_MOV64_IMM(BPF_REG_3, 16),378 379 /* sysctl_get_name arg4 (flags) */380 BPF_MOV64_IMM(BPF_REG_4, 0),381 382 /* sysctl_get_name(ctx, buf, buf_len, flags) */383 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),384 385 /* if (ret == expected && */386 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10),387 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),393 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),399 400 /* return ALLOW; */401 BPF_MOV64_IMM(BPF_REG_0, 1),402 BPF_JMP_A(1),403 404 /* else return DENY; */405 BPF_MOV64_IMM(BPF_REG_0, 0),406 BPF_EXIT_INSN(),407 },408 .attach_type = BPF_CGROUP_SYSCTL,409 .sysctl = "net/ipv4/tcp_mem",410 .open_flags = O_RDONLY,411 .result = SUCCESS,412 },413 {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),421 422 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),423 424 /* sysctl_get_name arg3 (buf_len) */425 BPF_MOV64_IMM(BPF_REG_3, 7),426 427 /* sysctl_get_name arg4 (flags) */428 BPF_MOV64_IMM(BPF_REG_4, 0),429 430 /* sysctl_get_name(ctx, buf, buf_len, flags) */431 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),432 433 /* if (ret == expected && */434 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),435 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),441 442 /* return ALLOW; */443 BPF_MOV64_IMM(BPF_REG_0, 1),444 BPF_JMP_A(1),445 446 /* else return DENY; */447 BPF_MOV64_IMM(BPF_REG_0, 0),448 BPF_EXIT_INSN(),449 },450 .attach_type = BPF_CGROUP_SYSCTL,451 .sysctl = "net/ipv4/tcp_mem",452 .open_flags = O_RDONLY,453 .result = SUCCESS,454 },455 {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),462 463 /* sysctl_get_current_value arg3 (buf_len) */464 BPF_MOV64_IMM(BPF_REG_3, 8),465 466 /* sysctl_get_current_value(ctx, buf, buf_len) */467 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),468 469 /* if (ret == expected && */470 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),471 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),477 478 /* return ALLOW; */479 BPF_MOV64_IMM(BPF_REG_0, 1),480 BPF_JMP_A(1),481 482 /* else return DENY; */483 BPF_MOV64_IMM(BPF_REG_0, 0),484 BPF_EXIT_INSN(),485 },486 .attach_type = BPF_CGROUP_SYSCTL,487 .sysctl = "kernel/ostype",488 .open_flags = O_RDONLY,489 .result = SUCCESS,490 },491 {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),499 500 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),501 502 /* sysctl_get_current_value arg3 (buf_len) */503 BPF_MOV64_IMM(BPF_REG_3, 7),504 505 /* sysctl_get_current_value(ctx, buf, buf_len) */506 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),507 508 /* if (ret == expected && */509 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),510 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),516 517 /* return ALLOW; */518 BPF_MOV64_IMM(BPF_REG_0, 1),519 BPF_JMP_A(1),520 521 /* else return DENY; */522 BPF_MOV64_IMM(BPF_REG_0, 0),523 BPF_EXIT_INSN(),524 },525 .attach_type = BPF_CGROUP_SYSCTL,526 .sysctl = "kernel/ostype",527 .open_flags = O_RDONLY,528 .result = SUCCESS,529 },530 {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),538 539 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),540 541 /* sysctl_get_current_value arg3 (buf_len) */542 BPF_MOV64_IMM(BPF_REG_3, 6),543 544 /* sysctl_get_current_value(ctx, buf, buf_len) */545 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),546 547 /* if (ret == expected && */548 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),549 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),555 556 /* return ALLOW; */557 BPF_MOV64_IMM(BPF_REG_0, 1),558 BPF_JMP_A(1),559 560 /* else return DENY; */561 BPF_MOV64_IMM(BPF_REG_0, 0),562 BPF_EXIT_INSN(),563 },564 .attach_type = BPF_CGROUP_SYSCTL,565 .sysctl = "kernel/ostype",566 .open_flags = O_RDONLY,567 .result = SUCCESS,568 },569 {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),575 576 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),577 578 /* sysctl_get_current_value arg3 (buf_len) */579 BPF_MOV64_IMM(BPF_REG_3, 8),580 581 /* sysctl_get_current_value(ctx, buf, buf_len) */582 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),583 584 /* if (ret == expected && */585 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4),586 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),590 591 /* return DENY; */592 BPF_MOV64_IMM(BPF_REG_0, 0),593 BPF_JMP_A(1),594 595 /* else return ALLOW; */596 BPF_MOV64_IMM(BPF_REG_0, 1),597 BPF_EXIT_INSN(),598 },599 .attach_type = BPF_CGROUP_SYSCTL,600 .sysctl = "net/ipv6/conf/lo/stable_secret", /* -EIO */601 .open_flags = O_RDONLY,602 .result = OP_EPERM,603 },604 {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),611 612 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),613 614 /* sysctl_get_current_value arg3 (buf_len) */615 BPF_MOV64_IMM(BPF_REG_3, 8),616 617 /* sysctl_get_current_value(ctx, buf, buf_len) */618 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),619 620 /* if (ret == expected && */621 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6),622 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),627 628 /* return DENY; */629 BPF_MOV64_IMM(BPF_REG_0, 0),630 BPF_JMP_A(1),631 632 /* else return ALLOW; */633 BPF_MOV64_IMM(BPF_REG_0, 1),634 BPF_EXIT_INSN(),635 },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,641 },642 {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),650 651 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),652 653 /* sysctl_get_new_value arg3 (buf_len) */654 BPF_MOV64_IMM(BPF_REG_3, 8),655 656 /* sysctl_get_new_value(ctx, buf, buf_len) */657 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),658 659 /* if (ret == expected) */660 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),661 662 /* return ALLOW; */663 BPF_MOV64_IMM(BPF_REG_0, 1),664 BPF_JMP_A(1),665 666 /* else return DENY; */667 BPF_MOV64_IMM(BPF_REG_0, 0),668 BPF_EXIT_INSN(),669 },670 .attach_type = BPF_CGROUP_SYSCTL,671 .sysctl = "net/ipv4/tcp_mem",672 .open_flags = O_RDONLY,673 .result = SUCCESS,674 },675 {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),681 682 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),683 684 /* sysctl_get_new_value arg3 (buf_len) */685 BPF_MOV64_IMM(BPF_REG_3, 4),686 687 /* sysctl_get_new_value(ctx, buf, buf_len) */688 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),689 690 /* if (ret == expected && */691 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),692 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),697 698 /* return DENY; */699 BPF_MOV64_IMM(BPF_REG_0, 0),700 BPF_JMP_A(1),701 702 /* else return ALLOW; */703 BPF_MOV64_IMM(BPF_REG_0, 1),704 BPF_EXIT_INSN(),705 },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,711 },712 {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),718 719 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),720 721 /* sysctl_get_new_value arg3 (buf_len) */722 BPF_MOV64_IMM(BPF_REG_3, 24),723 724 /* sysctl_get_new_value(ctx, buf, buf_len) */725 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),726 727 /* if (ret == expected && */728 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14),729 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),735 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),741 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),747 748 /* return DENY; */749 BPF_MOV64_IMM(BPF_REG_0, 0),750 BPF_JMP_A(1),751 752 /* else return ALLOW; */753 BPF_MOV64_IMM(BPF_REG_0, 1),754 BPF_EXIT_INSN(),755 },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,761 },762 {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),770 771 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),772 773 /* sysctl_get_new_value arg3 (buf_len) */774 BPF_MOV64_IMM(BPF_REG_3, 3),775 776 /* sysctl_get_new_value(ctx, buf, buf_len) */777 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),778 779 /* if (ret == expected && */780 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4),781 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),786 787 /* return DENY; */788 BPF_MOV64_IMM(BPF_REG_0, 0),789 BPF_JMP_A(1),790 791 /* else return ALLOW; */792 BPF_MOV64_IMM(BPF_REG_0, 1),793 BPF_EXIT_INSN(),794 },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,800 },801 {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),810 811 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),812 813 /* sysctl_set_new_value arg3 (buf_len) */814 BPF_MOV64_IMM(BPF_REG_3, 3),815 816 /* sysctl_set_new_value(ctx, buf, buf_len) */817 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),818 819 /* if (ret == expected) */820 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),821 822 /* return ALLOW; */823 BPF_MOV64_IMM(BPF_REG_0, 1),824 BPF_JMP_A(1),825 826 /* else return DENY; */827 BPF_MOV64_IMM(BPF_REG_0, 0),828 BPF_EXIT_INSN(),829 },830 .attach_type = BPF_CGROUP_SYSCTL,831 .sysctl = "net/ipv4/route/mtu_expires",832 .open_flags = O_RDONLY,833 .result = SUCCESS,834 },835 {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),844 845 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),846 847 /* sysctl_set_new_value arg3 (buf_len) */848 BPF_MOV64_IMM(BPF_REG_3, 3),849 850 /* sysctl_set_new_value(ctx, buf, buf_len) */851 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),852 853 /* if (ret == expected) */854 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),855 856 /* return ALLOW; */857 BPF_MOV64_IMM(BPF_REG_0, 1),858 BPF_JMP_A(1),859 860 /* else return DENY; */861 BPF_MOV64_IMM(BPF_REG_0, 0),862 BPF_EXIT_INSN(),863 },864 .attach_type = BPF_CGROUP_SYSCTL,865 .sysctl = "net/ipv4/route/mtu_expires",866 .open_flags = O_WRONLY,867 .newval = "606",868 .result = SUCCESS,869 },870 {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),879 880 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),881 882 /* arg2 (buf_len) */883 BPF_MOV64_IMM(BPF_REG_2, 4),884 885 /* arg3 (flags) */886 BPF_MOV64_IMM(BPF_REG_3, 0),887 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),892 893 BPF_EMIT_CALL(BPF_FUNC_strtoul),894 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),900 901 /* return ALLOW; */902 BPF_MOV64_IMM(BPF_REG_0, 1),903 BPF_JMP_A(1),904 905 /* else return DENY; */906 BPF_MOV64_IMM(BPF_REG_0, 0),907 BPF_EXIT_INSN(),908 },909 .attach_type = BPF_CGROUP_SYSCTL,910 .sysctl = "net/ipv4/route/mtu_expires",911 .open_flags = O_RDONLY,912 .result = SUCCESS,913 },914 {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),925 926 /* arg2 (buf_len) */927 BPF_MOV64_IMM(BPF_REG_2, 8),928 929 /* arg3 (flags) */930 BPF_MOV64_IMM(BPF_REG_3, 0),931 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),936 937 BPF_EMIT_CALL(BPF_FUNC_strtoul),938 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),944 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),950 951 /* arg2 (buf_len) */952 BPF_MOV64_IMM(BPF_REG_2, 8),953 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0),954 955 /* arg3 (flags) */956 BPF_MOV64_IMM(BPF_REG_3, 0),957 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),962 963 BPF_EMIT_CALL(BPF_FUNC_strtoul),964 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),970 971 /* return ALLOW; */972 BPF_MOV64_IMM(BPF_REG_0, 1),973 BPF_JMP_A(1),974 975 /* else return DENY; */976 BPF_MOV64_IMM(BPF_REG_0, 0),977 BPF_EXIT_INSN(),978 },979 .attach_type = BPF_CGROUP_SYSCTL,980 .sysctl = "net/ipv4/tcp_mem",981 .open_flags = O_RDONLY,982 .result = SUCCESS,983 },984 {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),993 994 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),995 996 /* arg2 (buf_len) */997 BPF_MOV64_IMM(BPF_REG_2, 0),998 999 /* arg3 (flags) */1000 BPF_MOV64_IMM(BPF_REG_3, 0),1001 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),1006 1007 BPF_EMIT_CALL(BPF_FUNC_strtoul),1008 1009 BPF_MOV64_IMM(BPF_REG_0, 1),1010 BPF_EXIT_INSN(),1011 },1012 .attach_type = BPF_CGROUP_SYSCTL,1013 .sysctl = "net/ipv4/route/mtu_expires",1014 .open_flags = O_RDONLY,1015 .result = LOAD_REJECT,1016 },1017 {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),1026 1027 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1028 1029 /* arg2 (buf_len) */1030 BPF_MOV64_IMM(BPF_REG_2, 4),1031 1032 /* arg3 (flags) */1033 BPF_MOV64_IMM(BPF_REG_3, 8),1034 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),1039 1040 BPF_EMIT_CALL(BPF_FUNC_strtoul),1041 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),1047 1048 /* return ALLOW; */1049 BPF_MOV64_IMM(BPF_REG_0, 1),1050 BPF_JMP_A(1),1051 1052 /* else return DENY; */1053 BPF_MOV64_IMM(BPF_REG_0, 0),1054 BPF_EXIT_INSN(),1055 },1056 .attach_type = BPF_CGROUP_SYSCTL,1057 .sysctl = "net/ipv4/route/mtu_expires",1058 .open_flags = O_RDONLY,1059 .result = SUCCESS,1060 },1061 {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),1070 1071 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1072 1073 /* arg2 (buf_len) */1074 BPF_MOV64_IMM(BPF_REG_2, 4),1075 1076 /* arg3 (flags) */1077 BPF_MOV64_IMM(BPF_REG_3, 3),1078 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),1083 1084 BPF_EMIT_CALL(BPF_FUNC_strtoul),1085 1086 /* if (ret == expected) */1087 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),1088 1089 /* return ALLOW; */1090 BPF_MOV64_IMM(BPF_REG_0, 1),1091 BPF_JMP_A(1),1092 1093 /* else return DENY; */1094 BPF_MOV64_IMM(BPF_REG_0, 0),1095 BPF_EXIT_INSN(),1096 },1097 .attach_type = BPF_CGROUP_SYSCTL,1098 .sysctl = "net/ipv4/route/mtu_expires",1099 .open_flags = O_RDONLY,1100 .result = SUCCESS,1101 },1102 {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),1111 1112 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1113 1114 /* arg2 (buf_len) */1115 BPF_MOV64_IMM(BPF_REG_2, 4),1116 1117 /* arg3 (flags) */1118 BPF_MOV64_IMM(BPF_REG_3, 0),1119 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),1124 1125 BPF_EMIT_CALL(BPF_FUNC_strtoul),1126 1127 /* if (ret == expected) */1128 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),1129 1130 /* return ALLOW; */1131 BPF_MOV64_IMM(BPF_REG_0, 1),1132 BPF_JMP_A(1),1133 1134 /* else return DENY; */1135 BPF_MOV64_IMM(BPF_REG_0, 0),1136 BPF_EXIT_INSN(),1137 },1138 .attach_type = BPF_CGROUP_SYSCTL,1139 .sysctl = "net/ipv4/route/mtu_expires",1140 .open_flags = O_RDONLY,1141 .result = SUCCESS,1142 },1143 {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),1153 1154 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1155 1156 /* arg2 (buf_len) */1157 BPF_MOV64_IMM(BPF_REG_2, 4),1158 1159 /* arg3 (flags) */1160 BPF_MOV64_IMM(BPF_REG_3, 0),1161 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),1166 1167 BPF_EMIT_CALL(BPF_FUNC_strtoul),1168 1169 /* if (ret == expected) */1170 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),1171 1172 /* return ALLOW; */1173 BPF_MOV64_IMM(BPF_REG_0, 1),1174 BPF_JMP_A(1),1175 1176 /* else return DENY; */1177 BPF_MOV64_IMM(BPF_REG_0, 0),1178 BPF_EXIT_INSN(),1179 },1180 .attach_type = BPF_CGROUP_SYSCTL,1181 .sysctl = "net/ipv4/route/mtu_expires",1182 .open_flags = O_RDONLY,1183 .result = SUCCESS,1184 },1185 {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),1195 1196 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1197 1198 /* arg2 (buf_len) */1199 BPF_MOV64_IMM(BPF_REG_2, 4),1200 1201 /* arg3 (flags) */1202 BPF_MOV64_IMM(BPF_REG_3, 10),1203 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),1208 1209 BPF_EMIT_CALL(BPF_FUNC_strtol),1210 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),1216 1217 /* return ALLOW; */1218 BPF_MOV64_IMM(BPF_REG_0, 1),1219 BPF_JMP_A(1),1220 1221 /* else return DENY; */1222 BPF_MOV64_IMM(BPF_REG_0, 0),1223 BPF_EXIT_INSN(),1224 },1225 .attach_type = BPF_CGROUP_SYSCTL,1226 .sysctl = "net/ipv4/route/mtu_expires",1227 .open_flags = O_RDONLY,1228 .result = SUCCESS,1229 },1230 {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),1240 1241 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1242 1243 /* arg2 (buf_len) */1244 BPF_MOV64_IMM(BPF_REG_2, 4),1245 1246 /* arg3 (flags) */1247 BPF_MOV64_IMM(BPF_REG_3, 0),1248 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),1253 1254 BPF_EMIT_CALL(BPF_FUNC_strtol),1255 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),1261 1262 /* return ALLOW; */1263 BPF_MOV64_IMM(BPF_REG_0, 1),1264 BPF_JMP_A(1),1265 1266 /* else return DENY; */1267 BPF_MOV64_IMM(BPF_REG_0, 0),1268 BPF_EXIT_INSN(),1269 },1270 .attach_type = BPF_CGROUP_SYSCTL,1271 .sysctl = "net/ipv4/route/mtu_expires",1272 .open_flags = O_RDONLY,1273 .result = SUCCESS,1274 },1275 {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),1290 1291 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1292 1293 /* arg2 (buf_len) */1294 BPF_MOV64_IMM(BPF_REG_2, 19),1295 1296 /* arg3 (flags) */1297 BPF_MOV64_IMM(BPF_REG_3, 0),1298 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),1303 1304 BPF_EMIT_CALL(BPF_FUNC_strtol),1305 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),1312 1313 /* return ALLOW; */1314 BPF_MOV64_IMM(BPF_REG_0, 1),1315 BPF_JMP_A(1),1316 1317 /* else return DENY; */1318 BPF_MOV64_IMM(BPF_REG_0, 0),1319 BPF_EXIT_INSN(),1320 },1321 .attach_type = BPF_CGROUP_SYSCTL,1322 .sysctl = "net/ipv4/route/mtu_expires",1323 .open_flags = O_RDONLY,1324 .result = SUCCESS,1325 },1326 {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),1341 1342 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),1343 1344 /* arg2 (buf_len) */1345 BPF_MOV64_IMM(BPF_REG_2, 19),1346 1347 /* arg3 (flags) */1348 BPF_MOV64_IMM(BPF_REG_3, 0),1349 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),1354 1355 BPF_EMIT_CALL(BPF_FUNC_strtol),1356 1357 /* if (ret == expected) */1358 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2),1359 1360 /* return ALLOW; */1361 BPF_MOV64_IMM(BPF_REG_0, 1),1362 BPF_JMP_A(1),1363 1364 /* else return DENY; */1365 BPF_MOV64_IMM(BPF_REG_0, 0),1366 BPF_EXIT_INSN(),1367 },1368 .attach_type = BPF_CGROUP_SYSCTL,1369 .sysctl = "net/ipv4/route/mtu_expires",1370 .open_flags = O_RDONLY,1371 .result = SUCCESS,1372 },1373 {1374 "C prog: deny all writes",1375 .prog_file = "./test_sysctl_prog.bpf.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,1381 },1382 {1383 "C prog: deny access by name",1384 .prog_file = "./test_sysctl_prog.bpf.o",1385 .attach_type = BPF_CGROUP_SYSCTL,1386 .sysctl = "net/ipv4/route/mtu_expires",1387 .open_flags = O_RDONLY,1388 .result = OP_EPERM,1389 },1390 {1391 "C prog: read tcp_mem",1392 .prog_file = "./test_sysctl_prog.bpf.o",1393 .attach_type = BPF_CGROUP_SYSCTL,1394 .sysctl = "net/ipv4/tcp_mem",1395 .open_flags = O_RDONLY,1396 .result = SUCCESS,1397 },1398};1399 1400static size_t probe_prog_length(const struct bpf_insn *fp)1401{1402 size_t len;1403 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;1408}1409 1410static int fixup_sysctl_value(const char *buf, size_t buf_len,1411 struct bpf_insn *prog, size_t insn_num)1412{1413 union {1414 uint8_t raw[sizeof(uint64_t)];1415 uint64_t num;1416 } value = {};1417 1418 if (buf_len > sizeof(value)) {1419 log_err("Value is too big (%zd) to use in fixup", buf_len);1420 return -1;1421 }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;1425 }1426 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);1430 1431 return 0;1432}1433 1434static int load_sysctl_prog_insns(struct sysctl_test *test,1435 const char *sysctl_path)1436{1437 struct bpf_insn *prog = test->insns;1438 LIBBPF_OPTS(bpf_prog_load_opts, opts);1439 int ret, insn_cnt;1440 1441 insn_cnt = probe_prog_length(prog);1442 1443 if (test->fixup_value_insn) {1444 char buf[128];1445 ssize_t len;1446 int fd;1447 1448 fd = open(sysctl_path, O_RDONLY | O_CLOEXEC);1449 if (fd < 0) {1450 log_err("open(%s) failed", sysctl_path);1451 return -1;1452 }1453 len = read(fd, buf, sizeof(buf));1454 if (len == -1) {1455 log_err("read(%s) failed", sysctl_path);1456 close(fd);1457 return -1;1458 }1459 close(fd);1460 if (fixup_sysctl_value(buf, len, prog, test->fixup_value_insn))1461 return -1;1462 }1463 1464 opts.log_buf = bpf_log_buf;1465 opts.log_size = BPF_LOG_BUF_SIZE;1466 1467 ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SYSCTL, NULL, "GPL", prog, insn_cnt, &opts);1468 if (ret < 0 && test->result != LOAD_REJECT) {1469 log_err(">>> Loading program error.\n"1470 ">>> Verifier output:\n%s\n-------\n", bpf_log_buf);1471 }1472 1473 return ret;1474}1475 1476static int load_sysctl_prog_file(struct sysctl_test *test)1477{1478 struct bpf_object *obj;1479 int prog_fd;1480 1481 if (bpf_prog_test_load(test->prog_file, BPF_PROG_TYPE_CGROUP_SYSCTL, &obj, &prog_fd)) {1482 if (test->result != LOAD_REJECT)1483 log_err(">>> Loading program (%s) error.\n",1484 test->prog_file);1485 return -1;1486 }1487 1488 return prog_fd;1489}1490 1491static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path)1492{1493 return test->prog_file1494 ? load_sysctl_prog_file(test)1495 : load_sysctl_prog_insns(test, sysctl_path);1496}1497 1498static int access_sysctl(const char *sysctl_path,1499 const struct sysctl_test *test)1500{1501 int err = 0;1502 int fd;1503 1504 fd = open(sysctl_path, test->open_flags | O_CLOEXEC);1505 if (fd < 0)1506 return fd;1507 1508 if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) {1509 log_err("lseek(%d) failed", test->seek);1510 goto err;1511 }1512 1513 if (test->open_flags == O_RDONLY) {1514 char buf[128];1515 1516 if (read(fd, buf, sizeof(buf)) == -1)1517 goto err;1518 if (test->oldval &&1519 strncmp(buf, test->oldval, strlen(test->oldval))) {1520 log_err("Read value %s != %s", buf, test->oldval);1521 goto err;1522 }1523 } else if (test->open_flags == O_WRONLY) {1524 if (!test->newval) {1525 log_err("New value for sysctl is not set");1526 goto err;1527 }1528 if (write(fd, test->newval, strlen(test->newval)) == -1)1529 goto err;1530 } else {1531 log_err("Unexpected sysctl access: neither read nor write");1532 goto err;1533 }1534 1535 goto out;1536err:1537 err = -1;1538out:1539 close(fd);1540 return err;1541}1542 1543static int run_test_case(int cgfd, struct sysctl_test *test)1544{1545 enum bpf_attach_type atype = test->attach_type;1546 char sysctl_path[128];1547 int progfd = -1;1548 int err = 0;1549 1550 printf("Test case: %s .. ", test->descr);1551 1552 snprintf(sysctl_path, sizeof(sysctl_path), "/proc/sys/%s",1553 test->sysctl);1554 1555 progfd = load_sysctl_prog(test, sysctl_path);1556 if (progfd < 0) {1557 if (test->result == LOAD_REJECT)1558 goto out;1559 else1560 goto err;1561 }1562 1563 if (bpf_prog_attach(progfd, cgfd, atype, BPF_F_ALLOW_OVERRIDE) < 0) {1564 if (test->result == ATTACH_REJECT)1565 goto out;1566 else1567 goto err;1568 }1569 1570 errno = 0;1571 if (access_sysctl(sysctl_path, test) == -1) {1572 if (test->result == OP_EPERM && errno == EPERM)1573 goto out;1574 else1575 goto err;1576 }1577 1578 if (test->result != SUCCESS) {1579 log_err("Unexpected success");1580 goto err;1581 }1582 1583 goto out;1584err:1585 err = -1;1586out:1587 /* Detaching w/o checking return code: best effort attempt. */1588 if (progfd != -1)1589 bpf_prog_detach(cgfd, atype);1590 close(progfd);1591 printf("[%s]\n", err ? "FAIL" : "PASS");1592 return err;1593}1594 1595static int run_tests(int cgfd)1596{1597 int passes = 0;1598 int fails = 0;1599 int i;1600 1601 for (i = 0; i < ARRAY_SIZE(tests); ++i) {1602 if (run_test_case(cgfd, &tests[i]))1603 ++fails;1604 else1605 ++passes;1606 }1607 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);1608 return fails ? -1 : 0;1609}1610 1611int main(int argc, char **argv)1612{1613 int cgfd = -1;1614 int err = 0;1615 1616 cgfd = cgroup_setup_and_join(CG_PATH);1617 if (cgfd < 0)1618 goto err;1619 1620 /* Use libbpf 1.0 API mode */1621 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);1622 1623 if (run_tests(cgfd))1624 goto err;1625 1626 goto out;1627err:1628 err = -1;1629out:1630 close(cgfd);1631 cleanup_cgroup_environment();1632 return err;1633}1634