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