Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  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: release reference without check",
 89	.insns = {
 90	BPF_SK_LOOKUP(sk_lookup_tcp),
 91	/* reference in r0 may be NULL */
 92	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
 93	BPF_MOV64_IMM(BPF_REG_2, 0),
 94	BPF_EMIT_CALL(BPF_FUNC_sk_release),
 95	BPF_EXIT_INSN(),
 96	},
 97	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
 98	.errstr = "type=sock_or_null expected=sock",
 99	.result = REJECT,
100},
101{
102	"reference tracking: release reference to sock_common without check",
103	.insns = {
104	BPF_SK_LOOKUP(skc_lookup_tcp),
105	/* reference in r0 may be NULL */
106	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
107	BPF_MOV64_IMM(BPF_REG_2, 0),
108	BPF_EMIT_CALL(BPF_FUNC_sk_release),
109	BPF_EXIT_INSN(),
110	},
111	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
112	.errstr = "type=sock_common_or_null expected=sock",
113	.result = REJECT,
114},
115{
116	"reference tracking: release reference",
117	.insns = {
118	BPF_SK_LOOKUP(sk_lookup_tcp),
119	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
120	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
121	BPF_EMIT_CALL(BPF_FUNC_sk_release),
122	BPF_EXIT_INSN(),
123	},
124	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
125	.result = ACCEPT,
126},
127{
128	"reference tracking: release reference to sock_common",
129	.insns = {
130	BPF_SK_LOOKUP(skc_lookup_tcp),
131	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
132	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
133	BPF_EMIT_CALL(BPF_FUNC_sk_release),
134	BPF_EXIT_INSN(),
135	},
136	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
137	.result = ACCEPT,
138},
139{
140	"reference tracking: release reference 2",
141	.insns = {
142	BPF_SK_LOOKUP(sk_lookup_tcp),
143	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
144	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
145	BPF_EXIT_INSN(),
146	BPF_EMIT_CALL(BPF_FUNC_sk_release),
147	BPF_EXIT_INSN(),
148	},
149	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
150	.result = ACCEPT,
151},
152{
153	"reference tracking: release reference twice",
154	.insns = {
155	BPF_SK_LOOKUP(sk_lookup_tcp),
156	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
157	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
158	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
159	BPF_EMIT_CALL(BPF_FUNC_sk_release),
160	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
161	BPF_EMIT_CALL(BPF_FUNC_sk_release),
162	BPF_EXIT_INSN(),
163	},
164	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
165	.errstr = "type=inv expected=sock",
166	.result = REJECT,
167},
168{
169	"reference tracking: release reference twice inside branch",
170	.insns = {
171	BPF_SK_LOOKUP(sk_lookup_tcp),
172	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
173	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
174	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3), /* goto end */
175	BPF_EMIT_CALL(BPF_FUNC_sk_release),
176	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
177	BPF_EMIT_CALL(BPF_FUNC_sk_release),
178	BPF_EXIT_INSN(),
179	},
180	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
181	.errstr = "type=inv expected=sock",
182	.result = REJECT,
183},
184{
185	"reference tracking: alloc, check, free in one subbranch",
186	.insns = {
187	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
188		    offsetof(struct __sk_buff, data)),
189	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
190		    offsetof(struct __sk_buff, data_end)),
191	BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
192	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16),
193	/* if (offsetof(skb, mark) > data_len) exit; */
194	BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1),
195	BPF_EXIT_INSN(),
196	BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2,
197		    offsetof(struct __sk_buff, mark)),
198	BPF_SK_LOOKUP(sk_lookup_tcp),
199	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 1), /* mark == 0? */
200	/* Leak reference in R0 */
201	BPF_EXIT_INSN(),
202	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
203	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
204	BPF_EMIT_CALL(BPF_FUNC_sk_release),
205	BPF_EXIT_INSN(),
206	},
207	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
208	.errstr = "Unreleased reference",
209	.result = REJECT,
210	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
211},
212{
213	"reference tracking: alloc, check, free in both subbranches",
214	.insns = {
215	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
216		    offsetof(struct __sk_buff, data)),
217	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
218		    offsetof(struct __sk_buff, data_end)),
219	BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
220	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 16),
221	/* if (offsetof(skb, mark) > data_len) exit; */
222	BPF_JMP_REG(BPF_JLE, BPF_REG_0, BPF_REG_3, 1),
223	BPF_EXIT_INSN(),
224	BPF_LDX_MEM(BPF_W, BPF_REG_6, BPF_REG_2,
225		    offsetof(struct __sk_buff, mark)),
226	BPF_SK_LOOKUP(sk_lookup_tcp),
227	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 4), /* mark == 0? */
228	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
229	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
230	BPF_EMIT_CALL(BPF_FUNC_sk_release),
231	BPF_EXIT_INSN(),
232	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), /* sk NULL? */
233	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
234	BPF_EMIT_CALL(BPF_FUNC_sk_release),
235	BPF_EXIT_INSN(),
236	},
237	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
238	.result = ACCEPT,
239	.flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
240},
241{
242	"reference tracking in call: free reference in subprog",
243	.insns = {
244	BPF_SK_LOOKUP(sk_lookup_tcp),
245	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */
246	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
247	BPF_MOV64_IMM(BPF_REG_0, 0),
248	BPF_EXIT_INSN(),
249
250	/* subprog 1 */
251	BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
252	BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1),
253	BPF_EMIT_CALL(BPF_FUNC_sk_release),
254	BPF_EXIT_INSN(),
255	},
256	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
257	.result = ACCEPT,
258},
259{
260	"reference tracking in call: free reference in subprog and outside",
261	.insns = {
262	BPF_SK_LOOKUP(sk_lookup_tcp),
263	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), /* unchecked reference */
264	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
265	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3),
266	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
267	BPF_EMIT_CALL(BPF_FUNC_sk_release),
268	BPF_EXIT_INSN(),
269
270	/* subprog 1 */
271	BPF_MOV64_REG(BPF_REG_2, BPF_REG_1),
272	BPF_JMP_IMM(BPF_JEQ, BPF_REG_2, 0, 1),
273	BPF_EMIT_CALL(BPF_FUNC_sk_release),
274	BPF_EXIT_INSN(),
275	},
276	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
277	.errstr = "type=inv expected=sock",
278	.result = REJECT,
279},
280{
281	"reference tracking in call: alloc & leak reference in subprog",
282	.insns = {
283	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
284	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
285	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 3),
286	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
287	BPF_MOV64_IMM(BPF_REG_0, 0),
288	BPF_EXIT_INSN(),
289
290	/* subprog 1 */
291	BPF_MOV64_REG(BPF_REG_6, BPF_REG_4),
292	BPF_SK_LOOKUP(sk_lookup_tcp),
293	/* spill unchecked sk_ptr into stack of caller */
294	BPF_STX_MEM(BPF_DW, BPF_REG_6, BPF_REG_0, 0),
295	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
296	BPF_EXIT_INSN(),
297	},
298	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
299	.errstr = "Unreleased reference",
300	.result = REJECT,
301},
302{
303	"reference tracking in call: alloc in subprog, release outside",
304	.insns = {
305	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
306	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 4),
307	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
308	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
309	BPF_EMIT_CALL(BPF_FUNC_sk_release),
310	BPF_EXIT_INSN(),
311
312	/* subprog 1 */
313	BPF_SK_LOOKUP(sk_lookup_tcp),
314	BPF_EXIT_INSN(), /* return sk */
315	},
316	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
317	.retval = POINTER_VALUE,
318	.result = ACCEPT,
319},
320{
321	"reference tracking in call: sk_ptr leak into caller stack",
322	.insns = {
323	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
324	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
325	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
326	BPF_MOV64_IMM(BPF_REG_0, 0),
327	BPF_EXIT_INSN(),
328
329	/* subprog 1 */
330	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
331	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
332	BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
333	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 5),
334	/* spill unchecked sk_ptr into stack of caller */
335	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
336	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
337	BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0),
338	BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
339	BPF_EXIT_INSN(),
340
341	/* subprog 2 */
342	BPF_SK_LOOKUP(sk_lookup_tcp),
343	BPF_EXIT_INSN(),
344	},
345	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
346	.errstr = "Unreleased reference",
347	.result = REJECT,
348},
349{
350	"reference tracking in call: sk_ptr spill into caller stack",
351	.insns = {
352	BPF_MOV64_REG(BPF_REG_4, BPF_REG_10),
353	BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, -8),
354	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
355	BPF_MOV64_IMM(BPF_REG_0, 0),
356	BPF_EXIT_INSN(),
357
358	/* subprog 1 */
359	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
360	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
361	BPF_STX_MEM(BPF_DW, BPF_REG_5, BPF_REG_4, 0),
362	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 8),
363	/* spill unchecked sk_ptr into stack of caller */
364	BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
365	BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, -8),
366	BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_5, 0),
367	BPF_STX_MEM(BPF_DW, BPF_REG_4, BPF_REG_0, 0),
368	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
369	/* now the sk_ptr is verified, free the reference */
370	BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_4, 0),
371	BPF_EMIT_CALL(BPF_FUNC_sk_release),
372	BPF_EXIT_INSN(),
373
374	/* subprog 2 */
375	BPF_SK_LOOKUP(sk_lookup_tcp),
376	BPF_EXIT_INSN(),
377	},
378	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
379	.result = ACCEPT,
380},
381{
382	"reference tracking: allow LD_ABS",
383	.insns = {
384	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
385	BPF_SK_LOOKUP(sk_lookup_tcp),
386	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
387	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
388	BPF_EMIT_CALL(BPF_FUNC_sk_release),
389	BPF_LD_ABS(BPF_B, 0),
390	BPF_LD_ABS(BPF_H, 0),
391	BPF_LD_ABS(BPF_W, 0),
392	BPF_EXIT_INSN(),
393	},
394	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
395	.result = ACCEPT,
396},
397{
398	"reference tracking: forbid LD_ABS while holding reference",
399	.insns = {
400	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
401	BPF_SK_LOOKUP(sk_lookup_tcp),
402	BPF_LD_ABS(BPF_B, 0),
403	BPF_LD_ABS(BPF_H, 0),
404	BPF_LD_ABS(BPF_W, 0),
405	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
406	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
407	BPF_EMIT_CALL(BPF_FUNC_sk_release),
408	BPF_EXIT_INSN(),
409	},
410	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
411	.errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references",
412	.result = REJECT,
413},
414{
415	"reference tracking: allow LD_IND",
416	.insns = {
417	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
418	BPF_SK_LOOKUP(sk_lookup_tcp),
419	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
420	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
421	BPF_EMIT_CALL(BPF_FUNC_sk_release),
422	BPF_MOV64_IMM(BPF_REG_7, 1),
423	BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
424	BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
425	BPF_EXIT_INSN(),
426	},
427	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
428	.result = ACCEPT,
429	.retval = 1,
430},
431{
432	"reference tracking: forbid LD_IND while holding reference",
433	.insns = {
434	BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
435	BPF_SK_LOOKUP(sk_lookup_tcp),
436	BPF_MOV64_REG(BPF_REG_4, BPF_REG_0),
437	BPF_MOV64_IMM(BPF_REG_7, 1),
438	BPF_LD_IND(BPF_W, BPF_REG_7, -0x200000),
439	BPF_MOV64_REG(BPF_REG_0, BPF_REG_7),
440	BPF_MOV64_REG(BPF_REG_1, BPF_REG_4),
441	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
442	BPF_EMIT_CALL(BPF_FUNC_sk_release),
443	BPF_EXIT_INSN(),
444	},
445	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
446	.errstr = "BPF_LD_[ABS|IND] cannot be mixed with socket references",
447	.result = REJECT,
448},
449{
450	"reference tracking: check reference or tail call",
451	.insns = {
452	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
453	BPF_SK_LOOKUP(sk_lookup_tcp),
454	/* if (sk) bpf_sk_release() */
455	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
456	BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 7),
457	/* bpf_tail_call() */
458	BPF_MOV64_IMM(BPF_REG_3, 2),
459	BPF_LD_MAP_FD(BPF_REG_2, 0),
460	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
461	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
462	BPF_MOV64_IMM(BPF_REG_0, 0),
463	BPF_EXIT_INSN(),
464	BPF_EMIT_CALL(BPF_FUNC_sk_release),
465	BPF_EXIT_INSN(),
466	},
467	.fixup_prog1 = { 17 },
468	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
469	.result = ACCEPT,
470},
471{
472	"reference tracking: release reference then tail call",
473	.insns = {
474	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
475	BPF_SK_LOOKUP(sk_lookup_tcp),
476	/* if (sk) bpf_sk_release() */
477	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
478	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
479	BPF_EMIT_CALL(BPF_FUNC_sk_release),
480	/* bpf_tail_call() */
481	BPF_MOV64_IMM(BPF_REG_3, 2),
482	BPF_LD_MAP_FD(BPF_REG_2, 0),
483	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
484	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
485	BPF_MOV64_IMM(BPF_REG_0, 0),
486	BPF_EXIT_INSN(),
487	},
488	.fixup_prog1 = { 18 },
489	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
490	.result = ACCEPT,
491},
492{
493	"reference tracking: leak possible reference over tail call",
494	.insns = {
495	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
496	/* Look up socket and store in REG_6 */
497	BPF_SK_LOOKUP(sk_lookup_tcp),
498	/* bpf_tail_call() */
499	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
500	BPF_MOV64_IMM(BPF_REG_3, 2),
501	BPF_LD_MAP_FD(BPF_REG_2, 0),
502	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
503	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
504	BPF_MOV64_IMM(BPF_REG_0, 0),
505	/* if (sk) bpf_sk_release() */
506	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
507	BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
508	BPF_EMIT_CALL(BPF_FUNC_sk_release),
509	BPF_EXIT_INSN(),
510	},
511	.fixup_prog1 = { 16 },
512	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
513	.errstr = "tail_call would lead to reference leak",
514	.result = REJECT,
515},
516{
517	"reference tracking: leak checked reference over tail call",
518	.insns = {
519	BPF_MOV64_REG(BPF_REG_7, BPF_REG_1),
520	/* Look up socket and store in REG_6 */
521	BPF_SK_LOOKUP(sk_lookup_tcp),
522	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
523	/* if (!sk) goto end */
524	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
525	/* bpf_tail_call() */
526	BPF_MOV64_IMM(BPF_REG_3, 0),
527	BPF_LD_MAP_FD(BPF_REG_2, 0),
528	BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
529	BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
530	BPF_MOV64_IMM(BPF_REG_0, 0),
531	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
532	BPF_EMIT_CALL(BPF_FUNC_sk_release),
533	BPF_EXIT_INSN(),
534	},
535	.fixup_prog1 = { 17 },
536	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
537	.errstr = "tail_call would lead to reference leak",
538	.result = REJECT,
539},
540{
541	"reference tracking: mangle and release sock_or_null",
542	.insns = {
543	BPF_SK_LOOKUP(sk_lookup_tcp),
544	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
545	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5),
546	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1),
547	BPF_EMIT_CALL(BPF_FUNC_sk_release),
548	BPF_EXIT_INSN(),
549	},
550	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
551	.errstr = "R1 pointer arithmetic on sock_or_null prohibited",
552	.result = REJECT,
553},
554{
555	"reference tracking: mangle and release sock",
556	.insns = {
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, 2),
560	BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 5),
561	BPF_EMIT_CALL(BPF_FUNC_sk_release),
562	BPF_EXIT_INSN(),
563	},
564	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
565	.errstr = "R1 pointer arithmetic on sock prohibited",
566	.result = REJECT,
567},
568{
569	"reference tracking: access member",
570	.insns = {
571	BPF_SK_LOOKUP(sk_lookup_tcp),
572	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
573	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
574	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4),
575	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
576	BPF_EMIT_CALL(BPF_FUNC_sk_release),
577	BPF_EXIT_INSN(),
578	},
579	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
580	.result = ACCEPT,
581},
582{
583	"reference tracking: write to member",
584	.insns = {
585	BPF_SK_LOOKUP(sk_lookup_tcp),
586	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
587	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
588	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
589	BPF_LD_IMM64(BPF_REG_2, 42),
590	BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_2,
591		    offsetof(struct bpf_sock, mark)),
592	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
593	BPF_EMIT_CALL(BPF_FUNC_sk_release),
594	BPF_LD_IMM64(BPF_REG_0, 0),
595	BPF_EXIT_INSN(),
596	},
597	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
598	.errstr = "cannot write into sock",
599	.result = REJECT,
600},
601{
602	"reference tracking: invalid 64-bit access of member",
603	.insns = {
604	BPF_SK_LOOKUP(sk_lookup_tcp),
605	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
606	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
607	BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 0),
608	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
609	BPF_EMIT_CALL(BPF_FUNC_sk_release),
610	BPF_EXIT_INSN(),
611	},
612	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
613	.errstr = "invalid sock access off=0 size=8",
614	.result = REJECT,
615},
616{
617	"reference tracking: access after release",
618	.insns = {
619	BPF_SK_LOOKUP(sk_lookup_tcp),
620	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
621	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
622	BPF_EMIT_CALL(BPF_FUNC_sk_release),
623	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
624	BPF_EXIT_INSN(),
625	},
626	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
627	.errstr = "!read_ok",
628	.result = REJECT,
629},
630{
631	"reference tracking: direct access for lookup",
632	.insns = {
633	/* Check that the packet is at least 64B long */
634	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
635		    offsetof(struct __sk_buff, data)),
636	BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
637		    offsetof(struct __sk_buff, data_end)),
638	BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
639	BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 64),
640	BPF_JMP_REG(BPF_JGT, BPF_REG_0, BPF_REG_3, 9),
641	/* sk = sk_lookup_tcp(ctx, skb->data, ...) */
642	BPF_MOV64_IMM(BPF_REG_3, sizeof(struct bpf_sock_tuple)),
643	BPF_MOV64_IMM(BPF_REG_4, 0),
644	BPF_MOV64_IMM(BPF_REG_5, 0),
645	BPF_EMIT_CALL(BPF_FUNC_sk_lookup_tcp),
646	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
647	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
648	BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_0, 4),
649	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
650	BPF_EMIT_CALL(BPF_FUNC_sk_release),
651	BPF_EXIT_INSN(),
652	},
653	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
654	.result = ACCEPT,
655},
656{
657	"reference tracking: use ptr from bpf_tcp_sock() after release",
658	.insns = {
659	BPF_SK_LOOKUP(sk_lookup_tcp),
660	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
661	BPF_EXIT_INSN(),
662	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
663	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
664	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
665	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
666	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
667	BPF_EMIT_CALL(BPF_FUNC_sk_release),
668	BPF_EXIT_INSN(),
669	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
670	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
671	BPF_EMIT_CALL(BPF_FUNC_sk_release),
672	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_tcp_sock, snd_cwnd)),
673	BPF_EXIT_INSN(),
674	},
675	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
676	.result = REJECT,
677	.errstr = "invalid mem access",
678},
679{
680	"reference tracking: use ptr from bpf_sk_fullsock() after release",
681	.insns = {
682	BPF_SK_LOOKUP(sk_lookup_tcp),
683	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
684	BPF_EXIT_INSN(),
685	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
686	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
687	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
688	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
689	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
690	BPF_EMIT_CALL(BPF_FUNC_sk_release),
691	BPF_EXIT_INSN(),
692	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
693	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
694	BPF_EMIT_CALL(BPF_FUNC_sk_release),
695	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
696	BPF_EXIT_INSN(),
697	},
698	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
699	.result = REJECT,
700	.errstr = "invalid mem access",
701},
702{
703	"reference tracking: use ptr from bpf_sk_fullsock(tp) after release",
704	.insns = {
705	BPF_SK_LOOKUP(sk_lookup_tcp),
706	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
707	BPF_EXIT_INSN(),
708	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
709	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
710	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
711	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
712	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
713	BPF_EMIT_CALL(BPF_FUNC_sk_release),
714	BPF_EXIT_INSN(),
715	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
716	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
717	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
718	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
719	BPF_EMIT_CALL(BPF_FUNC_sk_release),
720	BPF_JMP_IMM(BPF_JNE, BPF_REG_6, 0, 1),
721	BPF_EXIT_INSN(),
722	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
723	BPF_EXIT_INSN(),
724	},
725	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
726	.result = REJECT,
727	.errstr = "invalid mem access",
728},
729{
730	"reference tracking: use sk after bpf_sk_release(tp)",
731	.insns = {
732	BPF_SK_LOOKUP(sk_lookup_tcp),
733	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
734	BPF_EXIT_INSN(),
735	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
736	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
737	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
738	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
739	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
740	BPF_EMIT_CALL(BPF_FUNC_sk_release),
741	BPF_EXIT_INSN(),
742	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
743	BPF_EMIT_CALL(BPF_FUNC_sk_release),
744	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
745	BPF_EXIT_INSN(),
746	},
747	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
748	.result = REJECT,
749	.errstr = "invalid mem access",
750},
751{
752	"reference tracking: use ptr from bpf_get_listener_sock() after bpf_sk_release(sk)",
753	.insns = {
754	BPF_SK_LOOKUP(sk_lookup_tcp),
755	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
756	BPF_EXIT_INSN(),
757	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
758	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
759	BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
760	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
761	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
762	BPF_EMIT_CALL(BPF_FUNC_sk_release),
763	BPF_EXIT_INSN(),
764	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
765	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
766	BPF_EMIT_CALL(BPF_FUNC_sk_release),
767	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, src_port)),
768	BPF_EXIT_INSN(),
769	},
770	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
771	.result = ACCEPT,
772},
773{
774	"reference tracking: bpf_sk_release(listen_sk)",
775	.insns = {
776	BPF_SK_LOOKUP(sk_lookup_tcp),
777	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
778	BPF_EXIT_INSN(),
779	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
780	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
781	BPF_EMIT_CALL(BPF_FUNC_get_listener_sock),
782	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
783	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
784	BPF_EMIT_CALL(BPF_FUNC_sk_release),
785	BPF_EXIT_INSN(),
786	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
787	BPF_EMIT_CALL(BPF_FUNC_sk_release),
788	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6, offsetof(struct bpf_sock, type)),
789	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
790	BPF_EMIT_CALL(BPF_FUNC_sk_release),
791	BPF_EXIT_INSN(),
792	},
793	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
794	.result = REJECT,
795	.errstr = "reference has not been acquired before",
796},
797{
798	/* !bpf_sk_fullsock(sk) is checked but !bpf_tcp_sock(sk) is not checked */
799	"reference tracking: tp->snd_cwnd after bpf_sk_fullsock(sk) and bpf_tcp_sock(sk)",
800	.insns = {
801	BPF_SK_LOOKUP(sk_lookup_tcp),
802	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
803	BPF_EXIT_INSN(),
804	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
805	BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
806	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
807	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
808	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
809	BPF_EMIT_CALL(BPF_FUNC_tcp_sock),
810	BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
811	BPF_JMP_IMM(BPF_JNE, BPF_REG_7, 0, 3),
812	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
813	BPF_EMIT_CALL(BPF_FUNC_sk_release),
814	BPF_EXIT_INSN(),
815	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_8, offsetof(struct bpf_tcp_sock, snd_cwnd)),
816	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
817	BPF_EMIT_CALL(BPF_FUNC_sk_release),
818	BPF_EXIT_INSN(),
819	},
820	.prog_type = BPF_PROG_TYPE_SCHED_CLS,
821	.result = REJECT,
822	.errstr = "invalid mem access",
823},