root/tools/testing/selftests/bpf/test_sysctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. probe_prog_length
  2. fixup_sysctl_value
  3. load_sysctl_prog_insns
  4. load_sysctl_prog_file
  5. load_sysctl_prog
  6. access_sysctl
  7. run_test_case
  8. run_tests
  9. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 // Copyright (c) 2019 Facebook
   3 
   4 #include <fcntl.h>
   5 #include <stdint.h>
   6 #include <stdio.h>
   7 #include <stdlib.h>
   8 #include <string.h>
   9 #include <unistd.h>
  10 
  11 #include <linux/filter.h>
  12 
  13 #include <bpf/bpf.h>
  14 #include <bpf/libbpf.h>
  15 
  16 #include "bpf_endian.h"
  17 #include "bpf_rlimit.h"
  18 #include "bpf_util.h"
  19 #include "cgroup_helpers.h"
  20 
  21 #define CG_PATH                 "/foo"
  22 #define MAX_INSNS               512
  23 #define FIXUP_SYSCTL_VALUE      0
  24 
  25 char bpf_log_buf[BPF_LOG_BUF_SIZE];
  26 
  27 struct sysctl_test {
  28         const char *descr;
  29         size_t fixup_value_insn;
  30         struct bpf_insn insns[MAX_INSNS];
  31         const char *prog_file;
  32         enum bpf_attach_type attach_type;
  33         const char *sysctl;
  34         int open_flags;
  35         int seek;
  36         const char *newval;
  37         const char *oldval;
  38         enum {
  39                 LOAD_REJECT,
  40                 ATTACH_REJECT,
  41                 OP_EPERM,
  42                 SUCCESS,
  43         } result;
  44 };
  45 
  46 static struct sysctl_test tests[] = {
  47         {
  48                 .descr = "sysctl wrong attach_type",
  49                 .insns = {
  50                         BPF_MOV64_IMM(BPF_REG_0, 1),
  51                         BPF_EXIT_INSN(),
  52                 },
  53                 .attach_type = 0,
  54                 .sysctl = "kernel/ostype",
  55                 .open_flags = O_RDONLY,
  56                 .result = ATTACH_REJECT,
  57         },
  58         {
  59                 .descr = "sysctl:read allow all",
  60                 .insns = {
  61                         BPF_MOV64_IMM(BPF_REG_0, 1),
  62                         BPF_EXIT_INSN(),
  63                 },
  64                 .attach_type = BPF_CGROUP_SYSCTL,
  65                 .sysctl = "kernel/ostype",
  66                 .open_flags = O_RDONLY,
  67                 .result = SUCCESS,
  68         },
  69         {
  70                 .descr = "sysctl:read deny all",
  71                 .insns = {
  72                         BPF_MOV64_IMM(BPF_REG_0, 0),
  73                         BPF_EXIT_INSN(),
  74                 },
  75                 .attach_type = BPF_CGROUP_SYSCTL,
  76                 .sysctl = "kernel/ostype",
  77                 .open_flags = O_RDONLY,
  78                 .result = OP_EPERM,
  79         },
  80         {
  81                 .descr = "ctx:write sysctl:read read ok",
  82                 .insns = {
  83                         /* If (write) */
  84                         BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
  85                                     offsetof(struct bpf_sysctl, write)),
  86                         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2),
  87 
  88                         /* return DENY; */
  89                         BPF_MOV64_IMM(BPF_REG_0, 0),
  90                         BPF_JMP_A(1),
  91 
  92                         /* else return ALLOW; */
  93                         BPF_MOV64_IMM(BPF_REG_0, 1),
  94                         BPF_EXIT_INSN(),
  95                 },
  96                 .attach_type = BPF_CGROUP_SYSCTL,
  97                 .sysctl = "kernel/ostype",
  98                 .open_flags = O_RDONLY,
  99                 .result = SUCCESS,
 100         },
 101         {
 102                 .descr = "ctx:write sysctl:write read ok",
 103                 .insns = {
 104                         /* If (write) */
 105                         BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
 106                                     offsetof(struct bpf_sysctl, write)),
 107                         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 1, 2),
 108 
 109                         /* return DENY; */
 110                         BPF_MOV64_IMM(BPF_REG_0, 0),
 111                         BPF_JMP_A(1),
 112 
 113                         /* else return ALLOW; */
 114                         BPF_MOV64_IMM(BPF_REG_0, 1),
 115                         BPF_EXIT_INSN(),
 116                 },
 117                 .attach_type = BPF_CGROUP_SYSCTL,
 118                 .sysctl = "kernel/domainname",
 119                 .open_flags = O_WRONLY,
 120                 .newval = "(none)", /* same as default, should fail anyway */
 121                 .result = OP_EPERM,
 122         },
 123         {
 124                 .descr = "ctx:write sysctl:read write reject",
 125                 .insns = {
 126                         /* write = X */
 127                         BPF_MOV64_IMM(BPF_REG_0, 0),
 128                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
 129                                     offsetof(struct bpf_sysctl, write)),
 130                         BPF_MOV64_IMM(BPF_REG_0, 1),
 131                         BPF_EXIT_INSN(),
 132                 },
 133                 .attach_type = BPF_CGROUP_SYSCTL,
 134                 .sysctl = "kernel/ostype",
 135                 .open_flags = O_RDONLY,
 136                 .result = LOAD_REJECT,
 137         },
 138         {
 139                 .descr = "ctx:file_pos sysctl:read read ok",
 140                 .insns = {
 141                         /* If (file_pos == X) */
 142                         BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_1,
 143                                     offsetof(struct bpf_sysctl, file_pos)),
 144                         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 3, 2),
 145 
 146                         /* return ALLOW; */
 147                         BPF_MOV64_IMM(BPF_REG_0, 1),
 148                         BPF_JMP_A(1),
 149 
 150                         /* else return DENY; */
 151                         BPF_MOV64_IMM(BPF_REG_0, 0),
 152                         BPF_EXIT_INSN(),
 153                 },
 154                 .attach_type = BPF_CGROUP_SYSCTL,
 155                 .sysctl = "kernel/ostype",
 156                 .open_flags = O_RDONLY,
 157                 .seek = 3,
 158                 .result = SUCCESS,
 159         },
 160         {
 161                 .descr = "ctx:file_pos sysctl:read read ok narrow",
 162                 .insns = {
 163                         /* If (file_pos == X) */
 164 #if __BYTE_ORDER == __LITTLE_ENDIAN
 165                         BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
 166                                     offsetof(struct bpf_sysctl, file_pos)),
 167 #else
 168                         BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_1,
 169                                     offsetof(struct bpf_sysctl, file_pos) + 3),
 170 #endif
 171                         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 4, 2),
 172 
 173                         /* return ALLOW; */
 174                         BPF_MOV64_IMM(BPF_REG_0, 1),
 175                         BPF_JMP_A(1),
 176 
 177                         /* else return DENY; */
 178                         BPF_MOV64_IMM(BPF_REG_0, 0),
 179                         BPF_EXIT_INSN(),
 180                 },
 181                 .attach_type = BPF_CGROUP_SYSCTL,
 182                 .sysctl = "kernel/ostype",
 183                 .open_flags = O_RDONLY,
 184                 .seek = 4,
 185                 .result = SUCCESS,
 186         },
 187         {
 188                 .descr = "ctx:file_pos sysctl:read write ok",
 189                 .insns = {
 190                         /* file_pos = X */
 191                         BPF_MOV64_IMM(BPF_REG_0, 2),
 192                         BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_0,
 193                                     offsetof(struct bpf_sysctl, file_pos)),
 194                         BPF_MOV64_IMM(BPF_REG_0, 1),
 195                         BPF_EXIT_INSN(),
 196                 },
 197                 .attach_type = BPF_CGROUP_SYSCTL,
 198                 .sysctl = "kernel/ostype",
 199                 .open_flags = O_RDONLY,
 200                 .oldval = "nux\n",
 201                 .result = SUCCESS,
 202         },
 203         {
 204                 .descr = "sysctl_get_name sysctl_value:base ok",
 205                 .insns = {
 206                         /* sysctl_get_name arg2 (buf) */
 207                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 208                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 209                         BPF_MOV64_IMM(BPF_REG_0, 0),
 210                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 211 
 212                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 213 
 214                         /* sysctl_get_name arg3 (buf_len) */
 215                         BPF_MOV64_IMM(BPF_REG_3, 8),
 216 
 217                         /* sysctl_get_name arg4 (flags) */
 218                         BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
 219 
 220                         /* sysctl_get_name(ctx, buf, buf_len, flags) */
 221                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
 222 
 223                         /* if (ret == expected && */
 224                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, sizeof("tcp_mem") - 1, 6),
 225                         /*     buf == "tcp_mem\0") */
 226                         BPF_LD_IMM64(BPF_REG_8,
 227                                      bpf_be64_to_cpu(0x7463705f6d656d00ULL)),
 228                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 229                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 230 
 231                         /* return ALLOW; */
 232                         BPF_MOV64_IMM(BPF_REG_0, 1),
 233                         BPF_JMP_A(1),
 234 
 235                         /* else return DENY; */
 236                         BPF_MOV64_IMM(BPF_REG_0, 0),
 237                         BPF_EXIT_INSN(),
 238                 },
 239                 .attach_type = BPF_CGROUP_SYSCTL,
 240                 .sysctl = "net/ipv4/tcp_mem",
 241                 .open_flags = O_RDONLY,
 242                 .result = SUCCESS,
 243         },
 244         {
 245                 .descr = "sysctl_get_name sysctl_value:base E2BIG truncated",
 246                 .insns = {
 247                         /* sysctl_get_name arg2 (buf) */
 248                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 249                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 250                         BPF_MOV64_IMM(BPF_REG_0, 0),
 251                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 252 
 253                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 254 
 255                         /* sysctl_get_name arg3 (buf_len) too small */
 256                         BPF_MOV64_IMM(BPF_REG_3, 7),
 257 
 258                         /* sysctl_get_name arg4 (flags) */
 259                         BPF_MOV64_IMM(BPF_REG_4, BPF_F_SYSCTL_BASE_NAME),
 260 
 261                         /* sysctl_get_name(ctx, buf, buf_len, flags) */
 262                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
 263 
 264                         /* if (ret == expected && */
 265                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
 266 
 267                         /*     buf[0:7] == "tcp_me\0") */
 268                         BPF_LD_IMM64(BPF_REG_8,
 269                                      bpf_be64_to_cpu(0x7463705f6d650000ULL)),
 270                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 271                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 272 
 273                         /* return ALLOW; */
 274                         BPF_MOV64_IMM(BPF_REG_0, 1),
 275                         BPF_JMP_A(1),
 276 
 277                         /* else return DENY; */
 278                         BPF_MOV64_IMM(BPF_REG_0, 0),
 279                         BPF_EXIT_INSN(),
 280                 },
 281                 .attach_type = BPF_CGROUP_SYSCTL,
 282                 .sysctl = "net/ipv4/tcp_mem",
 283                 .open_flags = O_RDONLY,
 284                 .result = SUCCESS,
 285         },
 286         {
 287                 .descr = "sysctl_get_name sysctl:full ok",
 288                 .insns = {
 289                         /* sysctl_get_name arg2 (buf) */
 290                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 291                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
 292                         BPF_MOV64_IMM(BPF_REG_0, 0),
 293                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 294                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
 295                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16),
 296 
 297                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 298 
 299                         /* sysctl_get_name arg3 (buf_len) */
 300                         BPF_MOV64_IMM(BPF_REG_3, 17),
 301 
 302                         /* sysctl_get_name arg4 (flags) */
 303                         BPF_MOV64_IMM(BPF_REG_4, 0),
 304 
 305                         /* sysctl_get_name(ctx, buf, buf_len, flags) */
 306                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
 307 
 308                         /* if (ret == expected && */
 309                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 16, 14),
 310 
 311                         /*     buf[0:8] == "net/ipv4" && */
 312                         BPF_LD_IMM64(BPF_REG_8,
 313                                      bpf_be64_to_cpu(0x6e65742f69707634ULL)),
 314                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 315                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10),
 316 
 317                         /*     buf[8:16] == "/tcp_mem" && */
 318                         BPF_LD_IMM64(BPF_REG_8,
 319                                      bpf_be64_to_cpu(0x2f7463705f6d656dULL)),
 320                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
 321                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
 322 
 323                         /*     buf[16:24] == "\0") */
 324                         BPF_LD_IMM64(BPF_REG_8, 0x0ULL),
 325                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16),
 326                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 327 
 328                         /* return ALLOW; */
 329                         BPF_MOV64_IMM(BPF_REG_0, 1),
 330                         BPF_JMP_A(1),
 331 
 332                         /* else return DENY; */
 333                         BPF_MOV64_IMM(BPF_REG_0, 0),
 334                         BPF_EXIT_INSN(),
 335                 },
 336                 .attach_type = BPF_CGROUP_SYSCTL,
 337                 .sysctl = "net/ipv4/tcp_mem",
 338                 .open_flags = O_RDONLY,
 339                 .result = SUCCESS,
 340         },
 341         {
 342                 .descr = "sysctl_get_name sysctl:full E2BIG truncated",
 343                 .insns = {
 344                         /* sysctl_get_name arg2 (buf) */
 345                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 346                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
 347                         BPF_MOV64_IMM(BPF_REG_0, 0),
 348                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 349                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
 350 
 351                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 352 
 353                         /* sysctl_get_name arg3 (buf_len) */
 354                         BPF_MOV64_IMM(BPF_REG_3, 16),
 355 
 356                         /* sysctl_get_name arg4 (flags) */
 357                         BPF_MOV64_IMM(BPF_REG_4, 0),
 358 
 359                         /* sysctl_get_name(ctx, buf, buf_len, flags) */
 360                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
 361 
 362                         /* if (ret == expected && */
 363                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 10),
 364 
 365                         /*     buf[0:8] == "net/ipv4" && */
 366                         BPF_LD_IMM64(BPF_REG_8,
 367                                      bpf_be64_to_cpu(0x6e65742f69707634ULL)),
 368                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 369                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
 370 
 371                         /*     buf[8:16] == "/tcp_me\0") */
 372                         BPF_LD_IMM64(BPF_REG_8,
 373                                      bpf_be64_to_cpu(0x2f7463705f6d6500ULL)),
 374                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
 375                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 376 
 377                         /* return ALLOW; */
 378                         BPF_MOV64_IMM(BPF_REG_0, 1),
 379                         BPF_JMP_A(1),
 380 
 381                         /* else return DENY; */
 382                         BPF_MOV64_IMM(BPF_REG_0, 0),
 383                         BPF_EXIT_INSN(),
 384                 },
 385                 .attach_type = BPF_CGROUP_SYSCTL,
 386                 .sysctl = "net/ipv4/tcp_mem",
 387                 .open_flags = O_RDONLY,
 388                 .result = SUCCESS,
 389         },
 390         {
 391                 .descr = "sysctl_get_name sysctl:full E2BIG truncated small",
 392                 .insns = {
 393                         /* sysctl_get_name arg2 (buf) */
 394                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 395                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 396                         BPF_MOV64_IMM(BPF_REG_0, 0),
 397                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 398 
 399                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 400 
 401                         /* sysctl_get_name arg3 (buf_len) */
 402                         BPF_MOV64_IMM(BPF_REG_3, 7),
 403 
 404                         /* sysctl_get_name arg4 (flags) */
 405                         BPF_MOV64_IMM(BPF_REG_4, 0),
 406 
 407                         /* sysctl_get_name(ctx, buf, buf_len, flags) */
 408                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_name),
 409 
 410                         /* if (ret == expected && */
 411                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
 412 
 413                         /*     buf[0:8] == "net/ip\0") */
 414                         BPF_LD_IMM64(BPF_REG_8,
 415                                      bpf_be64_to_cpu(0x6e65742f69700000ULL)),
 416                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 417                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 418 
 419                         /* return ALLOW; */
 420                         BPF_MOV64_IMM(BPF_REG_0, 1),
 421                         BPF_JMP_A(1),
 422 
 423                         /* else return DENY; */
 424                         BPF_MOV64_IMM(BPF_REG_0, 0),
 425                         BPF_EXIT_INSN(),
 426                 },
 427                 .attach_type = BPF_CGROUP_SYSCTL,
 428                 .sysctl = "net/ipv4/tcp_mem",
 429                 .open_flags = O_RDONLY,
 430                 .result = SUCCESS,
 431         },
 432         {
 433                 .descr = "sysctl_get_current_value sysctl:read ok, gt",
 434                 .insns = {
 435                         /* sysctl_get_current_value arg2 (buf) */
 436                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 437                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 438                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 439 
 440                         /* sysctl_get_current_value arg3 (buf_len) */
 441                         BPF_MOV64_IMM(BPF_REG_3, 8),
 442 
 443                         /* sysctl_get_current_value(ctx, buf, buf_len) */
 444                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
 445 
 446                         /* if (ret == expected && */
 447                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
 448 
 449                         /*     buf[0:6] == "Linux\n\0") */
 450                         BPF_LD_IMM64(BPF_REG_8,
 451                                      bpf_be64_to_cpu(0x4c696e75780a0000ULL)),
 452                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 453                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 454 
 455                         /* return ALLOW; */
 456                         BPF_MOV64_IMM(BPF_REG_0, 1),
 457                         BPF_JMP_A(1),
 458 
 459                         /* else return DENY; */
 460                         BPF_MOV64_IMM(BPF_REG_0, 0),
 461                         BPF_EXIT_INSN(),
 462                 },
 463                 .attach_type = BPF_CGROUP_SYSCTL,
 464                 .sysctl = "kernel/ostype",
 465                 .open_flags = O_RDONLY,
 466                 .result = SUCCESS,
 467         },
 468         {
 469                 .descr = "sysctl_get_current_value sysctl:read ok, eq",
 470                 .insns = {
 471                         /* sysctl_get_current_value arg2 (buf) */
 472                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 473                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 474                         BPF_MOV64_IMM(BPF_REG_0, 0),
 475                         BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 7),
 476 
 477                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 478 
 479                         /* sysctl_get_current_value arg3 (buf_len) */
 480                         BPF_MOV64_IMM(BPF_REG_3, 7),
 481 
 482                         /* sysctl_get_current_value(ctx, buf, buf_len) */
 483                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
 484 
 485                         /* if (ret == expected && */
 486                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 6, 6),
 487 
 488                         /*     buf[0:6] == "Linux\n\0") */
 489                         BPF_LD_IMM64(BPF_REG_8,
 490                                      bpf_be64_to_cpu(0x4c696e75780a0000ULL)),
 491                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 492                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 493 
 494                         /* return ALLOW; */
 495                         BPF_MOV64_IMM(BPF_REG_0, 1),
 496                         BPF_JMP_A(1),
 497 
 498                         /* else return DENY; */
 499                         BPF_MOV64_IMM(BPF_REG_0, 0),
 500                         BPF_EXIT_INSN(),
 501                 },
 502                 .attach_type = BPF_CGROUP_SYSCTL,
 503                 .sysctl = "kernel/ostype",
 504                 .open_flags = O_RDONLY,
 505                 .result = SUCCESS,
 506         },
 507         {
 508                 .descr = "sysctl_get_current_value sysctl:read E2BIG truncated",
 509                 .insns = {
 510                         /* sysctl_get_current_value arg2 (buf) */
 511                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 512                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 513                         BPF_MOV64_IMM(BPF_REG_0, 0),
 514                         BPF_STX_MEM(BPF_H, BPF_REG_7, BPF_REG_0, 6),
 515 
 516                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 517 
 518                         /* sysctl_get_current_value arg3 (buf_len) */
 519                         BPF_MOV64_IMM(BPF_REG_3, 6),
 520 
 521                         /* sysctl_get_current_value(ctx, buf, buf_len) */
 522                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
 523 
 524                         /* if (ret == expected && */
 525                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 6),
 526 
 527                         /*     buf[0:6] == "Linux\0") */
 528                         BPF_LD_IMM64(BPF_REG_8,
 529                                      bpf_be64_to_cpu(0x4c696e7578000000ULL)),
 530                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 531                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 532 
 533                         /* return ALLOW; */
 534                         BPF_MOV64_IMM(BPF_REG_0, 1),
 535                         BPF_JMP_A(1),
 536 
 537                         /* else return DENY; */
 538                         BPF_MOV64_IMM(BPF_REG_0, 0),
 539                         BPF_EXIT_INSN(),
 540                 },
 541                 .attach_type = BPF_CGROUP_SYSCTL,
 542                 .sysctl = "kernel/ostype",
 543                 .open_flags = O_RDONLY,
 544                 .result = SUCCESS,
 545         },
 546         {
 547                 .descr = "sysctl_get_current_value sysctl:read EINVAL",
 548                 .insns = {
 549                         /* sysctl_get_current_value arg2 (buf) */
 550                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 551                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 552 
 553                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 554 
 555                         /* sysctl_get_current_value arg3 (buf_len) */
 556                         BPF_MOV64_IMM(BPF_REG_3, 8),
 557 
 558                         /* sysctl_get_current_value(ctx, buf, buf_len) */
 559                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
 560 
 561                         /* if (ret == expected && */
 562                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 4),
 563 
 564                         /*     buf[0:8] is NUL-filled) */
 565                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 566                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2),
 567 
 568                         /* return DENY; */
 569                         BPF_MOV64_IMM(BPF_REG_0, 0),
 570                         BPF_JMP_A(1),
 571 
 572                         /* else return ALLOW; */
 573                         BPF_MOV64_IMM(BPF_REG_0, 1),
 574                         BPF_EXIT_INSN(),
 575                 },
 576                 .attach_type = BPF_CGROUP_SYSCTL,
 577                 .sysctl = "net/ipv6/conf/lo/stable_secret", /* -EIO */
 578                 .open_flags = O_RDONLY,
 579                 .result = OP_EPERM,
 580         },
 581         {
 582                 .descr = "sysctl_get_current_value sysctl:write ok",
 583                 .fixup_value_insn = 6,
 584                 .insns = {
 585                         /* sysctl_get_current_value arg2 (buf) */
 586                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 587                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 588 
 589                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 590 
 591                         /* sysctl_get_current_value arg3 (buf_len) */
 592                         BPF_MOV64_IMM(BPF_REG_3, 8),
 593 
 594                         /* sysctl_get_current_value(ctx, buf, buf_len) */
 595                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_current_value),
 596 
 597                         /* if (ret == expected && */
 598                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 6),
 599 
 600                         /*     buf[0:4] == expected) */
 601                         BPF_LD_IMM64(BPF_REG_8, FIXUP_SYSCTL_VALUE),
 602                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 603                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 604 
 605                         /* return DENY; */
 606                         BPF_MOV64_IMM(BPF_REG_0, 0),
 607                         BPF_JMP_A(1),
 608 
 609                         /* else return ALLOW; */
 610                         BPF_MOV64_IMM(BPF_REG_0, 1),
 611                         BPF_EXIT_INSN(),
 612                 },
 613                 .attach_type = BPF_CGROUP_SYSCTL,
 614                 .sysctl = "net/ipv4/route/mtu_expires",
 615                 .open_flags = O_WRONLY,
 616                 .newval = "600", /* same as default, should fail anyway */
 617                 .result = OP_EPERM,
 618         },
 619         {
 620                 .descr = "sysctl_get_new_value sysctl:read EINVAL",
 621                 .insns = {
 622                         /* sysctl_get_new_value arg2 (buf) */
 623                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 624                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 625                         BPF_MOV64_IMM(BPF_REG_0, 0),
 626                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 627 
 628                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 629 
 630                         /* sysctl_get_new_value arg3 (buf_len) */
 631                         BPF_MOV64_IMM(BPF_REG_3, 8),
 632 
 633                         /* sysctl_get_new_value(ctx, buf, buf_len) */
 634                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
 635 
 636                         /* if (ret == expected) */
 637                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
 638 
 639                         /* return ALLOW; */
 640                         BPF_MOV64_IMM(BPF_REG_0, 1),
 641                         BPF_JMP_A(1),
 642 
 643                         /* else return DENY; */
 644                         BPF_MOV64_IMM(BPF_REG_0, 0),
 645                         BPF_EXIT_INSN(),
 646                 },
 647                 .attach_type = BPF_CGROUP_SYSCTL,
 648                 .sysctl = "net/ipv4/tcp_mem",
 649                 .open_flags = O_RDONLY,
 650                 .result = SUCCESS,
 651         },
 652         {
 653                 .descr = "sysctl_get_new_value sysctl:write ok",
 654                 .insns = {
 655                         /* sysctl_get_new_value arg2 (buf) */
 656                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 657                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 658 
 659                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 660 
 661                         /* sysctl_get_new_value arg3 (buf_len) */
 662                         BPF_MOV64_IMM(BPF_REG_3, 4),
 663 
 664                         /* sysctl_get_new_value(ctx, buf, buf_len) */
 665                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
 666 
 667                         /* if (ret == expected && */
 668                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
 669 
 670                         /*     buf[0:4] == "606\0") */
 671                         BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
 672                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9,
 673                                     bpf_ntohl(0x36303600), 2),
 674 
 675                         /* return DENY; */
 676                         BPF_MOV64_IMM(BPF_REG_0, 0),
 677                         BPF_JMP_A(1),
 678 
 679                         /* else return ALLOW; */
 680                         BPF_MOV64_IMM(BPF_REG_0, 1),
 681                         BPF_EXIT_INSN(),
 682                 },
 683                 .attach_type = BPF_CGROUP_SYSCTL,
 684                 .sysctl = "net/ipv4/route/mtu_expires",
 685                 .open_flags = O_WRONLY,
 686                 .newval = "606",
 687                 .result = OP_EPERM,
 688         },
 689         {
 690                 .descr = "sysctl_get_new_value sysctl:write ok long",
 691                 .insns = {
 692                         /* sysctl_get_new_value arg2 (buf) */
 693                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 694                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
 695 
 696                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 697 
 698                         /* sysctl_get_new_value arg3 (buf_len) */
 699                         BPF_MOV64_IMM(BPF_REG_3, 24),
 700 
 701                         /* sysctl_get_new_value(ctx, buf, buf_len) */
 702                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
 703 
 704                         /* if (ret == expected && */
 705                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 23, 14),
 706 
 707                         /*     buf[0:8] == "3000000 " && */
 708                         BPF_LD_IMM64(BPF_REG_8,
 709                                      bpf_be64_to_cpu(0x3330303030303020ULL)),
 710                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 711                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 10),
 712 
 713                         /*     buf[8:16] == "4000000 " && */
 714                         BPF_LD_IMM64(BPF_REG_8,
 715                                      bpf_be64_to_cpu(0x3430303030303020ULL)),
 716                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 8),
 717                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 6),
 718 
 719                         /*     buf[16:24] == "6000000\0") */
 720                         BPF_LD_IMM64(BPF_REG_8,
 721                                      bpf_be64_to_cpu(0x3630303030303000ULL)),
 722                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 16),
 723                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
 724 
 725                         /* return DENY; */
 726                         BPF_MOV64_IMM(BPF_REG_0, 0),
 727                         BPF_JMP_A(1),
 728 
 729                         /* else return ALLOW; */
 730                         BPF_MOV64_IMM(BPF_REG_0, 1),
 731                         BPF_EXIT_INSN(),
 732                 },
 733                 .attach_type = BPF_CGROUP_SYSCTL,
 734                 .sysctl = "net/ipv4/tcp_mem",
 735                 .open_flags = O_WRONLY,
 736                 .newval = "3000000 4000000 6000000",
 737                 .result = OP_EPERM,
 738         },
 739         {
 740                 .descr = "sysctl_get_new_value sysctl:write E2BIG",
 741                 .insns = {
 742                         /* sysctl_get_new_value arg2 (buf) */
 743                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 744                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 745                         BPF_MOV64_IMM(BPF_REG_0, 0),
 746                         BPF_STX_MEM(BPF_B, BPF_REG_7, BPF_REG_0, 3),
 747 
 748                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 749 
 750                         /* sysctl_get_new_value arg3 (buf_len) */
 751                         BPF_MOV64_IMM(BPF_REG_3, 3),
 752 
 753                         /* sysctl_get_new_value(ctx, buf, buf_len) */
 754                         BPF_EMIT_CALL(BPF_FUNC_sysctl_get_new_value),
 755 
 756                         /* if (ret == expected && */
 757                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -E2BIG, 4),
 758 
 759                         /*     buf[0:3] == "60\0") */
 760                         BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_7, 0),
 761                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9,
 762                                     bpf_ntohl(0x36300000), 2),
 763 
 764                         /* return DENY; */
 765                         BPF_MOV64_IMM(BPF_REG_0, 0),
 766                         BPF_JMP_A(1),
 767 
 768                         /* else return ALLOW; */
 769                         BPF_MOV64_IMM(BPF_REG_0, 1),
 770                         BPF_EXIT_INSN(),
 771                 },
 772                 .attach_type = BPF_CGROUP_SYSCTL,
 773                 .sysctl = "net/ipv4/route/mtu_expires",
 774                 .open_flags = O_WRONLY,
 775                 .newval = "606",
 776                 .result = OP_EPERM,
 777         },
 778         {
 779                 .descr = "sysctl_set_new_value sysctl:read EINVAL",
 780                 .insns = {
 781                         /* sysctl_set_new_value arg2 (buf) */
 782                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 783                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 784                         BPF_MOV64_IMM(BPF_REG_0,
 785                                       bpf_ntohl(0x36303000)),
 786                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 787 
 788                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 789 
 790                         /* sysctl_set_new_value arg3 (buf_len) */
 791                         BPF_MOV64_IMM(BPF_REG_3, 3),
 792 
 793                         /* sysctl_set_new_value(ctx, buf, buf_len) */
 794                         BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
 795 
 796                         /* if (ret == expected) */
 797                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
 798 
 799                         /* return ALLOW; */
 800                         BPF_MOV64_IMM(BPF_REG_0, 1),
 801                         BPF_JMP_A(1),
 802 
 803                         /* else return DENY; */
 804                         BPF_MOV64_IMM(BPF_REG_0, 0),
 805                         BPF_EXIT_INSN(),
 806                 },
 807                 .attach_type = BPF_CGROUP_SYSCTL,
 808                 .sysctl = "net/ipv4/route/mtu_expires",
 809                 .open_flags = O_RDONLY,
 810                 .result = SUCCESS,
 811         },
 812         {
 813                 .descr = "sysctl_set_new_value sysctl:write ok",
 814                 .fixup_value_insn = 2,
 815                 .insns = {
 816                         /* sysctl_set_new_value arg2 (buf) */
 817                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 818                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 819                         BPF_LD_IMM64(BPF_REG_0, FIXUP_SYSCTL_VALUE),
 820                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 821 
 822                         BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
 823 
 824                         /* sysctl_set_new_value arg3 (buf_len) */
 825                         BPF_MOV64_IMM(BPF_REG_3, 3),
 826 
 827                         /* sysctl_set_new_value(ctx, buf, buf_len) */
 828                         BPF_EMIT_CALL(BPF_FUNC_sysctl_set_new_value),
 829 
 830                         /* if (ret == expected) */
 831                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2),
 832 
 833                         /* return ALLOW; */
 834                         BPF_MOV64_IMM(BPF_REG_0, 1),
 835                         BPF_JMP_A(1),
 836 
 837                         /* else return DENY; */
 838                         BPF_MOV64_IMM(BPF_REG_0, 0),
 839                         BPF_EXIT_INSN(),
 840                 },
 841                 .attach_type = BPF_CGROUP_SYSCTL,
 842                 .sysctl = "net/ipv4/route/mtu_expires",
 843                 .open_flags = O_WRONLY,
 844                 .newval = "606",
 845                 .result = SUCCESS,
 846         },
 847         {
 848                 "bpf_strtoul one number string",
 849                 .insns = {
 850                         /* arg1 (buf) */
 851                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 852                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 853                         BPF_MOV64_IMM(BPF_REG_0,
 854                                       bpf_ntohl(0x36303000)),
 855                         BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
 856 
 857                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
 858 
 859                         /* arg2 (buf_len) */
 860                         BPF_MOV64_IMM(BPF_REG_2, 4),
 861 
 862                         /* arg3 (flags) */
 863                         BPF_MOV64_IMM(BPF_REG_3, 0),
 864 
 865                         /* arg4 (res) */
 866                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 867                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 868                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
 869 
 870                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
 871 
 872                         /* if (ret == expected && */
 873                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
 874                         /*     res == expected) */
 875                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 876                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 2),
 877 
 878                         /* return ALLOW; */
 879                         BPF_MOV64_IMM(BPF_REG_0, 1),
 880                         BPF_JMP_A(1),
 881 
 882                         /* else return DENY; */
 883                         BPF_MOV64_IMM(BPF_REG_0, 0),
 884                         BPF_EXIT_INSN(),
 885                 },
 886                 .attach_type = BPF_CGROUP_SYSCTL,
 887                 .sysctl = "net/ipv4/route/mtu_expires",
 888                 .open_flags = O_RDONLY,
 889                 .result = SUCCESS,
 890         },
 891         {
 892                 "bpf_strtoul multi number string",
 893                 .insns = {
 894                         /* arg1 (buf) */
 895                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 896                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 897                         /* "600 602\0" */
 898                         BPF_LD_IMM64(BPF_REG_0,
 899                                      bpf_be64_to_cpu(0x3630302036303200ULL)),
 900                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 901                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
 902 
 903                         /* arg2 (buf_len) */
 904                         BPF_MOV64_IMM(BPF_REG_2, 8),
 905 
 906                         /* arg3 (flags) */
 907                         BPF_MOV64_IMM(BPF_REG_3, 0),
 908 
 909                         /* arg4 (res) */
 910                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 911                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 912                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
 913 
 914                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
 915 
 916                         /* if (ret == expected && */
 917                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 18),
 918                         /*     res == expected) */
 919                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 920                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 600, 16),
 921 
 922                         /*     arg1 (buf) */
 923                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 924                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 925                         BPF_ALU64_REG(BPF_ADD, BPF_REG_7, BPF_REG_0),
 926                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
 927 
 928                         /*     arg2 (buf_len) */
 929                         BPF_MOV64_IMM(BPF_REG_2, 8),
 930                         BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0),
 931 
 932                         /*     arg3 (flags) */
 933                         BPF_MOV64_IMM(BPF_REG_3, 0),
 934 
 935                         /*     arg4 (res) */
 936                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 937                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
 938                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
 939 
 940                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
 941 
 942                         /*     if (ret == expected && */
 943                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
 944                         /*         res == expected) */
 945                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
 946                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 602, 2),
 947 
 948                         /* return ALLOW; */
 949                         BPF_MOV64_IMM(BPF_REG_0, 1),
 950                         BPF_JMP_A(1),
 951 
 952                         /* else return DENY; */
 953                         BPF_MOV64_IMM(BPF_REG_0, 0),
 954                         BPF_EXIT_INSN(),
 955                 },
 956                 .attach_type = BPF_CGROUP_SYSCTL,
 957                 .sysctl = "net/ipv4/tcp_mem",
 958                 .open_flags = O_RDONLY,
 959                 .result = SUCCESS,
 960         },
 961         {
 962                 "bpf_strtoul buf_len = 0, reject",
 963                 .insns = {
 964                         /* arg1 (buf) */
 965                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 966                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 967                         BPF_MOV64_IMM(BPF_REG_0,
 968                                       bpf_ntohl(0x36303000)),
 969                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 970 
 971                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
 972 
 973                         /* arg2 (buf_len) */
 974                         BPF_MOV64_IMM(BPF_REG_2, 0),
 975 
 976                         /* arg3 (flags) */
 977                         BPF_MOV64_IMM(BPF_REG_3, 0),
 978 
 979                         /* arg4 (res) */
 980                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
 981                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
 982                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
 983 
 984                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
 985 
 986                         BPF_MOV64_IMM(BPF_REG_0, 1),
 987                         BPF_EXIT_INSN(),
 988                 },
 989                 .attach_type = BPF_CGROUP_SYSCTL,
 990                 .sysctl = "net/ipv4/route/mtu_expires",
 991                 .open_flags = O_RDONLY,
 992                 .result = LOAD_REJECT,
 993         },
 994         {
 995                 "bpf_strtoul supported base, ok",
 996                 .insns = {
 997                         /* arg1 (buf) */
 998                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
 999                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1000                         BPF_MOV64_IMM(BPF_REG_0,
1001                                       bpf_ntohl(0x30373700)),
1002                         BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1003 
1004                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1005 
1006                         /* arg2 (buf_len) */
1007                         BPF_MOV64_IMM(BPF_REG_2, 4),
1008 
1009                         /* arg3 (flags) */
1010                         BPF_MOV64_IMM(BPF_REG_3, 8),
1011 
1012                         /* arg4 (res) */
1013                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1014                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1015                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1016 
1017                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
1018 
1019                         /* if (ret == expected && */
1020                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1021                         /*     res == expected) */
1022                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1023                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 63, 2),
1024 
1025                         /* return ALLOW; */
1026                         BPF_MOV64_IMM(BPF_REG_0, 1),
1027                         BPF_JMP_A(1),
1028 
1029                         /* else return DENY; */
1030                         BPF_MOV64_IMM(BPF_REG_0, 0),
1031                         BPF_EXIT_INSN(),
1032                 },
1033                 .attach_type = BPF_CGROUP_SYSCTL,
1034                 .sysctl = "net/ipv4/route/mtu_expires",
1035                 .open_flags = O_RDONLY,
1036                 .result = SUCCESS,
1037         },
1038         {
1039                 "bpf_strtoul unsupported base, EINVAL",
1040                 .insns = {
1041                         /* arg1 (buf) */
1042                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1043                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1044                         BPF_MOV64_IMM(BPF_REG_0,
1045                                       bpf_ntohl(0x36303000)),
1046                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1047 
1048                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1049 
1050                         /* arg2 (buf_len) */
1051                         BPF_MOV64_IMM(BPF_REG_2, 4),
1052 
1053                         /* arg3 (flags) */
1054                         BPF_MOV64_IMM(BPF_REG_3, 3),
1055 
1056                         /* arg4 (res) */
1057                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1058                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1059                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1060 
1061                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
1062 
1063                         /* if (ret == expected) */
1064                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1065 
1066                         /* return ALLOW; */
1067                         BPF_MOV64_IMM(BPF_REG_0, 1),
1068                         BPF_JMP_A(1),
1069 
1070                         /* else return DENY; */
1071                         BPF_MOV64_IMM(BPF_REG_0, 0),
1072                         BPF_EXIT_INSN(),
1073                 },
1074                 .attach_type = BPF_CGROUP_SYSCTL,
1075                 .sysctl = "net/ipv4/route/mtu_expires",
1076                 .open_flags = O_RDONLY,
1077                 .result = SUCCESS,
1078         },
1079         {
1080                 "bpf_strtoul buf with spaces only, EINVAL",
1081                 .insns = {
1082                         /* arg1 (buf) */
1083                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1084                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1085                         BPF_MOV64_IMM(BPF_REG_0,
1086                                       bpf_ntohl(0x0d0c0a09)),
1087                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1088 
1089                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1090 
1091                         /* arg2 (buf_len) */
1092                         BPF_MOV64_IMM(BPF_REG_2, 4),
1093 
1094                         /* arg3 (flags) */
1095                         BPF_MOV64_IMM(BPF_REG_3, 0),
1096 
1097                         /* arg4 (res) */
1098                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1099                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1100                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1101 
1102                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
1103 
1104                         /* if (ret == expected) */
1105                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1106 
1107                         /* return ALLOW; */
1108                         BPF_MOV64_IMM(BPF_REG_0, 1),
1109                         BPF_JMP_A(1),
1110 
1111                         /* else return DENY; */
1112                         BPF_MOV64_IMM(BPF_REG_0, 0),
1113                         BPF_EXIT_INSN(),
1114                 },
1115                 .attach_type = BPF_CGROUP_SYSCTL,
1116                 .sysctl = "net/ipv4/route/mtu_expires",
1117                 .open_flags = O_RDONLY,
1118                 .result = SUCCESS,
1119         },
1120         {
1121                 "bpf_strtoul negative number, EINVAL",
1122                 .insns = {
1123                         /* arg1 (buf) */
1124                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1125                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1126                         /* " -6\0" */
1127                         BPF_MOV64_IMM(BPF_REG_0,
1128                                       bpf_ntohl(0x0a2d3600)),
1129                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1130 
1131                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1132 
1133                         /* arg2 (buf_len) */
1134                         BPF_MOV64_IMM(BPF_REG_2, 4),
1135 
1136                         /* arg3 (flags) */
1137                         BPF_MOV64_IMM(BPF_REG_3, 0),
1138 
1139                         /* arg4 (res) */
1140                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1141                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1142                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1143 
1144                         BPF_EMIT_CALL(BPF_FUNC_strtoul),
1145 
1146                         /* if (ret == expected) */
1147                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -EINVAL, 2),
1148 
1149                         /* return ALLOW; */
1150                         BPF_MOV64_IMM(BPF_REG_0, 1),
1151                         BPF_JMP_A(1),
1152 
1153                         /* else return DENY; */
1154                         BPF_MOV64_IMM(BPF_REG_0, 0),
1155                         BPF_EXIT_INSN(),
1156                 },
1157                 .attach_type = BPF_CGROUP_SYSCTL,
1158                 .sysctl = "net/ipv4/route/mtu_expires",
1159                 .open_flags = O_RDONLY,
1160                 .result = SUCCESS,
1161         },
1162         {
1163                 "bpf_strtol negative number, ok",
1164                 .insns = {
1165                         /* arg1 (buf) */
1166                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1167                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1168                         /* " -6\0" */
1169                         BPF_MOV64_IMM(BPF_REG_0,
1170                                       bpf_ntohl(0x0a2d3600)),
1171                         BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1172 
1173                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1174 
1175                         /* arg2 (buf_len) */
1176                         BPF_MOV64_IMM(BPF_REG_2, 4),
1177 
1178                         /* arg3 (flags) */
1179                         BPF_MOV64_IMM(BPF_REG_3, 10),
1180 
1181                         /* arg4 (res) */
1182                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1183                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1184                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1185 
1186                         BPF_EMIT_CALL(BPF_FUNC_strtol),
1187 
1188                         /* if (ret == expected && */
1189                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 3, 4),
1190                         /*     res == expected) */
1191                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1192                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9, -6, 2),
1193 
1194                         /* return ALLOW; */
1195                         BPF_MOV64_IMM(BPF_REG_0, 1),
1196                         BPF_JMP_A(1),
1197 
1198                         /* else return DENY; */
1199                         BPF_MOV64_IMM(BPF_REG_0, 0),
1200                         BPF_EXIT_INSN(),
1201                 },
1202                 .attach_type = BPF_CGROUP_SYSCTL,
1203                 .sysctl = "net/ipv4/route/mtu_expires",
1204                 .open_flags = O_RDONLY,
1205                 .result = SUCCESS,
1206         },
1207         {
1208                 "bpf_strtol hex number, ok",
1209                 .insns = {
1210                         /* arg1 (buf) */
1211                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1212                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1213                         /* "0xfe" */
1214                         BPF_MOV64_IMM(BPF_REG_0,
1215                                       bpf_ntohl(0x30786665)),
1216                         BPF_STX_MEM(BPF_W, BPF_REG_7, BPF_REG_0, 0),
1217 
1218                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1219 
1220                         /* arg2 (buf_len) */
1221                         BPF_MOV64_IMM(BPF_REG_2, 4),
1222 
1223                         /* arg3 (flags) */
1224                         BPF_MOV64_IMM(BPF_REG_3, 0),
1225 
1226                         /* arg4 (res) */
1227                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1228                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1229                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1230 
1231                         BPF_EMIT_CALL(BPF_FUNC_strtol),
1232 
1233                         /* if (ret == expected && */
1234                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 4, 4),
1235                         /*     res == expected) */
1236                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1237                         BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 254, 2),
1238 
1239                         /* return ALLOW; */
1240                         BPF_MOV64_IMM(BPF_REG_0, 1),
1241                         BPF_JMP_A(1),
1242 
1243                         /* else return DENY; */
1244                         BPF_MOV64_IMM(BPF_REG_0, 0),
1245                         BPF_EXIT_INSN(),
1246                 },
1247                 .attach_type = BPF_CGROUP_SYSCTL,
1248                 .sysctl = "net/ipv4/route/mtu_expires",
1249                 .open_flags = O_RDONLY,
1250                 .result = SUCCESS,
1251         },
1252         {
1253                 "bpf_strtol max long",
1254                 .insns = {
1255                         /* arg1 (buf) 9223372036854775807 */
1256                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1257                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
1258                         BPF_LD_IMM64(BPF_REG_0,
1259                                      bpf_be64_to_cpu(0x3932323333373230ULL)),
1260                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1261                         BPF_LD_IMM64(BPF_REG_0,
1262                                      bpf_be64_to_cpu(0x3336383534373735ULL)),
1263                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
1264                         BPF_LD_IMM64(BPF_REG_0,
1265                                      bpf_be64_to_cpu(0x3830370000000000ULL)),
1266                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16),
1267 
1268                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1269 
1270                         /* arg2 (buf_len) */
1271                         BPF_MOV64_IMM(BPF_REG_2, 19),
1272 
1273                         /* arg3 (flags) */
1274                         BPF_MOV64_IMM(BPF_REG_3, 0),
1275 
1276                         /* arg4 (res) */
1277                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1278                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1279                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1280 
1281                         BPF_EMIT_CALL(BPF_FUNC_strtol),
1282 
1283                         /* if (ret == expected && */
1284                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 19, 6),
1285                         /*     res == expected) */
1286                         BPF_LD_IMM64(BPF_REG_8, 0x7fffffffffffffffULL),
1287                         BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0),
1288                         BPF_JMP_REG(BPF_JNE, BPF_REG_8, BPF_REG_9, 2),
1289 
1290                         /* return ALLOW; */
1291                         BPF_MOV64_IMM(BPF_REG_0, 1),
1292                         BPF_JMP_A(1),
1293 
1294                         /* else return DENY; */
1295                         BPF_MOV64_IMM(BPF_REG_0, 0),
1296                         BPF_EXIT_INSN(),
1297                 },
1298                 .attach_type = BPF_CGROUP_SYSCTL,
1299                 .sysctl = "net/ipv4/route/mtu_expires",
1300                 .open_flags = O_RDONLY,
1301                 .result = SUCCESS,
1302         },
1303         {
1304                 "bpf_strtol overflow, ERANGE",
1305                 .insns = {
1306                         /* arg1 (buf) 9223372036854775808 */
1307                         BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
1308                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -24),
1309                         BPF_LD_IMM64(BPF_REG_0,
1310                                      bpf_be64_to_cpu(0x3932323333373230ULL)),
1311                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1312                         BPF_LD_IMM64(BPF_REG_0,
1313                                      bpf_be64_to_cpu(0x3336383534373735ULL)),
1314                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 8),
1315                         BPF_LD_IMM64(BPF_REG_0,
1316                                      bpf_be64_to_cpu(0x3830380000000000ULL)),
1317                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 16),
1318 
1319                         BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
1320 
1321                         /* arg2 (buf_len) */
1322                         BPF_MOV64_IMM(BPF_REG_2, 19),
1323 
1324                         /* arg3 (flags) */
1325                         BPF_MOV64_IMM(BPF_REG_3, 0),
1326 
1327                         /* arg4 (res) */
1328                         BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -8),
1329                         BPF_STX_MEM(BPF_DW, BPF_REG_7, BPF_REG_0, 0),
1330                         BPF_MOV64_REG(BPF_REG_4, BPF_REG_7),
1331 
1332                         BPF_EMIT_CALL(BPF_FUNC_strtol),
1333 
1334                         /* if (ret == expected) */
1335                         BPF_JMP_IMM(BPF_JNE, BPF_REG_0, -ERANGE, 2),
1336 
1337                         /* return ALLOW; */
1338                         BPF_MOV64_IMM(BPF_REG_0, 1),
1339                         BPF_JMP_A(1),
1340 
1341                         /* else return DENY; */
1342                         BPF_MOV64_IMM(BPF_REG_0, 0),
1343                         BPF_EXIT_INSN(),
1344                 },
1345                 .attach_type = BPF_CGROUP_SYSCTL,
1346                 .sysctl = "net/ipv4/route/mtu_expires",
1347                 .open_flags = O_RDONLY,
1348                 .result = SUCCESS,
1349         },
1350         {
1351                 "C prog: deny all writes",
1352                 .prog_file = "./test_sysctl_prog.o",
1353                 .attach_type = BPF_CGROUP_SYSCTL,
1354                 .sysctl = "net/ipv4/tcp_mem",
1355                 .open_flags = O_WRONLY,
1356                 .newval = "123 456 789",
1357                 .result = OP_EPERM,
1358         },
1359         {
1360                 "C prog: deny access by name",
1361                 .prog_file = "./test_sysctl_prog.o",
1362                 .attach_type = BPF_CGROUP_SYSCTL,
1363                 .sysctl = "net/ipv4/route/mtu_expires",
1364                 .open_flags = O_RDONLY,
1365                 .result = OP_EPERM,
1366         },
1367         {
1368                 "C prog: read tcp_mem",
1369                 .prog_file = "./test_sysctl_prog.o",
1370                 .attach_type = BPF_CGROUP_SYSCTL,
1371                 .sysctl = "net/ipv4/tcp_mem",
1372                 .open_flags = O_RDONLY,
1373                 .result = SUCCESS,
1374         },
1375 };
1376 
1377 static size_t probe_prog_length(const struct bpf_insn *fp)
1378 {
1379         size_t len;
1380 
1381         for (len = MAX_INSNS - 1; len > 0; --len)
1382                 if (fp[len].code != 0 || fp[len].imm != 0)
1383                         break;
1384         return len + 1;
1385 }
1386 
1387 static int fixup_sysctl_value(const char *buf, size_t buf_len,
1388                               struct bpf_insn *prog, size_t insn_num)
1389 {
1390         union {
1391                 uint8_t raw[sizeof(uint64_t)];
1392                 uint64_t num;
1393         } value = {};
1394 
1395         if (buf_len > sizeof(value)) {
1396                 log_err("Value is too big (%zd) to use in fixup", buf_len);
1397                 return -1;
1398         }
1399         if (prog[insn_num].code != (BPF_LD | BPF_DW | BPF_IMM)) {
1400                 log_err("Can fixup only BPF_LD_IMM64 insns");
1401                 return -1;
1402         }
1403 
1404         memcpy(value.raw, buf, buf_len);
1405         prog[insn_num].imm = (uint32_t)value.num;
1406         prog[insn_num + 1].imm = (uint32_t)(value.num >> 32);
1407 
1408         return 0;
1409 }
1410 
1411 static int load_sysctl_prog_insns(struct sysctl_test *test,
1412                                   const char *sysctl_path)
1413 {
1414         struct bpf_insn *prog = test->insns;
1415         struct bpf_load_program_attr attr;
1416         int ret;
1417 
1418         memset(&attr, 0, sizeof(struct bpf_load_program_attr));
1419         attr.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL;
1420         attr.insns = prog;
1421         attr.insns_cnt = probe_prog_length(attr.insns);
1422         attr.license = "GPL";
1423 
1424         if (test->fixup_value_insn) {
1425                 char buf[128];
1426                 ssize_t len;
1427                 int fd;
1428 
1429                 fd = open(sysctl_path, O_RDONLY | O_CLOEXEC);
1430                 if (fd < 0) {
1431                         log_err("open(%s) failed", sysctl_path);
1432                         return -1;
1433                 }
1434                 len = read(fd, buf, sizeof(buf));
1435                 if (len == -1) {
1436                         log_err("read(%s) failed", sysctl_path);
1437                         close(fd);
1438                         return -1;
1439                 }
1440                 close(fd);
1441                 if (fixup_sysctl_value(buf, len, prog, test->fixup_value_insn))
1442                         return -1;
1443         }
1444 
1445         ret = bpf_load_program_xattr(&attr, bpf_log_buf, BPF_LOG_BUF_SIZE);
1446         if (ret < 0 && test->result != LOAD_REJECT) {
1447                 log_err(">>> Loading program error.\n"
1448                         ">>> Verifier output:\n%s\n-------\n", bpf_log_buf);
1449         }
1450 
1451         return ret;
1452 }
1453 
1454 static int load_sysctl_prog_file(struct sysctl_test *test)
1455 {
1456         struct bpf_prog_load_attr attr;
1457         struct bpf_object *obj;
1458         int prog_fd;
1459 
1460         memset(&attr, 0, sizeof(struct bpf_prog_load_attr));
1461         attr.file = test->prog_file;
1462         attr.prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL;
1463 
1464         if (bpf_prog_load_xattr(&attr, &obj, &prog_fd)) {
1465                 if (test->result != LOAD_REJECT)
1466                         log_err(">>> Loading program (%s) error.\n",
1467                                 test->prog_file);
1468                 return -1;
1469         }
1470 
1471         return prog_fd;
1472 }
1473 
1474 static int load_sysctl_prog(struct sysctl_test *test, const char *sysctl_path)
1475 {
1476                 return test->prog_file
1477                         ? load_sysctl_prog_file(test)
1478                         : load_sysctl_prog_insns(test, sysctl_path);
1479 }
1480 
1481 static int access_sysctl(const char *sysctl_path,
1482                          const struct sysctl_test *test)
1483 {
1484         int err = 0;
1485         int fd;
1486 
1487         fd = open(sysctl_path, test->open_flags | O_CLOEXEC);
1488         if (fd < 0)
1489                 return fd;
1490 
1491         if (test->seek && lseek(fd, test->seek, SEEK_SET) == -1) {
1492                 log_err("lseek(%d) failed", test->seek);
1493                 goto err;
1494         }
1495 
1496         if (test->open_flags == O_RDONLY) {
1497                 char buf[128];
1498 
1499                 if (read(fd, buf, sizeof(buf)) == -1)
1500                         goto err;
1501                 if (test->oldval &&
1502                     strncmp(buf, test->oldval, strlen(test->oldval))) {
1503                         log_err("Read value %s != %s", buf, test->oldval);
1504                         goto err;
1505                 }
1506         } else if (test->open_flags == O_WRONLY) {
1507                 if (!test->newval) {
1508                         log_err("New value for sysctl is not set");
1509                         goto err;
1510                 }
1511                 if (write(fd, test->newval, strlen(test->newval)) == -1)
1512                         goto err;
1513         } else {
1514                 log_err("Unexpected sysctl access: neither read nor write");
1515                 goto err;
1516         }
1517 
1518         goto out;
1519 err:
1520         err = -1;
1521 out:
1522         close(fd);
1523         return err;
1524 }
1525 
1526 static int run_test_case(int cgfd, struct sysctl_test *test)
1527 {
1528         enum bpf_attach_type atype = test->attach_type;
1529         char sysctl_path[128];
1530         int progfd = -1;
1531         int err = 0;
1532 
1533         printf("Test case: %s .. ", test->descr);
1534 
1535         snprintf(sysctl_path, sizeof(sysctl_path), "/proc/sys/%s",
1536                  test->sysctl);
1537 
1538         progfd = load_sysctl_prog(test, sysctl_path);
1539         if (progfd < 0) {
1540                 if (test->result == LOAD_REJECT)
1541                         goto out;
1542                 else
1543                         goto err;
1544         }
1545 
1546         if (bpf_prog_attach(progfd, cgfd, atype, BPF_F_ALLOW_OVERRIDE) == -1) {
1547                 if (test->result == ATTACH_REJECT)
1548                         goto out;
1549                 else
1550                         goto err;
1551         }
1552 
1553         errno = 0;
1554         if (access_sysctl(sysctl_path, test) == -1) {
1555                 if (test->result == OP_EPERM && errno == EPERM)
1556                         goto out;
1557                 else
1558                         goto err;
1559         }
1560 
1561         if (test->result != SUCCESS) {
1562                 log_err("Unexpected success");
1563                 goto err;
1564         }
1565 
1566         goto out;
1567 err:
1568         err = -1;
1569 out:
1570         /* Detaching w/o checking return code: best effort attempt. */
1571         if (progfd != -1)
1572                 bpf_prog_detach(cgfd, atype);
1573         close(progfd);
1574         printf("[%s]\n", err ? "FAIL" : "PASS");
1575         return err;
1576 }
1577 
1578 static int run_tests(int cgfd)
1579 {
1580         int passes = 0;
1581         int fails = 0;
1582         int i;
1583 
1584         for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1585                 if (run_test_case(cgfd, &tests[i]))
1586                         ++fails;
1587                 else
1588                         ++passes;
1589         }
1590         printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1591         return fails ? -1 : 0;
1592 }
1593 
1594 int main(int argc, char **argv)
1595 {
1596         int cgfd = -1;
1597         int err = 0;
1598 
1599         if (setup_cgroup_environment())
1600                 goto err;
1601 
1602         cgfd = create_and_get_cgroup(CG_PATH);
1603         if (cgfd < 0)
1604                 goto err;
1605 
1606         if (join_cgroup(CG_PATH))
1607                 goto err;
1608 
1609         if (run_tests(cgfd))
1610                 goto err;
1611 
1612         goto out;
1613 err:
1614         err = -1;
1615 out:
1616         close(cgfd);
1617         cleanup_cgroup_environment();
1618         return err;
1619 }

/* [<][>][^][v][top][bottom][index][help] */