Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2019 Facebook
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             /* If (write) */
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             /* return DENY; */
0089             BPF_MOV64_IMM(BPF_REG_0, 0),
0090             BPF_JMP_A(1),
0091 
0092             /* else return ALLOW; */
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             /* If (write) */
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             /* return DENY; */
0110             BPF_MOV64_IMM(BPF_REG_0, 0),
0111             BPF_JMP_A(1),
0112 
0113             /* else return ALLOW; */
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)", /* same as default, should fail anyway */
0121         .result = OP_EPERM,
0122     },
0123     {
0124         .descr = "ctx:write sysctl:write read ok narrow",
0125         .insns = {
0126             /* u64 w = (u16)write & 1; */
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             /* return 1 - w; */
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)", /* same as default, should fail anyway */
0144         .result = OP_EPERM,
0145     },
0146     {
0147         .descr = "ctx:write sysctl:read write reject",
0148         .insns = {
0149             /* write = X */
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             /* If (file_pos == X) */
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             /* return ALLOW; */
0170             BPF_MOV64_IMM(BPF_REG_0, 1),
0171             BPF_JMP_A(1),
0172 
0173             /* else return DENY; */
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             /* If (file_pos == X) */
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             /* return ALLOW; */
0197             BPF_MOV64_IMM(BPF_REG_0, 1),
0198             BPF_JMP_A(1),
0199 
0200             /* else return DENY; */
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             /* file_pos = X */
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             /* sysctl_get_name arg2 (buf) */
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             /* sysctl_get_name arg3 (buf_len) */
0238             BPF_MOV64_IMM(BPF_REG_3, 8),
0239 
0240             /* sysctl_get_name arg4 (flags) */
0241             BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
0242 
0243             /* sysctl_get_name(ctx, buf, buf_len, flags) */
0244             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0245 
0246             /* if (ret == expected && */
0247             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6),
0248             /*     buf == "tcp_mem\0") */
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             /* return ALLOW; */
0255             BPF_MOV64_IMM(BPF_REG_0, 1),
0256             BPF_JMP_A(1),
0257 
0258             /* else return DENY; */
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             /* sysctl_get_name arg2 (buf) */
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             /* sysctl_get_name arg3 (buf_len) too small */
0279             BPF_MOV64_IMM(BPF_REG_3, 7),
0280 
0281             /* sysctl_get_name arg4 (flags) */
0282             BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
0283 
0284             /* sysctl_get_name(ctx, buf, buf_len, flags) */
0285             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0286 
0287             /* if (ret == expected && */
0288             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
0289 
0290             /*     buf[0:7] == "tcp_me\0") */
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             /* return ALLOW; */
0297             BPF_MOV64_IMM(BPF_REG_0, 1),
0298             BPF_JMP_A(1),
0299 
0300             /* else return DENY; */
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             /* sysctl_get_name arg2 (buf) */
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             /* sysctl_get_name arg3 (buf_len) */
0323             BPF_MOV64_IMM(BPF_REG_3, 17),
0324 
0325             /* sysctl_get_name arg4 (flags) */
0326             BPF_MOV64_IMM(BPF_REG_4, 0),
0327 
0328             /* sysctl_get_name(ctx, buf, buf_len, flags) */
0329             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0330 
0331             /* if (ret == expected && */
0332             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14),
0333 
0334             /*     buf[0:8] == "net/ipv4" && */
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             /*     buf[8:16] == "/tcp_mem" && */
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             /*     buf[16:24] == "\0") */
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             /* return ALLOW; */
0352             BPF_MOV64_IMM(BPF_REG_0, 1),
0353             BPF_JMP_A(1),
0354 
0355             /* else return DENY; */
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             /* sysctl_get_name arg2 (buf) */
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             /* sysctl_get_name arg3 (buf_len) */
0377             BPF_MOV64_IMM(BPF_REG_3, 16),
0378 
0379             /* sysctl_get_name arg4 (flags) */
0380             BPF_MOV64_IMM(BPF_REG_4, 0),
0381 
0382             /* sysctl_get_name(ctx, buf, buf_len, flags) */
0383             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0384 
0385             /* if (ret == expected && */
0386             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10),
0387 
0388             /*     buf[0:8] == "net/ipv4" && */
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             /*     buf[8:16] == "/tcp_me\0") */
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             /* return ALLOW; */
0401             BPF_MOV64_IMM(BPF_REG_0, 1),
0402             BPF_JMP_A(1),
0403 
0404             /* else return DENY; */
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             /* sysctl_get_name arg2 (buf) */
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             /* sysctl_get_name arg3 (buf_len) */
0425             BPF_MOV64_IMM(BPF_REG_3, 7),
0426 
0427             /* sysctl_get_name arg4 (flags) */
0428             BPF_MOV64_IMM(BPF_REG_4, 0),
0429 
0430             /* sysctl_get_name(ctx, buf, buf_len, flags) */
0431             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
0432 
0433             /* if (ret == expected && */
0434             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
0435 
0436             /*     buf[0:8] == "net/ip\0") */
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             /* return ALLOW; */
0443             BPF_MOV64_IMM(BPF_REG_0, 1),
0444             BPF_JMP_A(1),
0445 
0446             /* else return DENY; */
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             /* sysctl_get_current_value arg2 (buf) */
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             /* sysctl_get_current_value arg3 (buf_len) */
0464             BPF_MOV64_IMM(BPF_REG_3, 8),
0465 
0466             /* sysctl_get_current_value(ctx, buf, buf_len) */
0467             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0468 
0469             /* if (ret == expected && */
0470             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
0471 
0472             /*     buf[0:6] == "Linux\n\0") */
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             /* return ALLOW; */
0479             BPF_MOV64_IMM(BPF_REG_0, 1),
0480             BPF_JMP_A(1),
0481 
0482             /* else return DENY; */
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             /* sysctl_get_current_value arg2 (buf) */
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             /* sysctl_get_current_value arg3 (buf_len) */
0503             BPF_MOV64_IMM(BPF_REG_3, 7),
0504 
0505             /* sysctl_get_current_value(ctx, buf, buf_len) */
0506             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0507 
0508             /* if (ret == expected && */
0509             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
0510 
0511             /*     buf[0:6] == "Linux\n\0") */
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             /* return ALLOW; */
0518             BPF_MOV64_IMM(BPF_REG_0, 1),
0519             BPF_JMP_A(1),
0520 
0521             /* else return DENY; */
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             /* sysctl_get_current_value arg2 (buf) */
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             /* sysctl_get_current_value arg3 (buf_len) */
0542             BPF_MOV64_IMM(BPF_REG_3, 6),
0543 
0544             /* sysctl_get_current_value(ctx, buf, buf_len) */
0545             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0546 
0547             /* if (ret == expected && */
0548             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
0549 
0550             /*     buf[0:6] == "Linux\0") */
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             /* return ALLOW; */
0557             BPF_MOV64_IMM(BPF_REG_0, 1),
0558             BPF_JMP_A(1),
0559 
0560             /* else return DENY; */
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             /* sysctl_get_current_value arg2 (buf) */
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             /* sysctl_get_current_value arg3 (buf_len) */
0579             BPF_MOV64_IMM(BPF_REG_3, 8),
0580 
0581             /* sysctl_get_current_value(ctx, buf, buf_len) */
0582             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0583 
0584             /* if (ret == expected && */
0585             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4),
0586 
0587             /*     buf[0:8] is NUL-filled) */
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             /* return DENY; */
0592             BPF_MOV64_IMM(BPF_REG_0, 0),
0593             BPF_JMP_A(1),
0594 
0595             /* else return ALLOW; */
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", /* -EIO */
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             /* sysctl_get_current_value arg2 (buf) */
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             /* sysctl_get_current_value arg3 (buf_len) */
0615             BPF_MOV64_IMM(BPF_REG_3, 8),
0616 
0617             /* sysctl_get_current_value(ctx, buf, buf_len) */
0618             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
0619 
0620             /* if (ret == expected && */
0621             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6),
0622 
0623             /*     buf[0:4] == expected) */
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             /* return DENY; */
0629             BPF_MOV64_IMM(BPF_REG_0, 0),
0630             BPF_JMP_A(1),
0631 
0632             /* else return ALLOW; */
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", /* same as default, should fail anyway */
0640         .result = OP_EPERM,
0641     },
0642     {
0643         .descr = "sysctl_get_new_value sysctl:read EINVAL",
0644         .insns = {
0645             /* sysctl_get_new_value arg2 (buf) */
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             /* sysctl_get_new_value arg3 (buf_len) */
0654             BPF_MOV64_IMM(BPF_REG_3, 8),
0655 
0656             /* sysctl_get_new_value(ctx, buf, buf_len) */
0657             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0658 
0659             /* if (ret == expected) */
0660             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
0661 
0662             /* return ALLOW; */
0663             BPF_MOV64_IMM(BPF_REG_0, 1),
0664             BPF_JMP_A(1),
0665 
0666             /* else return DENY; */
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             /* sysctl_get_new_value arg2 (buf) */
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             /* sysctl_get_new_value arg3 (buf_len) */
0685             BPF_MOV64_IMM(BPF_REG_3, 4),
0686 
0687             /* sysctl_get_new_value(ctx, buf, buf_len) */
0688             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0689 
0690             /* if (ret == expected && */
0691             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
0692 
0693             /*     buf[0:4] == "606\0") */
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             /* return DENY; */
0699             BPF_MOV64_IMM(BPF_REG_0, 0),
0700             BPF_JMP_A(1),
0701 
0702             /* else return ALLOW; */
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             /* sysctl_get_new_value arg2 (buf) */
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             /* sysctl_get_new_value arg3 (buf_len) */
0722             BPF_MOV64_IMM(BPF_REG_3, 24),
0723 
0724             /* sysctl_get_new_value(ctx, buf, buf_len) */
0725             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0726 
0727             /* if (ret == expected && */
0728             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14),
0729 
0730             /*     buf[0:8] == "3000000 " && */
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             /*     buf[8:16] == "4000000 " && */
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             /*     buf[16:24] == "6000000\0") */
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             /* return DENY; */
0749             BPF_MOV64_IMM(BPF_REG_0, 0),
0750             BPF_JMP_A(1),
0751 
0752             /* else return ALLOW; */
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             /* sysctl_get_new_value arg2 (buf) */
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             /* sysctl_get_new_value arg3 (buf_len) */
0774             BPF_MOV64_IMM(BPF_REG_3, 3),
0775 
0776             /* sysctl_get_new_value(ctx, buf, buf_len) */
0777             BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
0778 
0779             /* if (ret == expected && */
0780             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4),
0781 
0782             /*     buf[0:3] == "60\0") */
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             /* return DENY; */
0788             BPF_MOV64_IMM(BPF_REG_0, 0),
0789             BPF_JMP_A(1),
0790 
0791             /* else return ALLOW; */
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             /* sysctl_set_new_value arg2 (buf) */
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             /* sysctl_set_new_value arg3 (buf_len) */
0814             BPF_MOV64_IMM(BPF_REG_3, 3),
0815 
0816             /* sysctl_set_new_value(ctx, buf, buf_len) */
0817             BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
0818 
0819             /* if (ret == expected) */
0820             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
0821 
0822             /* return ALLOW; */
0823             BPF_MOV64_IMM(BPF_REG_0, 1),
0824             BPF_JMP_A(1),
0825 
0826             /* else return DENY; */
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             /* sysctl_set_new_value arg2 (buf) */
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             /* sysctl_set_new_value arg3 (buf_len) */
0848             BPF_MOV64_IMM(BPF_REG_3, 3),
0849 
0850             /* sysctl_set_new_value(ctx, buf, buf_len) */
0851             BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
0852 
0853             /* if (ret == expected) */
0854             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
0855 
0856             /* return ALLOW; */
0857             BPF_MOV64_IMM(BPF_REG_0, 1),
0858             BPF_JMP_A(1),
0859 
0860             /* else return DENY; */
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             /* arg1 (buf) */
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             /* arg2 (buf_len) */
0883             BPF_MOV64_IMM(BPF_REG_2, 4),
0884 
0885             /* arg3 (flags) */
0886             BPF_MOV64_IMM(BPF_REG_3, 0),
0887 
0888             /* arg4 (res) */
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             /* if (ret == expected && */
0896             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
0897             /*     res == expected) */
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             /* return ALLOW; */
0902             BPF_MOV64_IMM(BPF_REG_0, 1),
0903             BPF_JMP_A(1),
0904 
0905             /* else return DENY; */
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             /* arg1 (buf) */
0918             BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
0919             BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
0920             /* "600 602\0" */
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             /* arg2 (buf_len) */
0927             BPF_MOV64_IMM(BPF_REG_2, 8),
0928 
0929             /* arg3 (flags) */
0930             BPF_MOV64_IMM(BPF_REG_3, 0),
0931 
0932             /* arg4 (res) */
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             /* if (ret == expected && */
0940             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18),
0941             /*     res == expected) */
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             /*     arg1 (buf) */
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             /*     arg2 (buf_len) */
0952             BPF_MOV64_IMM(BPF_REG_2, 8),
0953             BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0),
0954 
0955             /*     arg3 (flags) */
0956             BPF_MOV64_IMM(BPF_REG_3, 0),
0957 
0958             /*     arg4 (res) */
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             /*     if (ret == expected && */
0966             BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
0967             /*         res == expected) */
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             /* return ALLOW; */
0972             BPF_MOV64_IMM(BPF_REG_0, 1),
0973             BPF_JMP_A(1),
0974 
0975             /* else return DENY; */
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             /* arg1 (buf) */
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             /* arg2 (buf_len) */
0997             BPF_MOV64_IMM(BPF_REG_2, 0),
0998 
0999             /* 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.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     /* 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 
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     /* 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;
1627 err:
1628     err = -1;
1629 out:
1630     close(cgfd);
1631     cleanup_cgroup_environment();
1632     return err;
1633 }