0001
0002
0003
0004 #include <fcntl.h>
0005 #include <stdint.h>
0006 #include <stdio.h>
0007 #include <stdlib.h>
0008 #include <string.h>
0009 #include <unistd.h>
0010
0011 #include <linux/filter.h>
0012
0013 #include <bpf/bpf.h>
0014 #include <bpf/libbpf.h>
0015
0016 #include <bpf/bpf_endian.h>
0017 #include "bpf_util.h"
0018 #include "cgroup_helpers.h"
0019 #include "testing_helpers.h"
0020
0021 #define CG_PATH "/foo"
0022 #define MAX_INSNS 512
0023 #define FIXUP_SYSCTL_VALUE 0
0024
0025 char bpf_log_buf[BPF_LOG_BUF_SIZE];
0026
0027 struct sysctl_test {
0028 const char *descr;
0029 size_t fixup_value_insn;
0030 struct bpf_insn insns[MAX_INSNS];
0031 const char *prog_file;
0032 enum bpf_attach_type attach_type;
0033 const char *sysctl;
0034 int open_flags;
0035 int seek;
0036 const char *newval;
0037 const char *oldval;
0038 enum {
0039 LOAD_REJECT,
0040 ATTACH_REJECT,
0041 OP_EPERM,
0042 SUCCESS,
0043 } result;
0044 };
0045
0046 static struct sysctl_test tests[] = {
0047 {
0048 .descr = "sysctl wrong attach_type",
0049 .insns = {
0050 BPF_MOV64_IMM(BPF_REG_0, 1),
0051 BPF_EXIT_INSN(),
0052 },
0053 .attach_type = 0,
0054 .sysctl = "kernel/ostype",
0055 .open_flags = O_RDONLY,
0056 .result = ATTACH_REJECT,
0057 },
0058 {
0059 .descr = "sysctl:read allow all",
0060 .insns = {
0061 BPF_MOV64_IMM(BPF_REG_0, 1),
0062 BPF_EXIT_INSN(),
0063 },
0064 .attach_type = BPF_CGROUP_SYSCTL,
0065 .sysctl = "kernel/ostype",
0066 .open_flags = O_RDONLY,
0067 .result = SUCCESS,
0068 },
0069 {
0070 .descr = "sysctl:read deny all",
0071 .insns = {
0072 BPF_MOV64_IMM(BPF_REG_0, 0),
0073 BPF_EXIT_INSN(),
0074 },
0075 .attach_type = BPF_CGROUP_SYSCTL,
0076 .sysctl = "kernel/ostype",
0077 .open_flags = O_RDONLY,
0078 .result = OP_EPERM,
0079 },
0080 {
0081 .descr = "ctx:write sysctl:read read ok",
0082 .insns = {
0083
0084 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
0085 offsetof(struct bpf_sysctl, write)),
0086 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2),
0087
0088
0089 BPF_MOV64_IMM(BPF_REG_0, 0),
0090 BPF_JMP_A(1),
0091
0092
0093 BPF_MOV64_IMM(BPF_REG_0, 1),
0094 BPF_EXIT_INSN(),
0095 },
0096 .attach_type = BPF_CGROUP_SYSCTL,
0097 .sysctl = "kernel/ostype",
0098 .open_flags = O_RDONLY,
0099 .result = SUCCESS,
0100 },
0101 {
0102 .descr = "ctx:write sysctl:write read ok",
0103 .insns = {
0104
0105 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
0106 offsetof(struct bpf_sysctl, write)),
0107 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2),
0108
0109
0110 BPF_MOV64_IMM(BPF_REG_0, 0),
0111 BPF_JMP_A(1),
0112
0113
0114 BPF_MOV64_IMM(BPF_REG_0, 1),
0115 BPF_EXIT_INSN(),
0116 },
0117 .attach_type = BPF_CGROUP_SYSCTL,
0118 .sysctl = "kernel/domainname",
0119 .open_flags = O_WRONLY,
0120 .newval = "(none)",
0121 .result = OP_EPERM,
0122 },
0123 {
0124 .descr = "ctx:write sysctl:write read ok narrow",
0125 .insns = {
0126
0127 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0128 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1,
0129 offsetof(struct bpf_sysctl, write)),
0130 #else
0131 BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_1,
0132 offsetof(struct bpf_sysctl, write) + 2),
0133 #endif
0134 BPF_ALU64_IMM(BPF_AND, BPF_REG_7, 1),
0135
0136 BPF_MOV64_IMM(BPF_REG_0, 1),
0137 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_7),
0138 BPF_EXIT_INSN(),
0139 },
0140 .attach_type = BPF_CGROUP_SYSCTL,
0141 .sysctl = "kernel/domainname",
0142 .open_flags = O_WRONLY,
0143 .newval = "(none)",
0144 .result = OP_EPERM,
0145 },
0146 {
0147 .descr = "ctx:write sysctl:read write reject",
0148 .insns = {
0149
0150 BPF_MOV64_IMM(BPF_REG_0, 0),
0151 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
0152 offsetof(struct bpf_sysctl, write)),
0153 BPF_MOV64_IMM(BPF_REG_0, 1),
0154 BPF_EXIT_INSN(),
0155 },
0156 .attach_type = BPF_CGROUP_SYSCTL,
0157 .sysctl = "kernel/ostype",
0158 .open_flags = O_RDONLY,
0159 .result = LOAD_REJECT,
0160 },
0161 {
0162 .descr = "ctx:file_pos sysctl:read read ok",
0163 .insns = {
0164
0165 BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
0166 offsetof(struct bpf_sysctl, file_pos)),
0167 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 3, 2),
0168
0169
0170 BPF_MOV64_IMM(BPF_REG_0, 1),
0171 BPF_JMP_A(1),
0172
0173
0174 BPF_MOV64_IMM(BPF_REG_0, 0),
0175 BPF_EXIT_INSN(),
0176 },
0177 .attach_type = BPF_CGROUP_SYSCTL,
0178 .sysctl = "kernel/ostype",
0179 .open_flags = O_RDONLY,
0180 .seek = 3,
0181 .result = SUCCESS,
0182 },
0183 {
0184 .descr = "ctx:file_pos sysctl:read read ok narrow",
0185 .insns = {
0186
0187 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0188 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
0189 offsetof(struct bpf_sysctl, file_pos)),
0190 #else
0191 BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
0192 offsetof(struct bpf_sysctl, file_pos) + 3),
0193 #endif
0194 BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2),
0195
0196
0197 BPF_MOV64_IMM(BPF_REG_0, 1),
0198 BPF_JMP_A(1),
0199
0200
0201 BPF_MOV64_IMM(BPF_REG_0, 0),
0202 BPF_EXIT_INSN(),
0203 },
0204 .attach_type = BPF_CGROUP_SYSCTL,
0205 .sysctl = "kernel/ostype",
0206 .open_flags = O_RDONLY,
0207 .seek = 4,
0208 .result = SUCCESS,
0209 },
0210 {
0211 .descr = "ctx:file_pos sysctl:read write ok",
0212 .insns = {
0213
0214 BPF_MOV64_IMM(BPF_REG_0, 2),
0215 BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
0216 offsetof(struct bpf_sysctl, file_pos)),
0217 BPF_MOV64_IMM(BPF_REG_0, 1),
0218 BPF_EXIT_INSN(),
0219 },
0220 .attach_type = BPF_CGROUP_SYSCTL,
0221 .sysctl = "kernel/ostype",
0222 .open_flags = O_RDONLY,
0223 .oldval = "nux\n",
0224 .result = SUCCESS,
0225 },
0226 {
0227 .descr = "sysctl_get_name sysctl_value:base ok",
0228 .insns = {
0229
0230 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0231 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0232 BPF_MOV64_IMM(BPF_REG_0, 0),
0233 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0234
0235 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0236
0237
0238 BPF_MOV64_IMM(BPF_REG_3, 8),
0239
0240
0241 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
0242
0243
0244 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0245
0246
0247 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6),
0248
0249 BPF_LD_IMM64(BPF_REG_8,
0250 bpf_be64_to_cpu(0x7463705f6d656d00ULL)),
0251 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0252 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0253
0254
0255 BPF_MOV64_IMM(BPF_REG_0, 1),
0256 BPF_JMP_A(1),
0257
0258
0259 BPF_MOV64_IMM(BPF_REG_0, 0),
0260 BPF_EXIT_INSN(),
0261 },
0262 .attach_type = BPF_CGROUP_SYSCTL,
0263 .sysctl = "net/ipv4/tcp_mem",
0264 .open_flags = O_RDONLY,
0265 .result = SUCCESS,
0266 },
0267 {
0268 .descr = "sysctl_get_name sysctl_value:base E2BIG truncated",
0269 .insns = {
0270
0271 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0272 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0273 BPF_MOV64_IMM(BPF_REG_0, 0),
0274 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0275
0276 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0277
0278
0279 BPF_MOV64_IMM(BPF_REG_3, 7),
0280
0281
0282 BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
0283
0284
0285 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0286
0287
0288 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
0289
0290
0291 BPF_LD_IMM64(BPF_REG_8,
0292 bpf_be64_to_cpu(0x7463705f6d650000ULL)),
0293 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0294 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0295
0296
0297 BPF_MOV64_IMM(BPF_REG_0, 1),
0298 BPF_JMP_A(1),
0299
0300
0301 BPF_MOV64_IMM(BPF_REG_0, 0),
0302 BPF_EXIT_INSN(),
0303 },
0304 .attach_type = BPF_CGROUP_SYSCTL,
0305 .sysctl = "net/ipv4/tcp_mem",
0306 .open_flags = O_RDONLY,
0307 .result = SUCCESS,
0308 },
0309 {
0310 .descr = "sysctl_get_name sysctl:full ok",
0311 .insns = {
0312
0313 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0314 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
0315 BPF_MOV64_IMM(BPF_REG_0, 0),
0316 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0317 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
0318 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16),
0319
0320 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0321
0322
0323 BPF_MOV64_IMM(BPF_REG_3, 17),
0324
0325
0326 BPF_MOV64_IMM(BPF_REG_4, 0),
0327
0328
0329 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0330
0331
0332 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14),
0333
0334
0335 BPF_LD_IMM64(BPF_REG_8,
0336 bpf_be64_to_cpu(0x6e65742f69707634ULL)),
0337 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0338 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10),
0339
0340
0341 BPF_LD_IMM64(BPF_REG_8,
0342 bpf_be64_to_cpu(0x2f7463705f6d656dULL)),
0343 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
0344 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
0345
0346
0347 BPF_LD_IMM64(BPF_REG_8, 0x0ULL),
0348 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16),
0349 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0350
0351
0352 BPF_MOV64_IMM(BPF_REG_0, 1),
0353 BPF_JMP_A(1),
0354
0355
0356 BPF_MOV64_IMM(BPF_REG_0, 0),
0357 BPF_EXIT_INSN(),
0358 },
0359 .attach_type = BPF_CGROUP_SYSCTL,
0360 .sysctl = "net/ipv4/tcp_mem",
0361 .open_flags = O_RDONLY,
0362 .result = SUCCESS,
0363 },
0364 {
0365 .descr = "sysctl_get_name sysctl:full E2BIG truncated",
0366 .insns = {
0367
0368 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0369 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
0370 BPF_MOV64_IMM(BPF_REG_0, 0),
0371 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0372 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
0373
0374 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0375
0376
0377 BPF_MOV64_IMM(BPF_REG_3, 16),
0378
0379
0380 BPF_MOV64_IMM(BPF_REG_4, 0),
0381
0382
0383 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0384
0385
0386 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10),
0387
0388
0389 BPF_LD_IMM64(BPF_REG_8,
0390 bpf_be64_to_cpu(0x6e65742f69707634ULL)),
0391 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0392 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
0393
0394
0395 BPF_LD_IMM64(BPF_REG_8,
0396 bpf_be64_to_cpu(0x2f7463705f6d6500ULL)),
0397 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
0398 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0399
0400
0401 BPF_MOV64_IMM(BPF_REG_0, 1),
0402 BPF_JMP_A(1),
0403
0404
0405 BPF_MOV64_IMM(BPF_REG_0, 0),
0406 BPF_EXIT_INSN(),
0407 },
0408 .attach_type = BPF_CGROUP_SYSCTL,
0409 .sysctl = "net/ipv4/tcp_mem",
0410 .open_flags = O_RDONLY,
0411 .result = SUCCESS,
0412 },
0413 {
0414 .descr = "sysctl_get_name sysctl:full E2BIG truncated small",
0415 .insns = {
0416
0417 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0418 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0419 BPF_MOV64_IMM(BPF_REG_0, 0),
0420 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0421
0422 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0423
0424
0425 BPF_MOV64_IMM(BPF_REG_3, 7),
0426
0427
0428 BPF_MOV64_IMM(BPF_REG_4, 0),
0429
0430
0431 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0432
0433
0434 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
0435
0436
0437 BPF_LD_IMM64(BPF_REG_8,
0438 bpf_be64_to_cpu(0x6e65742f69700000ULL)),
0439 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0440 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0441
0442
0443 BPF_MOV64_IMM(BPF_REG_0, 1),
0444 BPF_JMP_A(1),
0445
0446
0447 BPF_MOV64_IMM(BPF_REG_0, 0),
0448 BPF_EXIT_INSN(),
0449 },
0450 .attach_type = BPF_CGROUP_SYSCTL,
0451 .sysctl = "net/ipv4/tcp_mem",
0452 .open_flags = O_RDONLY,
0453 .result = SUCCESS,
0454 },
0455 {
0456 .descr = "sysctl_get_current_value sysctl:read ok, gt",
0457 .insns = {
0458
0459 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0460 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0461 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0462
0463
0464 BPF_MOV64_IMM(BPF_REG_3, 8),
0465
0466
0467 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0468
0469
0470 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
0471
0472
0473 BPF_LD_IMM64(BPF_REG_8,
0474 bpf_be64_to_cpu(0x4c696e75780a0000ULL)),
0475 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0476 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0477
0478
0479 BPF_MOV64_IMM(BPF_REG_0, 1),
0480 BPF_JMP_A(1),
0481
0482
0483 BPF_MOV64_IMM(BPF_REG_0, 0),
0484 BPF_EXIT_INSN(),
0485 },
0486 .attach_type = BPF_CGROUP_SYSCTL,
0487 .sysctl = "kernel/ostype",
0488 .open_flags = O_RDONLY,
0489 .result = SUCCESS,
0490 },
0491 {
0492 .descr = "sysctl_get_current_value sysctl:read ok, eq",
0493 .insns = {
0494
0495 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0496 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0497 BPF_MOV64_IMM(BPF_REG_0, 0),
0498 BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 7),
0499
0500 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0501
0502
0503 BPF_MOV64_IMM(BPF_REG_3, 7),
0504
0505
0506 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0507
0508
0509 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
0510
0511
0512 BPF_LD_IMM64(BPF_REG_8,
0513 bpf_be64_to_cpu(0x4c696e75780a0000ULL)),
0514 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0515 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0516
0517
0518 BPF_MOV64_IMM(BPF_REG_0, 1),
0519 BPF_JMP_A(1),
0520
0521
0522 BPF_MOV64_IMM(BPF_REG_0, 0),
0523 BPF_EXIT_INSN(),
0524 },
0525 .attach_type = BPF_CGROUP_SYSCTL,
0526 .sysctl = "kernel/ostype",
0527 .open_flags = O_RDONLY,
0528 .result = SUCCESS,
0529 },
0530 {
0531 .descr = "sysctl_get_current_value sysctl:read E2BIG truncated",
0532 .insns = {
0533
0534 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0535 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0536 BPF_MOV64_IMM(BPF_REG_0, 0),
0537 BPF_STX_MEM(BPF_H, BPF_REG_7, BPF_REG_0, 6),
0538
0539 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0540
0541
0542 BPF_MOV64_IMM(BPF_REG_3, 6),
0543
0544
0545 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0546
0547
0548 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
0549
0550
0551 BPF_LD_IMM64(BPF_REG_8,
0552 bpf_be64_to_cpu(0x4c696e7578000000ULL)),
0553 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0554 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0555
0556
0557 BPF_MOV64_IMM(BPF_REG_0, 1),
0558 BPF_JMP_A(1),
0559
0560
0561 BPF_MOV64_IMM(BPF_REG_0, 0),
0562 BPF_EXIT_INSN(),
0563 },
0564 .attach_type = BPF_CGROUP_SYSCTL,
0565 .sysctl = "kernel/ostype",
0566 .open_flags = O_RDONLY,
0567 .result = SUCCESS,
0568 },
0569 {
0570 .descr = "sysctl_get_current_value sysctl:read EINVAL",
0571 .insns = {
0572
0573 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0574 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0575
0576 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0577
0578
0579 BPF_MOV64_IMM(BPF_REG_3, 8),
0580
0581
0582 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0583
0584
0585 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4),
0586
0587
0588 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0589 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2),
0590
0591
0592 BPF_MOV64_IMM(BPF_REG_0, 0),
0593 BPF_JMP_A(1),
0594
0595
0596 BPF_MOV64_IMM(BPF_REG_0, 1),
0597 BPF_EXIT_INSN(),
0598 },
0599 .attach_type = BPF_CGROUP_SYSCTL,
0600 .sysctl = "net/ipv6/conf/lo/stable_secret",
0601 .open_flags = O_RDONLY,
0602 .result = OP_EPERM,
0603 },
0604 {
0605 .descr = "sysctl_get_current_value sysctl:write ok",
0606 .fixup_value_insn = 6,
0607 .insns = {
0608
0609 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0610 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0611
0612 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0613
0614
0615 BPF_MOV64_IMM(BPF_REG_3, 8),
0616
0617
0618 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0619
0620
0621 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6),
0622
0623
0624 BPF_LD_IMM64(BPF_REG_8, FIXUP_SYSCTL_VALUE),
0625 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0626 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0627
0628
0629 BPF_MOV64_IMM(BPF_REG_0, 0),
0630 BPF_JMP_A(1),
0631
0632
0633 BPF_MOV64_IMM(BPF_REG_0, 1),
0634 BPF_EXIT_INSN(),
0635 },
0636 .attach_type = BPF_CGROUP_SYSCTL,
0637 .sysctl = "net/ipv4/route/mtu_expires",
0638 .open_flags = O_WRONLY,
0639 .newval = "600",
0640 .result = OP_EPERM,
0641 },
0642 {
0643 .descr = "sysctl_get_new_value sysctl:read EINVAL",
0644 .insns = {
0645
0646 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0647 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0648 BPF_MOV64_IMM(BPF_REG_0, 0),
0649 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0650
0651 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0652
0653
0654 BPF_MOV64_IMM(BPF_REG_3, 8),
0655
0656
0657 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0658
0659
0660 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
0661
0662
0663 BPF_MOV64_IMM(BPF_REG_0, 1),
0664 BPF_JMP_A(1),
0665
0666
0667 BPF_MOV64_IMM(BPF_REG_0, 0),
0668 BPF_EXIT_INSN(),
0669 },
0670 .attach_type = BPF_CGROUP_SYSCTL,
0671 .sysctl = "net/ipv4/tcp_mem",
0672 .open_flags = O_RDONLY,
0673 .result = SUCCESS,
0674 },
0675 {
0676 .descr = "sysctl_get_new_value sysctl:write ok",
0677 .insns = {
0678
0679 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0680 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0681
0682 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0683
0684
0685 BPF_MOV64_IMM(BPF_REG_3, 4),
0686
0687
0688 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0689
0690
0691 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
0692
0693
0694 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
0695 BPF_JMP_IMM(BPF_JNE, BPF_REG_9,
0696 bpf_ntohl(0x36303600), 2),
0697
0698
0699 BPF_MOV64_IMM(BPF_REG_0, 0),
0700 BPF_JMP_A(1),
0701
0702
0703 BPF_MOV64_IMM(BPF_REG_0, 1),
0704 BPF_EXIT_INSN(),
0705 },
0706 .attach_type = BPF_CGROUP_SYSCTL,
0707 .sysctl = "net/ipv4/route/mtu_expires",
0708 .open_flags = O_WRONLY,
0709 .newval = "606",
0710 .result = OP_EPERM,
0711 },
0712 {
0713 .descr = "sysctl_get_new_value sysctl:write ok long",
0714 .insns = {
0715
0716 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0717 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
0718
0719 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0720
0721
0722 BPF_MOV64_IMM(BPF_REG_3, 24),
0723
0724
0725 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0726
0727
0728 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14),
0729
0730
0731 BPF_LD_IMM64(BPF_REG_8,
0732 bpf_be64_to_cpu(0x3330303030303020ULL)),
0733 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0734 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10),
0735
0736
0737 BPF_LD_IMM64(BPF_REG_8,
0738 bpf_be64_to_cpu(0x3430303030303020ULL)),
0739 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
0740 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
0741
0742
0743 BPF_LD_IMM64(BPF_REG_8,
0744 bpf_be64_to_cpu(0x3630303030303000ULL)),
0745 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16),
0746 BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
0747
0748
0749 BPF_MOV64_IMM(BPF_REG_0, 0),
0750 BPF_JMP_A(1),
0751
0752
0753 BPF_MOV64_IMM(BPF_REG_0, 1),
0754 BPF_EXIT_INSN(),
0755 },
0756 .attach_type = BPF_CGROUP_SYSCTL,
0757 .sysctl = "net/ipv4/tcp_mem",
0758 .open_flags = O_WRONLY,
0759 .newval = "3000000 4000000 6000000",
0760 .result = OP_EPERM,
0761 },
0762 {
0763 .descr = "sysctl_get_new_value sysctl:write E2BIG",
0764 .insns = {
0765
0766 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0767 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0768 BPF_MOV64_IMM(BPF_REG_0, 0),
0769 BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 3),
0770
0771 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0772
0773
0774 BPF_MOV64_IMM(BPF_REG_3, 3),
0775
0776
0777 BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0778
0779
0780 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4),
0781
0782
0783 BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
0784 BPF_JMP_IMM(BPF_JNE, BPF_REG_9,
0785 bpf_ntohl(0x36300000), 2),
0786
0787
0788 BPF_MOV64_IMM(BPF_REG_0, 0),
0789 BPF_JMP_A(1),
0790
0791
0792 BPF_MOV64_IMM(BPF_REG_0, 1),
0793 BPF_EXIT_INSN(),
0794 },
0795 .attach_type = BPF_CGROUP_SYSCTL,
0796 .sysctl = "net/ipv4/route/mtu_expires",
0797 .open_flags = O_WRONLY,
0798 .newval = "606",
0799 .result = OP_EPERM,
0800 },
0801 {
0802 .descr = "sysctl_set_new_value sysctl:read EINVAL",
0803 .insns = {
0804
0805 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0806 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0807 BPF_MOV64_IMM(BPF_REG_0,
0808 bpf_ntohl(0x36303000)),
0809 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0810
0811 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0812
0813
0814 BPF_MOV64_IMM(BPF_REG_3, 3),
0815
0816
0817 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
0818
0819
0820 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
0821
0822
0823 BPF_MOV64_IMM(BPF_REG_0, 1),
0824 BPF_JMP_A(1),
0825
0826
0827 BPF_MOV64_IMM(BPF_REG_0, 0),
0828 BPF_EXIT_INSN(),
0829 },
0830 .attach_type = BPF_CGROUP_SYSCTL,
0831 .sysctl = "net/ipv4/route/mtu_expires",
0832 .open_flags = O_RDONLY,
0833 .result = SUCCESS,
0834 },
0835 {
0836 .descr = "sysctl_set_new_value sysctl:write ok",
0837 .fixup_value_insn = 2,
0838 .insns = {
0839
0840 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0841 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0842 BPF_LD_IMM64(BPF_REG_0, FIXUP_SYSCTL_VALUE),
0843 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0844
0845 BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
0846
0847
0848 BPF_MOV64_IMM(BPF_REG_3, 3),
0849
0850
0851 BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
0852
0853
0854 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
0855
0856
0857 BPF_MOV64_IMM(BPF_REG_0, 1),
0858 BPF_JMP_A(1),
0859
0860
0861 BPF_MOV64_IMM(BPF_REG_0, 0),
0862 BPF_EXIT_INSN(),
0863 },
0864 .attach_type = BPF_CGROUP_SYSCTL,
0865 .sysctl = "net/ipv4/route/mtu_expires",
0866 .open_flags = O_WRONLY,
0867 .newval = "606",
0868 .result = SUCCESS,
0869 },
0870 {
0871 "bpf_strtoul one number string",
0872 .insns = {
0873
0874 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0875 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0876 BPF_MOV64_IMM(BPF_REG_0,
0877 bpf_ntohl(0x36303000)),
0878 BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
0879
0880 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
0881
0882
0883 BPF_MOV64_IMM(BPF_REG_2, 4),
0884
0885
0886 BPF_MOV64_IMM(BPF_REG_3, 0),
0887
0888
0889 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0890 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0891 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
0892
0893 BPF_EMIT_CALL(BPF_FUNC_strtoul),
0894
0895
0896 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
0897
0898 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0899 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 2),
0900
0901
0902 BPF_MOV64_IMM(BPF_REG_0, 1),
0903 BPF_JMP_A(1),
0904
0905
0906 BPF_MOV64_IMM(BPF_REG_0, 0),
0907 BPF_EXIT_INSN(),
0908 },
0909 .attach_type = BPF_CGROUP_SYSCTL,
0910 .sysctl = "net/ipv4/route/mtu_expires",
0911 .open_flags = O_RDONLY,
0912 .result = SUCCESS,
0913 },
0914 {
0915 "bpf_strtoul multi number string",
0916 .insns = {
0917
0918 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0919 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0920
0921 BPF_LD_IMM64(BPF_REG_0,
0922 bpf_be64_to_cpu(0x3630302036303200ULL)),
0923 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0924 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
0925
0926
0927 BPF_MOV64_IMM(BPF_REG_2, 8),
0928
0929
0930 BPF_MOV64_IMM(BPF_REG_3, 0),
0931
0932
0933 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0934 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0935 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
0936
0937 BPF_EMIT_CALL(BPF_FUNC_strtoul),
0938
0939
0940 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18),
0941
0942 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0943 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 16),
0944
0945
0946 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0947 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0948 BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0),
0949 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
0950
0951
0952 BPF_MOV64_IMM(BPF_REG_2, 8),
0953 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0),
0954
0955
0956 BPF_MOV64_IMM(BPF_REG_3, 0),
0957
0958
0959 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0960 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
0961 BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
0962
0963 BPF_EMIT_CALL(BPF_FUNC_strtoul),
0964
0965
0966 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
0967
0968 BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
0969 BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 602, 2),
0970
0971
0972 BPF_MOV64_IMM(BPF_REG_0, 1),
0973 BPF_JMP_A(1),
0974
0975
0976 BPF_MOV64_IMM(BPF_REG_0, 0),
0977 BPF_EXIT_INSN(),
0978 },
0979 .attach_type = BPF_CGROUP_SYSCTL,
0980 .sysctl = "net/ipv4/tcp_mem",
0981 .open_flags = O_RDONLY,
0982 .result = SUCCESS,
0983 },
0984 {
0985 "bpf_strtoul buf_len = 0, reject",
0986 .insns = {
0987
0988 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0989 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0990 BPF_MOV64_IMM(BPF_REG_0,
0991 bpf_ntohl(0x36303000)),
0992 BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
0993
0994 BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
0995
0996
0997 BPF_MOV64_IMM(BPF_REG_2, 0),
0998
0999
1000 BPF_MOV64_IMM(BPF_REG_3, 0),
1001
1002
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
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
1030 BPF_MOV64_IMM(BPF_REG_2, 4),
1031
1032
1033 BPF_MOV64_IMM(BPF_REG_3, 8),
1034
1035
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
1043 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1044
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
1049 BPF_MOV64_IMM(BPF_REG_0, 1),
1050 BPF_JMP_A(1),
1051
1052
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
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
1074 BPF_MOV64_IMM(BPF_REG_2, 4),
1075
1076
1077 BPF_MOV64_IMM(BPF_REG_3, 3),
1078
1079
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
1087 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1088
1089
1090 BPF_MOV64_IMM(BPF_REG_0, 1),
1091 BPF_JMP_A(1),
1092
1093
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
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
1115 BPF_MOV64_IMM(BPF_REG_2, 4),
1116
1117
1118 BPF_MOV64_IMM(BPF_REG_3, 0),
1119
1120
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
1128 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1129
1130
1131 BPF_MOV64_IMM(BPF_REG_0, 1),
1132 BPF_JMP_A(1),
1133
1134
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
1147 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1148 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1149
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
1157 BPF_MOV64_IMM(BPF_REG_2, 4),
1158
1159
1160 BPF_MOV64_IMM(BPF_REG_3, 0),
1161
1162
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
1170 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1171
1172
1173 BPF_MOV64_IMM(BPF_REG_0, 1),
1174 BPF_JMP_A(1),
1175
1176
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
1189 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1190 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1191
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
1199 BPF_MOV64_IMM(BPF_REG_2, 4),
1200
1201
1202 BPF_MOV64_IMM(BPF_REG_3, 10),
1203
1204
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
1212 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1213
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
1218 BPF_MOV64_IMM(BPF_REG_0, 1),
1219 BPF_JMP_A(1),
1220
1221
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
1234 BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1235 BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1236
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
1244 BPF_MOV64_IMM(BPF_REG_2, 4),
1245
1246
1247 BPF_MOV64_IMM(BPF_REG_3, 0),
1248
1249
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
1257 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
1258
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
1263 BPF_MOV64_IMM(BPF_REG_0, 1),
1264 BPF_JMP_A(1),
1265
1266
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
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
1294 BPF_MOV64_IMM(BPF_REG_2, 19),
1295
1296
1297 BPF_MOV64_IMM(BPF_REG_3, 0),
1298
1299
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
1307 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 19, 6),
1308
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
1314 BPF_MOV64_IMM(BPF_REG_0, 1),
1315 BPF_JMP_A(1),
1316
1317
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
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
1345 BPF_MOV64_IMM(BPF_REG_2, 19),
1346
1347
1348 BPF_MOV64_IMM(BPF_REG_3, 0),
1349
1350
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
1358 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2),
1359
1360
1361 BPF_MOV64_IMM(BPF_REG_0, 1),
1362 BPF_JMP_A(1),
1363
1364
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.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.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.o",
1393 .attach_type = BPF_CGROUP_SYSCTL,
1394 .sysctl = "net/ipv4/tcp_mem",
1395 .open_flags = O_RDONLY,
1396 .result = SUCCESS,
1397 },
1398 };
1399
1400 static 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
1410 static 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
1434 static 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
1476 static 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
1491 static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path)
1492 {
1493 return test->prog_file
1494 ? load_sysctl_prog_file(test)
1495 : load_sysctl_prog_insns(test, sysctl_path);
1496 }
1497
1498 static 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;
1536 err:
1537 err = -1;
1538 out:
1539 close(fd);
1540 return err;
1541 }
1542
1543 static 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 else
1560 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 else
1567 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 else
1575 goto err;
1576 }
1577
1578 if (test->result != SUCCESS) {
1579 log_err("Unexpected success");
1580 goto err;
1581 }
1582
1583 goto out;
1584 err:
1585 err = -1;
1586 out:
1587
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
1595 static 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 else
1605 ++passes;
1606 }
1607 printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1608 return fails ? -1 : 0;
1609 }
1610
1611 int 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
1621 libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1622
1623 if (run_tests(cgfd))
1624 goto err;
1625
1626 goto out;
1627 err:
1628 err = -1;
1629 out:
1630 close(cgfd);
1631 cleanup_cgroup_environment();
1632 return err;
1633 }