Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.9.
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2022 Facebook */
  3
  4#include <errno.h>
  5#include <string.h>
  6#include <linux/bpf.h>
  7#include <bpf/bpf_helpers.h>
  8#include "bpf_misc.h"
  9
 10char _license[] SEC("license") = "GPL";
 11
 12struct test_info {
 13	int x;
 14	struct bpf_dynptr ptr;
 15};
 16
 17struct {
 18	__uint(type, BPF_MAP_TYPE_ARRAY);
 19	__uint(max_entries, 1);
 20	__type(key, __u32);
 21	__type(value, struct bpf_dynptr);
 22} array_map1 SEC(".maps");
 23
 24struct {
 25	__uint(type, BPF_MAP_TYPE_ARRAY);
 26	__uint(max_entries, 1);
 27	__type(key, __u32);
 28	__type(value, struct test_info);
 29} array_map2 SEC(".maps");
 30
 31struct {
 32	__uint(type, BPF_MAP_TYPE_ARRAY);
 33	__uint(max_entries, 1);
 34	__type(key, __u32);
 35	__type(value, __u32);
 36} array_map3 SEC(".maps");
 37
 38struct sample {
 39	int pid;
 40	long value;
 41	char comm[16];
 42};
 43
 44struct {
 45	__uint(type, BPF_MAP_TYPE_RINGBUF);
 46	__uint(max_entries, 4096);
 47} ringbuf SEC(".maps");
 48
 49int err, val;
 50
 51static int get_map_val_dynptr(struct bpf_dynptr *ptr)
 52{
 53	__u32 key = 0, *map_val;
 54
 55	bpf_map_update_elem(&array_map3, &key, &val, 0);
 56
 57	map_val = bpf_map_lookup_elem(&array_map3, &key);
 58	if (!map_val)
 59		return -ENOENT;
 60
 61	bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);
 62
 63	return 0;
 64}
 65
 66/* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
 67 * bpf_ringbuf_submit/discard_dynptr call
 68 */
 69SEC("?raw_tp")
 70__failure __msg("Unreleased reference id=1")
 71int ringbuf_missing_release1(void *ctx)
 72{
 73	struct bpf_dynptr ptr;
 74
 75	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
 76
 77	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
 78
 79	return 0;
 80}
 81
 82SEC("?raw_tp")
 83__failure __msg("Unreleased reference id=2")
 84int ringbuf_missing_release2(void *ctx)
 85{
 86	struct bpf_dynptr ptr1, ptr2;
 87	struct sample *sample;
 88
 89	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);
 90	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
 91
 92	sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));
 93	if (!sample) {
 94		bpf_ringbuf_discard_dynptr(&ptr1, 0);
 95		bpf_ringbuf_discard_dynptr(&ptr2, 0);
 96		return 0;
 97	}
 98
 99	bpf_ringbuf_submit_dynptr(&ptr1, 0);
100
101	/* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */
102
103	return 0;
104}
105
106static int missing_release_callback_fn(__u32 index, void *data)
107{
108	struct bpf_dynptr ptr;
109
110	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
111
112	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
113
114	return 0;
115}
116
117/* Any dynptr initialized within a callback must have bpf_dynptr_put called */
118SEC("?raw_tp")
119__failure __msg("Unreleased reference id")
120int ringbuf_missing_release_callback(void *ctx)
121{
122	bpf_loop(10, missing_release_callback_fn, NULL, 0);
123	return 0;
124}
125
126/* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
127SEC("?raw_tp")
128__failure __msg("arg 1 is an unacquired reference")
129int ringbuf_release_uninit_dynptr(void *ctx)
130{
131	struct bpf_dynptr ptr;
132
133	/* this should fail */
134	bpf_ringbuf_submit_dynptr(&ptr, 0);
135
136	return 0;
137}
138
139/* A dynptr can't be used after it has been invalidated */
140SEC("?raw_tp")
141__failure __msg("Expected an initialized dynptr as arg #3")
142int use_after_invalid(void *ctx)
143{
144	struct bpf_dynptr ptr;
145	char read_data[64];
146
147	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);
148
149	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
150
151	bpf_ringbuf_submit_dynptr(&ptr, 0);
152
153	/* this should fail */
154	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
155
156	return 0;
157}
158
159/* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
160SEC("?raw_tp")
161__failure __msg("type=mem expected=ringbuf_mem")
162int ringbuf_invalid_api(void *ctx)
163{
164	struct bpf_dynptr ptr;
165	struct sample *sample;
166
167	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
168	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
169	if (!sample)
170		goto done;
171
172	sample->pid = 123;
173
174	/* invalid API use. need to use dynptr API to submit/discard */
175	bpf_ringbuf_submit(sample, 0);
176
177done:
178	bpf_ringbuf_discard_dynptr(&ptr, 0);
179	return 0;
180}
181
182/* Can't add a dynptr to a map */
183SEC("?raw_tp")
184__failure __msg("invalid indirect read from stack")
185int add_dynptr_to_map1(void *ctx)
186{
187	struct bpf_dynptr ptr;
188	int key = 0;
189
190	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
191
192	/* this should fail */
193	bpf_map_update_elem(&array_map1, &key, &ptr, 0);
194
195	bpf_ringbuf_submit_dynptr(&ptr, 0);
196
197	return 0;
198}
199
200/* Can't add a struct with an embedded dynptr to a map */
201SEC("?raw_tp")
202__failure __msg("invalid indirect read from stack")
203int add_dynptr_to_map2(void *ctx)
204{
205	struct test_info x;
206	int key = 0;
207
208	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);
209
210	/* this should fail */
211	bpf_map_update_elem(&array_map2, &key, &x, 0);
212
213	bpf_ringbuf_submit_dynptr(&x.ptr, 0);
214
215	return 0;
216}
217
218/* A data slice can't be accessed out of bounds */
219SEC("?raw_tp")
220__failure __msg("value is outside of the allowed memory range")
221int data_slice_out_of_bounds_ringbuf(void *ctx)
222{
223	struct bpf_dynptr ptr;
224	void *data;
225
226	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
227
228	data  = bpf_dynptr_data(&ptr, 0, 8);
229	if (!data)
230		goto done;
231
232	/* can't index out of bounds of the data slice */
233	val = *((char *)data + 8);
234
235done:
236	bpf_ringbuf_submit_dynptr(&ptr, 0);
237	return 0;
238}
239
240SEC("?raw_tp")
241__failure __msg("value is outside of the allowed memory range")
242int data_slice_out_of_bounds_map_value(void *ctx)
243{
244	__u32 key = 0, map_val;
245	struct bpf_dynptr ptr;
246	void *data;
247
248	get_map_val_dynptr(&ptr);
249
250	data  = bpf_dynptr_data(&ptr, 0, sizeof(map_val));
251	if (!data)
252		return 0;
253
254	/* can't index out of bounds of the data slice */
255	val = *((char *)data + (sizeof(map_val) + 1));
256
257	return 0;
258}
259
260/* A data slice can't be used after it has been released */
261SEC("?raw_tp")
262__failure __msg("invalid mem access 'scalar'")
263int data_slice_use_after_release1(void *ctx)
264{
265	struct bpf_dynptr ptr;
266	struct sample *sample;
267
268	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
269	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
270	if (!sample)
271		goto done;
272
273	sample->pid = 123;
274
275	bpf_ringbuf_submit_dynptr(&ptr, 0);
276
277	/* this should fail */
278	val = sample->pid;
279
280	return 0;
281
282done:
283	bpf_ringbuf_discard_dynptr(&ptr, 0);
284	return 0;
285}
286
287/* A data slice can't be used after it has been released.
288 *
289 * This tests the case where the data slice tracks a dynptr (ptr2)
290 * that is at a non-zero offset from the frame pointer (ptr1 is at fp,
291 * ptr2 is at fp - 16).
292 */
293SEC("?raw_tp")
294__failure __msg("invalid mem access 'scalar'")
295int data_slice_use_after_release2(void *ctx)
296{
297	struct bpf_dynptr ptr1, ptr2;
298	struct sample *sample;
299
300	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);
301	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
302
303	sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));
304	if (!sample)
305		goto done;
306
307	sample->pid = 23;
308
309	bpf_ringbuf_submit_dynptr(&ptr2, 0);
310
311	/* this should fail */
312	sample->pid = 23;
313
314	bpf_ringbuf_submit_dynptr(&ptr1, 0);
315
316	return 0;
317
318done:
319	bpf_ringbuf_discard_dynptr(&ptr2, 0);
320	bpf_ringbuf_discard_dynptr(&ptr1, 0);
321	return 0;
322}
323
324/* A data slice must be first checked for NULL */
325SEC("?raw_tp")
326__failure __msg("invalid mem access 'mem_or_null'")
327int data_slice_missing_null_check1(void *ctx)
328{
329	struct bpf_dynptr ptr;
330	void *data;
331
332	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
333
334	data  = bpf_dynptr_data(&ptr, 0, 8);
335
336	/* missing if (!data) check */
337
338	/* this should fail */
339	*(__u8 *)data = 3;
340
341	bpf_ringbuf_submit_dynptr(&ptr, 0);
342	return 0;
343}
344
345/* A data slice can't be dereferenced if it wasn't checked for null */
346SEC("?raw_tp")
347__failure __msg("invalid mem access 'mem_or_null'")
348int data_slice_missing_null_check2(void *ctx)
349{
350	struct bpf_dynptr ptr;
351	__u64 *data1, *data2;
352
353	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
354
355	data1 = bpf_dynptr_data(&ptr, 0, 8);
356	data2 = bpf_dynptr_data(&ptr, 0, 8);
357	if (data1)
358		/* this should fail */
359		*data2 = 3;
360
361done:
362	bpf_ringbuf_discard_dynptr(&ptr, 0);
363	return 0;
364}
365
366/* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
367 * dynptr argument
368 */
369SEC("?raw_tp")
370__failure __msg("invalid indirect read from stack")
371int invalid_helper1(void *ctx)
372{
373	struct bpf_dynptr ptr;
374
375	get_map_val_dynptr(&ptr);
376
377	/* this should fail */
378	bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");
379
380	return 0;
381}
382
383/* A dynptr can't be passed into a helper function at a non-zero offset */
384SEC("?raw_tp")
385__failure __msg("Expected an initialized dynptr as arg #3")
386int invalid_helper2(void *ctx)
387{
388	struct bpf_dynptr ptr;
389	char read_data[64];
390
391	get_map_val_dynptr(&ptr);
392
393	/* this should fail */
394	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);
395
396	return 0;
397}
398
399/* A bpf_dynptr is invalidated if it's been written into */
400SEC("?raw_tp")
401__failure __msg("Expected an initialized dynptr as arg #1")
402int invalid_write1(void *ctx)
403{
404	struct bpf_dynptr ptr;
405	void *data;
406	__u8 x = 0;
407
408	get_map_val_dynptr(&ptr);
409
410	memcpy(&ptr, &x, sizeof(x));
411
412	/* this should fail */
413	data = bpf_dynptr_data(&ptr, 0, 1);
414
415	return 0;
416}
417
418/*
419 * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed
420 * offset
421 */
422SEC("?raw_tp")
423__failure __msg("Expected an initialized dynptr as arg #3")
424int invalid_write2(void *ctx)
425{
426	struct bpf_dynptr ptr;
427	char read_data[64];
428	__u8 x = 0;
429
430	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
431
432	memcpy((void *)&ptr + 8, &x, sizeof(x));
433
434	/* this should fail */
435	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
436
437	bpf_ringbuf_submit_dynptr(&ptr, 0);
438
439	return 0;
440}
441
442/*
443 * A bpf_dynptr can't be used as a dynptr if it has been written into at a
444 * non-const offset
445 */
446SEC("?raw_tp")
447__failure __msg("Expected an initialized dynptr as arg #1")
448int invalid_write3(void *ctx)
449{
450	struct bpf_dynptr ptr;
451	char stack_buf[16];
452	unsigned long len;
453	__u8 x = 0;
454
455	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
456
457	memcpy(stack_buf, &val, sizeof(val));
458	len = stack_buf[0] & 0xf;
459
460	memcpy((void *)&ptr + len, &x, sizeof(x));
461
462	/* this should fail */
463	bpf_ringbuf_submit_dynptr(&ptr, 0);
464
465	return 0;
466}
467
468static int invalid_write4_callback(__u32 index, void *data)
469{
470	*(__u32 *)data = 123;
471
472	return 0;
473}
474
475/* If the dynptr is written into in a callback function, it should
476 * be invalidated as a dynptr
477 */
478SEC("?raw_tp")
479__failure __msg("arg 1 is an unacquired reference")
480int invalid_write4(void *ctx)
481{
482	struct bpf_dynptr ptr;
483
484	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
485
486	bpf_loop(10, invalid_write4_callback, &ptr, 0);
487
488	/* this should fail */
489	bpf_ringbuf_submit_dynptr(&ptr, 0);
490
491	return 0;
492}
493
494/* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
495struct bpf_dynptr global_dynptr;
496
497SEC("?raw_tp")
498__failure __msg("type=map_value expected=fp")
499int global(void *ctx)
500{
501	/* this should fail */
502	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);
503
504	bpf_ringbuf_discard_dynptr(&global_dynptr, 0);
505
506	return 0;
507}
508
509/* A direct read should fail */
510SEC("?raw_tp")
511__failure __msg("invalid read from stack")
512int invalid_read1(void *ctx)
513{
514	struct bpf_dynptr ptr;
515
516	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
517
518	/* this should fail */
519	val = *(int *)&ptr;
520
521	bpf_ringbuf_discard_dynptr(&ptr, 0);
522
523	return 0;
524}
525
526/* A direct read at an offset should fail */
527SEC("?raw_tp")
528__failure __msg("cannot pass in dynptr at an offset")
529int invalid_read2(void *ctx)
530{
531	struct bpf_dynptr ptr;
532	char read_data[64];
533
534	get_map_val_dynptr(&ptr);
535
536	/* this should fail */
537	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);
538
539	return 0;
540}
541
542/* A direct read at an offset into the lower stack slot should fail */
543SEC("?raw_tp")
544__failure __msg("invalid read from stack")
545int invalid_read3(void *ctx)
546{
547	struct bpf_dynptr ptr1, ptr2;
548
549	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);
550	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);
551
552	/* this should fail */
553	memcpy(&val, (void *)&ptr1 + 8, sizeof(val));
554
555	bpf_ringbuf_discard_dynptr(&ptr1, 0);
556	bpf_ringbuf_discard_dynptr(&ptr2, 0);
557
558	return 0;
559}
560
561static int invalid_read4_callback(__u32 index, void *data)
562{
563	/* this should fail */
564	val = *(__u32 *)data;
565
566	return 0;
567}
568
569/* A direct read within a callback function should fail */
570SEC("?raw_tp")
571__failure __msg("invalid read from stack")
572int invalid_read4(void *ctx)
573{
574	struct bpf_dynptr ptr;
575
576	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
577
578	bpf_loop(10, invalid_read4_callback, &ptr, 0);
579
580	bpf_ringbuf_submit_dynptr(&ptr, 0);
581
582	return 0;
583}
584
585/* Initializing a dynptr on an offset should fail */
586SEC("?raw_tp")
587__failure __msg("invalid write to stack")
588int invalid_offset(void *ctx)
589{
590	struct bpf_dynptr ptr;
591
592	/* this should fail */
593	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);
594
595	bpf_ringbuf_discard_dynptr(&ptr, 0);
596
597	return 0;
598}
599
600/* Can't release a dynptr twice */
601SEC("?raw_tp")
602__failure __msg("arg 1 is an unacquired reference")
603int release_twice(void *ctx)
604{
605	struct bpf_dynptr ptr;
606
607	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
608
609	bpf_ringbuf_discard_dynptr(&ptr, 0);
610
611	/* this second release should fail */
612	bpf_ringbuf_discard_dynptr(&ptr, 0);
613
614	return 0;
615}
616
617static int release_twice_callback_fn(__u32 index, void *data)
618{
619	/* this should fail */
620	bpf_ringbuf_discard_dynptr(data, 0);
621
622	return 0;
623}
624
625/* Test that releasing a dynptr twice, where one of the releases happens
626 * within a calback function, fails
627 */
628SEC("?raw_tp")
629__failure __msg("arg 1 is an unacquired reference")
630int release_twice_callback(void *ctx)
631{
632	struct bpf_dynptr ptr;
633
634	bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);
635
636	bpf_ringbuf_discard_dynptr(&ptr, 0);
637
638	bpf_loop(10, release_twice_callback_fn, &ptr, 0);
639
640	return 0;
641}
642
643/* Reject unsupported local mem types for dynptr_from_mem API */
644SEC("?raw_tp")
645__failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data")
646int dynptr_from_mem_invalid_api(void *ctx)
647{
648	struct bpf_dynptr ptr;
649	int x = 0;
650
651	/* this should fail */
652	bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);
653
654	return 0;
655}