File Index
Files and directories
Sign in
FILE

test_sysctl.c

File preview with syntax highlighting.

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