1 {
2 	"reference tracking: leak potential reference",
3 	.insns = {
4 	BPF_SK_LOOKUP(sk_lookup_tcp),
5 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), /* leak reference */
6 	BPF_EXIT_INSN(),
7 	},
8 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
9 	.errstr = "Unreleased reference",
10 	.result = REJECT,
11 },
12 {
13 	"reference tracking: leak potential reference to sock_common",
14 	.insns = {
15 	BPF_SK_LOOKUP(skc_lookup_tcp),
16 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), /* leak reference */
17 	BPF_EXIT_INSN(),
18 	},
19 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
20 	.errstr = "Unreleased reference",
21 	.result = REJECT,
22 },
23 {
24 	"reference tracking: leak potential reference on stack",
25 	.insns = {
26 	BPF_SK_LOOKUP(sk_lookup_tcp),
27 	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
28 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
29 	BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
30 	BPF_MOV64_IMM(BPF_REG_0, 0),
31 	BPF_EXIT_INSN(),
32 	},
33 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
34 	.errstr = "Unreleased reference",
35 	.result = REJECT,
36 },
37 {
38 	"reference tracking: leak potential reference on stack 2",
39 	.insns = {
40 	BPF_SK_LOOKUP(sk_lookup_tcp),
41 	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
42 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
43 	BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
44 	BPF_MOV64_IMM(BPF_REG_0, 0),
45 	BPF_ST_MEM(BPF_DW, BPF_REG_4, 0, 0),
46 	BPF_EXIT_INSN(),
47 	},
48 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
49 	.errstr = "Unreleased reference",
50 	.result = REJECT,
51 },
52 {
53 	"reference tracking: zero potential reference",
54 	.insns = {
55 	BPF_SK_LOOKUP(sk_lookup_tcp),
56 	BPF_MOV64_IMM(BPF_REG_0, 0), /* leak reference */
57 	BPF_EXIT_INSN(),
58 	},
59 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
60 	.errstr = "Unreleased reference",
61 	.result = REJECT,
62 },
63 {
64 	"reference tracking: zero potential reference to sock_common",
65 	.insns = {
66 	BPF_SK_LOOKUP(skc_lookup_tcp),
67 	BPF_MOV64_IMM(BPF_REG_0, 0), /* leak reference */
68 	BPF_EXIT_INSN(),
69 	},
70 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
71 	.errstr = "Unreleased reference",
72 	.result = REJECT,
73 },
74 {
75 	"reference tracking: copy and zero potential references",
76 	.insns = {
77 	BPF_SK_LOOKUP(sk_lookup_tcp),
78 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
79 	BPF_MOV64_IMM(BPF_REG_0, 0),
80 	BPF_MOV64_IMM(BPF_REG_7, 0), /* leak reference */
81 	BPF_EXIT_INSN(),
82 	},
83 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
84 	.errstr = "Unreleased reference",
85 	.result = REJECT,
86 },
87 {
88 	"reference tracking: acquire/release user key reference",
89 	.insns = {
90 	BPF_MOV64_IMM(BPF_REG_1, -3),
91 	BPF_MOV64_IMM(BPF_REG_2, 0),
92 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
93 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
94 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
95 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
96 	BPF_MOV64_IMM(BPF_REG_0, 0),
97 	BPF_EXIT_INSN(),
98 	},
99 	.prog_type = BPF_PROG_TYPE_LSM,
100 	.kfunc = "bpf",
101 	.expected_attach_type = BPF_LSM_MAC,
102 	.flags = BPF_F_SLEEPABLE,
103 	.fixup_kfunc_btf_id = {
104 		{ "bpf_lookup_user_key", 2 },
105 		{ "bpf_key_put", 5 },
106 	},
107 	.result = ACCEPT,
108 },
109 {
110 	"reference tracking: acquire/release system key reference",
111 	.insns = {
112 	BPF_MOV64_IMM(BPF_REG_1, 1),
113 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
114 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
115 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
116 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
117 	BPF_MOV64_IMM(BPF_REG_0, 0),
118 	BPF_EXIT_INSN(),
119 	},
120 	.prog_type = BPF_PROG_TYPE_LSM,
121 	.kfunc = "bpf",
122 	.expected_attach_type = BPF_LSM_MAC,
123 	.flags = BPF_F_SLEEPABLE,
124 	.fixup_kfunc_btf_id = {
125 		{ "bpf_lookup_system_key", 1 },
126 		{ "bpf_key_put", 4 },
127 	},
128 	.result = ACCEPT,
129 },
130 {
131 	"reference tracking: release user key reference without check",
132 	.insns = {
133 	BPF_MOV64_IMM(BPF_REG_1, -3),
134 	BPF_MOV64_IMM(BPF_REG_2, 0),
135 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
136 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
137 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
138 	BPF_MOV64_IMM(BPF_REG_0, 0),
139 	BPF_EXIT_INSN(),
140 	},
141 	.prog_type = BPF_PROG_TYPE_LSM,
142 	.kfunc = "bpf",
143 	.expected_attach_type = BPF_LSM_MAC,
144 	.flags = BPF_F_SLEEPABLE,
145 	.errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar",
146 	.fixup_kfunc_btf_id = {
147 		{ "bpf_lookup_user_key", 2 },
148 		{ "bpf_key_put", 4 },
149 	},
150 	.result = REJECT,
151 },
152 {
153 	"reference tracking: release system key reference without check",
154 	.insns = {
155 	BPF_MOV64_IMM(BPF_REG_1, 1),
156 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
157 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
158 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
159 	BPF_MOV64_IMM(BPF_REG_0, 0),
160 	BPF_EXIT_INSN(),
161 	},
162 	.prog_type = BPF_PROG_TYPE_LSM,
163 	.kfunc = "bpf",
164 	.expected_attach_type = BPF_LSM_MAC,
165 	.flags = BPF_F_SLEEPABLE,
166 	.errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar",
167 	.fixup_kfunc_btf_id = {
168 		{ "bpf_lookup_system_key", 1 },
169 		{ "bpf_key_put", 3 },
170 	},
171 	.result = REJECT,
172 },
173 {
174 	"reference tracking: release with NULL key pointer",
175 	.insns = {
176 	BPF_MOV64_IMM(BPF_REG_1, 0),
177 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
178 	BPF_MOV64_IMM(BPF_REG_0, 0),
179 	BPF_EXIT_INSN(),
180 	},
181 	.prog_type = BPF_PROG_TYPE_LSM,
182 	.kfunc = "bpf",
183 	.expected_attach_type = BPF_LSM_MAC,
184 	.flags = BPF_F_SLEEPABLE,
185 	.errstr = "arg#0 pointer type STRUCT bpf_key must point to scalar, or struct with scalar",
186 	.fixup_kfunc_btf_id = {
187 		{ "bpf_key_put", 1 },
188 	},
189 	.result = REJECT,
190 },
191 {
192 	"reference tracking: leak potential reference to user key",
193 	.insns = {
194 	BPF_MOV64_IMM(BPF_REG_1, -3),
195 	BPF_MOV64_IMM(BPF_REG_2, 0),
196 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
197 	BPF_EXIT_INSN(),
198 	},
199 	.prog_type = BPF_PROG_TYPE_LSM,
200 	.kfunc = "bpf",
201 	.expected_attach_type = BPF_LSM_MAC,
202 	.flags = BPF_F_SLEEPABLE,
203 	.errstr = "Unreleased reference",
204 	.fixup_kfunc_btf_id = {
205 		{ "bpf_lookup_user_key", 2 },
206 	},
207 	.result = REJECT,
208 },
209 {
210 	"reference tracking: leak potential reference to system key",
211 	.insns = {
212 	BPF_MOV64_IMM(BPF_REG_1, 1),
213 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, BPF_PSEUDO_KFUNC_CALL, 0, 0),
214 	BPF_EXIT_INSN(),
215 	},
216 	.prog_type = BPF_PROG_TYPE_LSM,
217 	.kfunc = "bpf",
218 	.expected_attach_type = BPF_LSM_MAC,
219 	.flags = BPF_F_SLEEPABLE,
220 	.errstr = "Unreleased reference",
221 	.fixup_kfunc_btf_id = {
222 		{ "bpf_lookup_system_key", 1 },
223 	},
224 	.result = REJECT,
225 },
226 {
227 	"reference tracking: release reference without check",
228 	.insns = {
229 	BPF_SK_LOOKUP(sk_lookup_tcp),
230 	/* reference in r0 may be NULL */
231 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
232 	BPF_MOV64_IMM(BPF_REG_2, 0),
233 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
234 	BPF_EXIT_INSN(),
235 	},
236 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
237 	.errstr = "type=sock_or_null expected=sock",
238 	.result = REJECT,
239 },
240 {
241 	"reference tracking: release reference to sock_common without check",
242 	.insns = {
243 	BPF_SK_LOOKUP(skc_lookup_tcp),
244 	/* reference in r0 may be NULL */
245 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
246 	BPF_MOV64_IMM(BPF_REG_2, 0),
247 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
248 	BPF_EXIT_INSN(),
249 	},
250 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
251 	.errstr = "type=sock_common_or_null expected=sock",
252 	.result = REJECT,
253 },
254 {
255 	"reference tracking: release reference",
256 	.insns = {
257 	BPF_SK_LOOKUP(sk_lookup_tcp),
258 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
259 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
260 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
261 	BPF_EXIT_INSN(),
262 	},
263 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
264 	.result = ACCEPT,
265 },
266 {
267 	"reference tracking: release reference to sock_common",
268 	.insns = {
269 	BPF_SK_LOOKUP(skc_lookup_tcp),
270 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
271 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
272 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
273 	BPF_EXIT_INSN(),
274 	},
275 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
276 	.result = ACCEPT,
277 },
278 {
279 	"reference tracking: release reference 2",
280 	.insns = {
281 	BPF_SK_LOOKUP(sk_lookup_tcp),
282 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
283 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
284 	BPF_EXIT_INSN(),
285 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
286 	BPF_EXIT_INSN(),
287 	},
288 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
289 	.result = ACCEPT,
290 },
291 {
292 	"reference tracking: release reference twice",
293 	.insns = {
294 	BPF_SK_LOOKUP(sk_lookup_tcp),
295 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
296 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
297 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
298 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
299 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
300 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
301 	BPF_EXIT_INSN(),
302 	},
303 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
304 	.errstr = "type=scalar expected=sock",
305 	.result = REJECT,
306 },
307 {
308 	"reference tracking: release reference twice inside branch",
309 	.insns = {
310 	BPF_SK_LOOKUP(sk_lookup_tcp),
311 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
312 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
313 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), /* goto end */
314 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
315 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
316 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
317 	BPF_EXIT_INSN(),
318 	},
319 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
320 	.errstr = "type=scalar expected=sock",
321 	.result = REJECT,
322 },
323 {
324 	"reference tracking: alloc, check, free in one subbranch",
325 	.insns = {
326 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
327 		    offsetof(struct __sk_buff, data)),
328 	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
329 		    offsetof(struct __sk_buff, data_end)),
330 	BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
331 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16),
332 	/* if (offsetof(skb, mark) > data_len) exit; */
333 	BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1),
334 	BPF_EXIT_INSN(),
335 	BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2,
336 		    offsetof(struct __sk_buff, mark)),
337 	BPF_SK_LOOKUP(sk_lookup_tcp),
338 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 1), /* mark == 0? */
339 	/* Leak reference in R0 */
340 	BPF_EXIT_INSN(),
341 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
342 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
343 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
344 	BPF_EXIT_INSN(),
345 	},
346 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
347 	.errstr = "Unreleased reference",
348 	.result = REJECT,
349 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
350 },
351 {
352 	"reference tracking: alloc, check, free in both subbranches",
353 	.insns = {
354 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
355 		    offsetof(struct __sk_buff, data)),
356 	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
357 		    offsetof(struct __sk_buff, data_end)),
358 	BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
359 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16),
360 	/* if (offsetof(skb, mark) > data_len) exit; */
361 	BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1),
362 	BPF_EXIT_INSN(),
363 	BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2,
364 		    offsetof(struct __sk_buff, mark)),
365 	BPF_SK_LOOKUP(sk_lookup_tcp),
366 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 4), /* mark == 0? */
367 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
368 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
369 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
370 	BPF_EXIT_INSN(),
371 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
372 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
373 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
374 	BPF_EXIT_INSN(),
375 	},
376 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
377 	.result = ACCEPT,
378 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
379 },
380 {
381 	"reference tracking in call: free reference in subprog",
382 	.insns = {
383 	BPF_SK_LOOKUP(sk_lookup_tcp),
384 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */
385 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
386 	BPF_MOV64_IMM(BPF_REG_0, 0),
387 	BPF_EXIT_INSN(),
388 
389 	/* subprog 1 */
390 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
391 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1),
392 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
393 	BPF_EXIT_INSN(),
394 	},
395 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
396 	.result = ACCEPT,
397 },
398 {
399 	"reference tracking in call: free reference in subprog and outside",
400 	.insns = {
401 	BPF_SK_LOOKUP(sk_lookup_tcp),
402 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */
403 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
404 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3),
405 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
406 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
407 	BPF_EXIT_INSN(),
408 
409 	/* subprog 1 */
410 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
411 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1),
412 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
413 	BPF_EXIT_INSN(),
414 	},
415 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
416 	.errstr = "type=scalar expected=sock",
417 	.result = REJECT,
418 },
419 {
420 	"reference tracking in call: alloc & leak reference in subprog",
421 	.insns = {
422 	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
423 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
424 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3),
425 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
426 	BPF_MOV64_IMM(BPF_REG_0, 0),
427 	BPF_EXIT_INSN(),
428 
429 	/* subprog 1 */
430 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_4),
431 	BPF_SK_LOOKUP(sk_lookup_tcp),
432 	/* spill unchecked sk_ptr into stack of caller */
433 	BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0),
434 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
435 	BPF_EXIT_INSN(),
436 	},
437 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
438 	.errstr = "Unreleased reference",
439 	.result = REJECT,
440 },
441 {
442 	"reference tracking in call: alloc in subprog, release outside",
443 	.insns = {
444 	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
445 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4),
446 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
447 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
448 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
449 	BPF_EXIT_INSN(),
450 
451 	/* subprog 1 */
452 	BPF_SK_LOOKUP(sk_lookup_tcp),
453 	BPF_EXIT_INSN(), /* return sk */
454 	},
455 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
456 	.retval = POINTER_VALUE,
457 	.result = ACCEPT,
458 },
459 {
460 	"reference tracking in call: sk_ptr leak into caller stack",
461 	.insns = {
462 	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
463 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
464 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
465 	BPF_MOV64_IMM(BPF_REG_0, 0),
466 	BPF_EXIT_INSN(),
467 
468 	/* subprog 1 */
469 	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
470 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
471 	BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
472 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 5),
473 	/* spill unchecked sk_ptr into stack of caller */
474 	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
475 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
476 	BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0),
477 	BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
478 	BPF_EXIT_INSN(),
479 
480 	/* subprog 2 */
481 	BPF_SK_LOOKUP(sk_lookup_tcp),
482 	BPF_EXIT_INSN(),
483 	},
484 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
485 	.errstr = "Unreleased reference",
486 	.result = REJECT,
487 },
488 {
489 	"reference tracking in call: sk_ptr spill into caller stack",
490 	.insns = {
491 	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
492 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
493 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
494 	BPF_MOV64_IMM(BPF_REG_0, 0),
495 	BPF_EXIT_INSN(),
496 
497 	/* subprog 1 */
498 	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
499 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
500 	BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
501 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 8),
502 	/* spill unchecked sk_ptr into stack of caller */
503 	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
504 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
505 	BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0),
506 	BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
507 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
508 	/* now the sk_ptr is verified, free the reference */
509 	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_4, 0),
510 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
511 	BPF_EXIT_INSN(),
512 
513 	/* subprog 2 */
514 	BPF_SK_LOOKUP(sk_lookup_tcp),
515 	BPF_EXIT_INSN(),
516 	},
517 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
518 	.result = ACCEPT,
519 },
520 {
521 	"reference tracking: allow LD_ABS",
522 	.insns = {
523 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
524 	BPF_SK_LOOKUP(sk_lookup_tcp),
525 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
526 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
527 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
528 	BPF_LD_ABS(BPF_B, 0),
529 	BPF_LD_ABS(BPF_H, 0),
530 	BPF_LD_ABS(BPF_W, 0),
531 	BPF_EXIT_INSN(),
532 	},
533 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
534 	.result = ACCEPT,
535 },
536 {
537 	"reference tracking: forbid LD_ABS while holding reference",
538 	.insns = {
539 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
540 	BPF_SK_LOOKUP(sk_lookup_tcp),
541 	BPF_LD_ABS(BPF_B, 0),
542 	BPF_LD_ABS(BPF_H, 0),
543 	BPF_LD_ABS(BPF_W, 0),
544 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
545 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
546 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
547 	BPF_EXIT_INSN(),
548 	},
549 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
550 	.errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references",
551 	.result = REJECT,
552 },
553 {
554 	"reference tracking: allow LD_IND",
555 	.insns = {
556 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
557 	BPF_SK_LOOKUP(sk_lookup_tcp),
558 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
559 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
560 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
561 	BPF_MOV64_IMM(BPF_REG_7, 1),
562 	BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
563 	BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
564 	BPF_EXIT_INSN(),
565 	},
566 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
567 	.result = ACCEPT,
568 	.retval = 1,
569 },
570 {
571 	"reference tracking: forbid LD_IND while holding reference",
572 	.insns = {
573 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
574 	BPF_SK_LOOKUP(sk_lookup_tcp),
575 	BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
576 	BPF_MOV64_IMM(BPF_REG_7, 1),
577 	BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
578 	BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
579 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_4),
580 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
581 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
582 	BPF_EXIT_INSN(),
583 	},
584 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
585 	.errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references",
586 	.result = REJECT,
587 },
588 {
589 	"reference tracking: check reference or tail call",
590 	.insns = {
591 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
592 	BPF_SK_LOOKUP(sk_lookup_tcp),
593 	/* if (sk) bpf_sk_release() */
594 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
595 	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 7),
596 	/* bpf_tail_call() */
597 	BPF_MOV64_IMM(BPF_REG_3, 3),
598 	BPF_LD_MAP_FD(BPF_REG_2, 0),
599 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
600 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
601 	BPF_MOV64_IMM(BPF_REG_0, 0),
602 	BPF_EXIT_INSN(),
603 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
604 	BPF_EXIT_INSN(),
605 	},
606 	.fixup_prog1 = { 17 },
607 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
608 	.result = ACCEPT,
609 },
610 {
611 	"reference tracking: release reference then tail call",
612 	.insns = {
613 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
614 	BPF_SK_LOOKUP(sk_lookup_tcp),
615 	/* if (sk) bpf_sk_release() */
616 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
617 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
618 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
619 	/* bpf_tail_call() */
620 	BPF_MOV64_IMM(BPF_REG_3, 3),
621 	BPF_LD_MAP_FD(BPF_REG_2, 0),
622 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
623 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
624 	BPF_MOV64_IMM(BPF_REG_0, 0),
625 	BPF_EXIT_INSN(),
626 	},
627 	.fixup_prog1 = { 18 },
628 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
629 	.result = ACCEPT,
630 },
631 {
632 	"reference tracking: leak possible reference over tail call",
633 	.insns = {
634 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
635 	/* Look up socket and store in REG_6 */
636 	BPF_SK_LOOKUP(sk_lookup_tcp),
637 	/* bpf_tail_call() */
638 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
639 	BPF_MOV64_IMM(BPF_REG_3, 3),
640 	BPF_LD_MAP_FD(BPF_REG_2, 0),
641 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
642 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
643 	BPF_MOV64_IMM(BPF_REG_0, 0),
644 	/* if (sk) bpf_sk_release() */
645 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
646 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
647 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
648 	BPF_EXIT_INSN(),
649 	},
650 	.fixup_prog1 = { 16 },
651 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
652 	.errstr = "tail_call would lead to reference leak",
653 	.result = REJECT,
654 },
655 {
656 	"reference tracking: leak checked reference over tail call",
657 	.insns = {
658 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
659 	/* Look up socket and store in REG_6 */
660 	BPF_SK_LOOKUP(sk_lookup_tcp),
661 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
662 	/* if (!sk) goto end */
663 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
664 	/* bpf_tail_call() */
665 	BPF_MOV64_IMM(BPF_REG_3, 0),
666 	BPF_LD_MAP_FD(BPF_REG_2, 0),
667 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
668 	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
669 	BPF_MOV64_IMM(BPF_REG_0, 0),
670 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
671 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
672 	BPF_EXIT_INSN(),
673 	},
674 	.fixup_prog1 = { 17 },
675 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
676 	.errstr = "tail_call would lead to reference leak",
677 	.result = REJECT,
678 },
679 {
680 	"reference tracking: mangle and release sock_or_null",
681 	.insns = {
682 	BPF_SK_LOOKUP(sk_lookup_tcp),
683 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
684 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5),
685 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
686 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
687 	BPF_EXIT_INSN(),
688 	},
689 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
690 	.errstr = "R1 pointer arithmetic on sock_or_null prohibited",
691 	.result = REJECT,
692 },
693 {
694 	"reference tracking: mangle and release sock",
695 	.insns = {
696 	BPF_SK_LOOKUP(sk_lookup_tcp),
697 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
698 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
699 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5),
700 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
701 	BPF_EXIT_INSN(),
702 	},
703 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
704 	.errstr = "R1 pointer arithmetic on sock prohibited",
705 	.result = REJECT,
706 },
707 {
708 	"reference tracking: access member",
709 	.insns = {
710 	BPF_SK_LOOKUP(sk_lookup_tcp),
711 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
712 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
713 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4),
714 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
715 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
716 	BPF_EXIT_INSN(),
717 	},
718 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
719 	.result = ACCEPT,
720 },
721 {
722 	"reference tracking: write to member",
723 	.insns = {
724 	BPF_SK_LOOKUP(sk_lookup_tcp),
725 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
726 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
727 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
728 	BPF_LD_IMM64(BPF_REG_2, 42),
729 	BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_2,
730 		    offsetof(struct bpf_sock, mark)),
731 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
732 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
733 	BPF_LD_IMM64(BPF_REG_0, 0),
734 	BPF_EXIT_INSN(),
735 	},
736 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
737 	.errstr = "cannot write into sock",
738 	.result = REJECT,
739 },
740 {
741 	"reference tracking: invalid 64-bit access of member",
742 	.insns = {
743 	BPF_SK_LOOKUP(sk_lookup_tcp),
744 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
745 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
746 	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
747 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
748 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
749 	BPF_EXIT_INSN(),
750 	},
751 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
752 	.errstr = "invalid sock access off=0 size=8",
753 	.result = REJECT,
754 },
755 {
756 	"reference tracking: access after release",
757 	.insns = {
758 	BPF_SK_LOOKUP(sk_lookup_tcp),
759 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
760 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
761 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
762 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
763 	BPF_EXIT_INSN(),
764 	},
765 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
766 	.errstr = "!read_ok",
767 	.result = REJECT,
768 },
769 {
770 	"reference tracking: direct access for lookup",
771 	.insns = {
772 	/* Check that the packet is at least 64B long */
773 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
774 		    offsetof(struct __sk_buff, data)),
775 	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
776 		    offsetof(struct __sk_buff, data_end)),
777 	BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
778 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 64),
779 	BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 9),
780 	/* sk = sk_lookup_tcp(ctx, skb->data, ...) */
781 	BPF_MOV64_IMM(BPF_REG_3, sizeof(struct bpf_sock_tuple)),
782 	BPF_MOV64_IMM(BPF_REG_4, 0),
783 	BPF_MOV64_IMM(BPF_REG_5, 0),
784 	BPF_EMIT_CALL(BPF_FUNC_sk_lookup_tcp),
785 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
786 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
787 	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4),
788 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
789 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
790 	BPF_EXIT_INSN(),
791 	},
792 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
793 	.result = ACCEPT,
794 },
795 {
796 	"reference tracking: use ptr from bpf_tcp_sock() after release",
797 	.insns = {
798 	BPF_SK_LOOKUP(sk_lookup_tcp),
799 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
800 	BPF_EXIT_INSN(),
801 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
802 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
803 	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
804 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
805 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
806 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
807 	BPF_EXIT_INSN(),
808 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
809 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
810 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
811 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_tcp_sock, snd_cwnd)),
812 	BPF_EXIT_INSN(),
813 	},
814 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
815 	.result = REJECT,
816 	.errstr = "invalid mem access",
817 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
818 },
819 {
820 	"reference tracking: use ptr from bpf_sk_fullsock() after release",
821 	.insns = {
822 	BPF_SK_LOOKUP(sk_lookup_tcp),
823 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
824 	BPF_EXIT_INSN(),
825 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
826 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
827 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
828 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
829 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
830 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
831 	BPF_EXIT_INSN(),
832 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
833 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
834 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
835 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
836 	BPF_EXIT_INSN(),
837 	},
838 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
839 	.result = REJECT,
840 	.errstr = "invalid mem access",
841 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
842 },
843 {
844 	"reference tracking: use ptr from bpf_sk_fullsock(tp) after release",
845 	.insns = {
846 	BPF_SK_LOOKUP(sk_lookup_tcp),
847 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
848 	BPF_EXIT_INSN(),
849 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
850 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
851 	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
852 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
853 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
854 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
855 	BPF_EXIT_INSN(),
856 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
857 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
858 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
859 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
860 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
861 	BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1),
862 	BPF_EXIT_INSN(),
863 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
864 	BPF_EXIT_INSN(),
865 	},
866 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
867 	.result = REJECT,
868 	.errstr = "invalid mem access",
869 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
870 },
871 {
872 	"reference tracking: use sk after bpf_sk_release(tp)",
873 	.insns = {
874 	BPF_SK_LOOKUP(sk_lookup_tcp),
875 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
876 	BPF_EXIT_INSN(),
877 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
878 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
879 	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
880 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
881 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
882 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
883 	BPF_EXIT_INSN(),
884 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
885 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
886 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
887 	BPF_EXIT_INSN(),
888 	},
889 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
890 	.result = REJECT,
891 	.errstr = "invalid mem access",
892 	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
893 },
894 {
895 	"reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)",
896 	.insns = {
897 	BPF_SK_LOOKUP(sk_lookup_tcp),
898 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
899 	BPF_EXIT_INSN(),
900 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
901 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
902 	BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
903 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
904 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
905 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
906 	BPF_EXIT_INSN(),
907 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
908 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
909 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
910 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, src_port)),
911 	BPF_EXIT_INSN(),
912 	},
913 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
914 	.result = ACCEPT,
915 },
916 {
917 	"reference tracking: bpf_sk_release(listen_sk)",
918 	.insns = {
919 	BPF_SK_LOOKUP(sk_lookup_tcp),
920 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
921 	BPF_EXIT_INSN(),
922 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
923 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
924 	BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
925 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
926 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
927 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
928 	BPF_EXIT_INSN(),
929 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
930 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
931 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
932 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
933 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
934 	BPF_EXIT_INSN(),
935 	},
936 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
937 	.result = REJECT,
938 	.errstr = "R1 must be referenced when passed to release function",
939 },
940 {
941 	/* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */
942 	"reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)",
943 	.insns = {
944 	BPF_SK_LOOKUP(sk_lookup_tcp),
945 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
946 	BPF_EXIT_INSN(),
947 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
948 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
949 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
950 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
951 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
952 	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
953 	BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
954 	BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 3),
955 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
956 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
957 	BPF_EXIT_INSN(),
958 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_8, offsetof(struct bpf_tcp_sock, snd_cwnd)),
959 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
960 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
961 	BPF_EXIT_INSN(),
962 	},
963 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
964 	.result = REJECT,
965 	.errstr = "invalid mem access",
966 },
967 {
968 	"reference tracking: branch tracking valid pointer null comparison",
969 	.insns = {
970 	BPF_SK_LOOKUP(sk_lookup_tcp),
971 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
972 	BPF_MOV64_IMM(BPF_REG_3, 1),
973 	BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1),
974 	BPF_MOV64_IMM(BPF_REG_3, 0),
975 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 2),
976 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
977 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
978 	BPF_EXIT_INSN(),
979 	},
980 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
981 	.result = ACCEPT,
982 },
983 {
984 	"reference tracking: branch tracking valid pointer value comparison",
985 	.insns = {
986 	BPF_SK_LOOKUP(sk_lookup_tcp),
987 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
988 	BPF_MOV64_IMM(BPF_REG_3, 1),
989 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 4),
990 	BPF_MOV64_IMM(BPF_REG_3, 0),
991 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 1234, 2),
992 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
993 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
994 	BPF_EXIT_INSN(),
995 	},
996 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
997 	.errstr = "Unreleased reference",
998 	.result = REJECT,
999 },
1000 {
1001 	"reference tracking: bpf_sk_release(btf_tcp_sock)",
1002 	.insns = {
1003 	BPF_SK_LOOKUP(sk_lookup_tcp),
1004 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1005 	BPF_EXIT_INSN(),
1006 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
1007 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
1008 	BPF_EMIT_CALL(BPF_FUNC_skc_to_tcp_sock),
1009 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
1010 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
1011 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
1012 	BPF_EXIT_INSN(),
1013 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
1014 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
1015 	BPF_EXIT_INSN(),
1016 	},
1017 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
1018 	.result = ACCEPT,
1019 	.result_unpriv = REJECT,
1020 	.errstr_unpriv = "unknown func",
1021 },
1022 {
1023 	"reference tracking: use ptr from bpf_skc_to_tcp_sock() after release",
1024 	.insns = {
1025 	BPF_SK_LOOKUP(sk_lookup_tcp),
1026 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1027 	BPF_EXIT_INSN(),
1028 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
1029 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
1030 	BPF_EMIT_CALL(BPF_FUNC_skc_to_tcp_sock),
1031 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
1032 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
1033 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
1034 	BPF_EXIT_INSN(),
1035 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
1036 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
1037 	BPF_EMIT_CALL(BPF_FUNC_sk_release),
1038 	BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_7, 0),
1039 	BPF_EXIT_INSN(),
1040 	},
1041 	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
1042 	.result = REJECT,
1043 	.errstr = "invalid mem access",
1044 	.result_unpriv = REJECT,
1045 	.errstr_unpriv = "unknown func",
1046 },
1047 {
1048 	"reference tracking: try to leak released ptr reg",
1049 	.insns = {
1050 		BPF_MOV64_IMM(BPF_REG_0, 0),
1051 		BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
1052 		BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
1053 		BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
1054 		BPF_LD_MAP_FD(BPF_REG_1, 0),
1055 		BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
1056 		BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1057 		BPF_EXIT_INSN(),
1058 		BPF_MOV64_REG(BPF_REG_9, BPF_REG_0),
1059 
1060 		BPF_MOV64_IMM(BPF_REG_0, 0),
1061 		BPF_LD_MAP_FD(BPF_REG_1, 0),
1062 		BPF_MOV64_IMM(BPF_REG_2, 8),
1063 		BPF_MOV64_IMM(BPF_REG_3, 0),
1064 		BPF_EMIT_CALL(BPF_FUNC_ringbuf_reserve),
1065 		BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1066 		BPF_EXIT_INSN(),
1067 		BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
1068 
1069 		BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
1070 		BPF_MOV64_IMM(BPF_REG_2, 0),
1071 		BPF_EMIT_CALL(BPF_FUNC_ringbuf_discard),
1072 		BPF_MOV64_IMM(BPF_REG_0, 0),
1073 
1074 		BPF_STX_MEM(BPF_DW, BPF_REG_9, BPF_REG_8, 0),
1075 		BPF_EXIT_INSN()
1076 	},
1077 	.fixup_map_array_48b = { 4 },
1078 	.fixup_map_ringbuf = { 11 },
1079 	.result = ACCEPT,
1080 	.result_unpriv = REJECT,
1081 	.errstr_unpriv = "R8 !read_ok"
1082 },
1083