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