11590Srgrimes// SPDX-License-Identifier: GPL-2.0
21590Srgrimes/* Copyright (c) 2022 Facebook */
31590Srgrimes
41590Srgrimes#include <errno.h>
51590Srgrimes#include <string.h>
61590Srgrimes#include <stdbool.h>
71590Srgrimes#include <linux/bpf.h>
81590Srgrimes#include <bpf/bpf_helpers.h>
91590Srgrimes#include <linux/if_ether.h>
101590Srgrimes#include "bpf_misc.h"
111590Srgrimes#include "bpf_kfuncs.h"
121590Srgrimes
131590Srgrimeschar _license[] SEC("license") = "GPL";
141590Srgrimes
151590Srgrimesstruct test_info {
161590Srgrimes	int x;
171590Srgrimes	struct bpf_dynptr ptr;
181590Srgrimes};
191590Srgrimes
201590Srgrimesstruct {
211590Srgrimes	__uint(type, BPF_MAP_TYPE_ARRAY);
221590Srgrimes	__uint(max_entries, 1);
231590Srgrimes	__type(key, __u32);
241590Srgrimes	__type(value, struct bpf_dynptr);
251590Srgrimes} array_map1 SEC(".maps");
261590Srgrimes
271590Srgrimesstruct {
281590Srgrimes	__uint(type, BPF_MAP_TYPE_ARRAY);
291590Srgrimes	__uint(max_entries, 1);
3087709Smarkm	__type(key, __u32);
3187709Smarkm	__type(value, struct test_info);
3287709Smarkm} array_map2 SEC(".maps");
3387709Smarkm
341590Srgrimesstruct {
3528198Scharnier	__uint(type, BPF_MAP_TYPE_ARRAY);
361590Srgrimes	__uint(max_entries, 1);
371590Srgrimes	__type(key, __u32);
3887709Smarkm	__type(value, __u32);
391590Srgrimes} array_map3 SEC(".maps");
401590Srgrimes
4187709Smarkmstruct {
4228198Scharnier	__uint(type, BPF_MAP_TYPE_ARRAY);
431590Srgrimes	__uint(max_entries, 1);
441590Srgrimes	__type(key, __u32);
451590Srgrimes	__type(value, __u64);
461590Srgrimes} array_map4 SEC(".maps");
471590Srgrimes
481590Srgrimesstruct sample {
4928198Scharnier	int pid;
501590Srgrimes	long value;
511590Srgrimes	char comm[16];
5273986Sobrien};
531590Srgrimes
5493123Smikestruct {
551590Srgrimes	__uint(type, BPF_MAP_TYPE_RINGBUF);
561590Srgrimes	__uint(max_entries, 4096);
571590Srgrimes} ringbuf SEC(".maps");
581590Srgrimes
591590Srgrimesint err, val;
601590Srgrimes
611590Srgrimesstatic int get_map_val_dynptr(struct bpf_dynptr *ptr)
621590Srgrimes{
63227186Sed	__u32 key = 0, *map_val;
64227186Sed
65227186Sed	bpf_map_update_elem(&array_map3, &key, &val, 0);
661590Srgrimes
67227186Sed	map_val = bpf_map_lookup_elem(&array_map3, &key);
68227186Sed	if (!map_val)
69201612Sdwmalone		return -ENOENT;
70227186Sed
71227186Sed	bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);
72227186Sed
731590Srgrimes	return 0;
741590Srgrimes}
75201612Sdwmalone
761590Srgrimes/* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
77201612Sdwmalone * bpf_ringbuf_submit/discard_dynptr call
781590Srgrimes */
791590SrgrimesSEC("?raw_tp")
801590Srgrimes__failure __msg("Unreleased reference id=2")
8187709Smarkmint ringbuf_missing_release1(void *ctx)
8287709Smarkm{
831590Srgrimes	struct bpf_dynptr ptr = {};
8481607Speter
851590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
86209570Sgavin
8724360Simp	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
881590Srgrimes
891590Srgrimes	return 0;
901590Srgrimes}
911590Srgrimes
921590SrgrimesSEC("?raw_tp")
931590Srgrimes__failure __msg("Unreleased reference id=4")
941590Srgrimesint ringbuf_missing_release2(void *ctx)
9528198Scharnier{
961590Srgrimes	struct bpf_dynptr ptr1, ptr2;
971590Srgrimes	struct sample *sample;
981590Srgrimes
991590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);
1001590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
1011590Srgrimes
1021590Srgrimes	sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));
1031590Srgrimes	if (!sample) {
1041590Srgrimes		bpf_ringbuf_discard_dynptr(&ptr1, 0);
1051590Srgrimes		bpf_ringbuf_discard_dynptr(&ptr2, 0);
1061590Srgrimes		return 0;
1071590Srgrimes	}
1081590Srgrimes
1091590Srgrimes	bpf_ringbuf_submit_dynptr(&ptr1, 0);
1101590Srgrimes
1111590Srgrimes	/* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */
1121590Srgrimes
1131590Srgrimes	return 0;
1141590Srgrimes}
1151590Srgrimes
1161590Srgrimesstatic int missing_release_callback_fn(__u32 index, void *data)
1171590Srgrimes{
1181590Srgrimes	struct bpf_dynptr ptr;
1191590Srgrimes
1201590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1211590Srgrimes
1221590Srgrimes	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
1231590Srgrimes
1241590Srgrimes	return 0;
1251590Srgrimes}
1261590Srgrimes
1271590Srgrimes/* Any dynptr initialized within a callback must have bpf_dynptr_put called */
1281590SrgrimesSEC("?raw_tp")
12928198Scharnier__failure __msg("Unreleased reference id")
13028198Scharnierint ringbuf_missing_release_callback(void *ctx)
1311590Srgrimes{
1321590Srgrimes	bpf_loop(10, missing_release_callback_fn, NULL, 0);
1331590Srgrimes	return 0;
1341590Srgrimes}
1351590Srgrimes
13628198Scharnier/* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
13728198ScharnierSEC("?raw_tp")
1381590Srgrimes__failure __msg("arg 1 is an unacquired reference")
1391590Srgrimesint ringbuf_release_uninit_dynptr(void *ctx)
1401590Srgrimes{
1411590Srgrimes	struct bpf_dynptr ptr;
1421590Srgrimes
1431590Srgrimes	/* this should fail */
1441590Srgrimes	bpf_ringbuf_submit_dynptr(&ptr, 0);
1451590Srgrimes
1461590Srgrimes	return 0;
1471590Srgrimes}
1481590Srgrimes
1491590Srgrimes/* A dynptr can't be used after it has been invalidated */
1501590SrgrimesSEC("?raw_tp")
1511590Srgrimes__failure __msg("Expected an initialized dynptr as arg #3")
1521590Srgrimesint use_after_invalid(void *ctx)
1531590Srgrimes{
1541590Srgrimes	struct bpf_dynptr ptr;
1551590Srgrimes	char read_data[64];
1561590Srgrimes
157209570Sgavin	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);
1581590Srgrimes
1591590Srgrimes	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
1601590Srgrimes
161209570Sgavin	bpf_ringbuf_submit_dynptr(&ptr, 0);
1621590Srgrimes
163209570Sgavin	/* this should fail */
164209570Sgavin	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
1651590Srgrimes
166209570Sgavin	return 0;
1671590Srgrimes}
1681590Srgrimes
1691590Srgrimes/* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
1701590SrgrimesSEC("?raw_tp")
1711590Srgrimes__failure __msg("type=mem expected=ringbuf_mem")
1721590Srgrimesint ringbuf_invalid_api(void *ctx)
1731590Srgrimes{
1741590Srgrimes	struct bpf_dynptr ptr;
1751590Srgrimes	struct sample *sample;
1761590Srgrimes
1771590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
1781590Srgrimes	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
1791590Srgrimes	if (!sample)
1801590Srgrimes		goto done;
1811590Srgrimes
1821590Srgrimes	sample->pid = 123;
18328198Scharnier
184209570Sgavin	/* invalid API use. need to use dynptr API to submit/discard */
185209570Sgavin	bpf_ringbuf_submit(sample, 0);
18628198Scharnier
187209570Sgavindone:
188209570Sgavin	bpf_ringbuf_discard_dynptr(&ptr, 0);
189209570Sgavin	return 0;
19028198Scharnier}
19128198Scharnier
1921590Srgrimes/* Can't add a dynptr to a map */
1931590SrgrimesSEC("?raw_tp")
1941590Srgrimes__failure __msg("invalid indirect read from stack")
1951590Srgrimesint add_dynptr_to_map1(void *ctx)
1961590Srgrimes{
1971590Srgrimes	struct bpf_dynptr ptr;
1981590Srgrimes	int key = 0;
1991590Srgrimes
2001590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
2011590Srgrimes
202209570Sgavin	/* this should fail */
203209570Sgavin	bpf_map_update_elem(&array_map1, &key, &ptr, 0);
2041590Srgrimes
2051590Srgrimes	bpf_ringbuf_submit_dynptr(&ptr, 0);
2061590Srgrimes
2071590Srgrimes	return 0;
2081590Srgrimes}
2091590Srgrimes
2101590Srgrimes/* Can't add a struct with an embedded dynptr to a map */
2111590SrgrimesSEC("?raw_tp")
212209570Sgavin__failure __msg("invalid indirect read from stack")
2131590Srgrimesint add_dynptr_to_map2(void *ctx)
2141590Srgrimes{
2151590Srgrimes	struct test_info x;
2161590Srgrimes	int key = 0;
2171590Srgrimes
21846203Sphk	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);
21946203Sphk
2201590Srgrimes	/* this should fail */
2211590Srgrimes	bpf_map_update_elem(&array_map2, &key, &x, 0);
2221590Srgrimes
2231590Srgrimes	bpf_ringbuf_submit_dynptr(&x.ptr, 0);
2241590Srgrimes
2251590Srgrimes	return 0;
226227186Sed}
227201612Sdwmalone
2281590Srgrimes/* A data slice can't be accessed out of bounds */
229201612SdwmaloneSEC("?raw_tp")
230201612Sdwmalone__failure __msg("value is outside of the allowed memory range")
2311590Srgrimesint data_slice_out_of_bounds_ringbuf(void *ctx)
2321590Srgrimes{
2331590Srgrimes	struct bpf_dynptr ptr;
2341590Srgrimes	void *data;
2351590Srgrimes
2361590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
2371590Srgrimes
2381590Srgrimes	data  = bpf_dynptr_data(&ptr, 0, 8);
2391590Srgrimes	if (!data)
2401590Srgrimes		goto done;
2411590Srgrimes
24228198Scharnier	/* can't index out of bounds of the data slice */
2431590Srgrimes	val = *((char *)data + 8);
2441590Srgrimes
2451590Srgrimesdone:
2461590Srgrimes	bpf_ringbuf_submit_dynptr(&ptr, 0);
2471590Srgrimes	return 0;
2481590Srgrimes}
2491590Srgrimes
2501590Srgrimes/* A data slice can't be accessed out of bounds */
2511590SrgrimesSEC("?tc")
25228198Scharnier__failure __msg("value is outside of the allowed memory range")
2531590Srgrimesint data_slice_out_of_bounds_skb(struct __sk_buff *skb)
2541590Srgrimes{
2551590Srgrimes	struct bpf_dynptr ptr;
2561590Srgrimes	struct ethhdr *hdr;
2571590Srgrimes	char buffer[sizeof(*hdr)] = {};
2581590Srgrimes
2591590Srgrimes	bpf_dynptr_from_skb(skb, 0, &ptr);
2601590Srgrimes
2611590Srgrimes	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
2621590Srgrimes	if (!hdr)
2631590Srgrimes		return SK_DROP;
2641590Srgrimes
2651590Srgrimes	/* this should fail */
2661590Srgrimes	*(__u8*)(hdr + 1) = 1;
2671590Srgrimes
2681590Srgrimes	return SK_PASS;
2691590Srgrimes}
2701590Srgrimes
2711590SrgrimesSEC("?raw_tp")
2721590Srgrimes__failure __msg("value is outside of the allowed memory range")
2731590Srgrimesint data_slice_out_of_bounds_map_value(void *ctx)
2741590Srgrimes{
2751590Srgrimes	__u32 map_val;
2761590Srgrimes	struct bpf_dynptr ptr;
2771590Srgrimes	void *data;
278227186Sed
279201612Sdwmalone	get_map_val_dynptr(&ptr);
2801590Srgrimes
28148566Sbillf	data  = bpf_dynptr_data(&ptr, 0, sizeof(map_val));
2821590Srgrimes	if (!data)
283209570Sgavin		return 0;
2841590Srgrimes
285209570Sgavin	/* can't index out of bounds of the data slice */
28648566Sbillf	val = *((char *)data + (sizeof(map_val) + 1));
287209570Sgavin
28887763Smarkm	return 0;
2891590Srgrimes}
2901590Srgrimes
2911590Srgrimes/* A data slice can't be used after it has been released */
292227186SedSEC("?raw_tp")
293201612Sdwmalone__failure __msg("invalid mem access 'scalar'")
2941590Srgrimesint data_slice_use_after_release1(void *ctx)
2951590Srgrimes{
2961590Srgrimes	struct bpf_dynptr ptr;
29728198Scharnier	struct sample *sample;
29828198Scharnier
2991590Srgrimes	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
3001590Srgrimes	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
3011590Srgrimes	if (!sample)
302227186Sed		goto done;
303201612Sdwmalone
3041590Srgrimes	sample->pid = 123;
3051590Srgrimes
3061590Srgrimes	bpf_ringbuf_submit_dynptr(&ptr, 0);
3071590Srgrimes
3081590Srgrimes	/* this should fail */
30928198Scharnier	val = sample->pid;
31028198Scharnier
3111590Srgrimes	return 0;
3121590Srgrimes
31328198Scharnierdone:
314201612Sdwmalone	bpf_ringbuf_discard_dynptr(&ptr, 0);
3151590Srgrimes	return 0;
31628198Scharnier}
3171590Srgrimes
3181590Srgrimes/* A data slice can't be used after it has been released.
31946203Sphk *
320227186Sed * This tests the case where the data slice tracks a dynptr (ptr2)
32146203Sphk * that is at a non-zero offset from the frame pointer (ptr1 is at fp,
32246203Sphk * ptr2 is at fp - 16).
32346203Sphk */
32446203SphkSEC("?raw_tp")
32546203Sphk__failure __msg("invalid mem access 'scalar'")
32646203Sphkint data_slice_use_after_release2(void *ctx)
32746203Sphk{
32846203Sphk	struct bpf_dynptr ptr1, ptr2;
32946203Sphk	struct sample *sample;
33046203Sphk
33146203Sphk	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);
33246203Sphk	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
33346203Sphk
33446203Sphk	sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));
33546203Sphk	if (!sample)
33646203Sphk		goto done;
33746203Sphk
338	sample->pid = 23;
339
340	bpf_ringbuf_submit_dynptr(&ptr2, 0);
341
342	/* this should fail */
343	sample->pid = 23;
344
345	bpf_ringbuf_submit_dynptr(&ptr1, 0);
346
347	return 0;
348
349done:
350	bpf_ringbuf_discard_dynptr(&ptr2, 0);
351	bpf_ringbuf_discard_dynptr(&ptr1, 0);
352	return 0;
353}
354
355/* A data slice must be first checked for NULL */
356SEC("?raw_tp")
357__failure __msg("invalid mem access 'mem_or_null'")
358int data_slice_missing_null_check1(void *ctx)
359{
360	struct bpf_dynptr ptr;
361	void *data;
362
363	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
364
365	data  = bpf_dynptr_data(&ptr, 0, 8);
366
367	/* missing if (!data) check */
368
369	/* this should fail */
370	*(__u8 *)data = 3;
371
372	bpf_ringbuf_submit_dynptr(&ptr, 0);
373	return 0;
374}
375
376/* A data slice can't be dereferenced if it wasn't checked for null */
377SEC("?raw_tp")
378__failure __msg("invalid mem access 'mem_or_null'")
379int data_slice_missing_null_check2(void *ctx)
380{
381	struct bpf_dynptr ptr;
382	__u64 *data1, *data2;
383
384	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
385
386	data1 = bpf_dynptr_data(&ptr, 0, 8);
387	data2 = bpf_dynptr_data(&ptr, 0, 8);
388	if (data1)
389		/* this should fail */
390		*data2 = 3;
391
392	bpf_ringbuf_discard_dynptr(&ptr, 0);
393	return 0;
394}
395
396/* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
397 * dynptr argument
398 */
399SEC("?raw_tp")
400__failure __msg("invalid indirect read from stack")
401int invalid_helper1(void *ctx)
402{
403	struct bpf_dynptr ptr;
404
405	get_map_val_dynptr(&ptr);
406
407	/* this should fail */
408	bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");
409
410	return 0;
411}
412
413/* A dynptr can't be passed into a helper function at a non-zero offset */
414SEC("?raw_tp")
415__failure __msg("cannot pass in dynptr at an offset=-8")
416int invalid_helper2(void *ctx)
417{
418	struct bpf_dynptr ptr;
419	char read_data[64];
420
421	get_map_val_dynptr(&ptr);
422
423	/* this should fail */
424	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);
425	return 0;
426}
427
428/* A bpf_dynptr is invalidated if it's been written into */
429SEC("?raw_tp")
430__failure __msg("Expected an initialized dynptr as arg #1")
431int invalid_write1(void *ctx)
432{
433	struct bpf_dynptr ptr;
434	void *data;
435	__u8 x = 0;
436
437	get_map_val_dynptr(&ptr);
438
439	memcpy(&ptr, &x, sizeof(x));
440
441	/* this should fail */
442	data = bpf_dynptr_data(&ptr, 0, 1);
443	__sink(data);
444
445	return 0;
446}
447
448/*
449 * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed
450 * offset
451 */
452SEC("?raw_tp")
453__failure __msg("cannot overwrite referenced dynptr")
454int invalid_write2(void *ctx)
455{
456	struct bpf_dynptr ptr;
457	char read_data[64];
458	__u8 x = 0;
459
460	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
461
462	memcpy((void *)&ptr + 8, &x, sizeof(x));
463
464	/* this should fail */
465	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
466
467	bpf_ringbuf_submit_dynptr(&ptr, 0);
468
469	return 0;
470}
471
472/*
473 * A bpf_dynptr can't be used as a dynptr if it has been written into at a
474 * non-const offset
475 */
476SEC("?raw_tp")
477__failure __msg("cannot overwrite referenced dynptr")
478int invalid_write3(void *ctx)
479{
480	struct bpf_dynptr ptr;
481	char stack_buf[16];
482	unsigned long len;
483	__u8 x = 0;
484
485	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
486
487	memcpy(stack_buf, &val, sizeof(val));
488	len = stack_buf[0] & 0xf;
489
490	memcpy((void *)&ptr + len, &x, sizeof(x));
491
492	/* this should fail */
493	bpf_ringbuf_submit_dynptr(&ptr, 0);
494
495	return 0;
496}
497
498static int invalid_write4_callback(__u32 index, void *data)
499{
500	*(__u32 *)data = 123;
501
502	return 0;
503}
504
505/* If the dynptr is written into in a callback function, it should
506 * be invalidated as a dynptr
507 */
508SEC("?raw_tp")
509__failure __msg("cannot overwrite referenced dynptr")
510int invalid_write4(void *ctx)
511{
512	struct bpf_dynptr ptr;
513
514	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
515
516	bpf_loop(10, invalid_write4_callback, &ptr, 0);
517
518	/* this should fail */
519	bpf_ringbuf_submit_dynptr(&ptr, 0);
520
521	return 0;
522}
523
524/* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
525struct bpf_dynptr global_dynptr;
526
527SEC("?raw_tp")
528__failure __msg("type=map_value expected=fp")
529int global(void *ctx)
530{
531	/* this should fail */
532	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);
533
534	bpf_ringbuf_discard_dynptr(&global_dynptr, 0);
535
536	return 0;
537}
538
539/* A direct read should fail */
540SEC("?raw_tp")
541__failure __msg("invalid read from stack")
542int invalid_read1(void *ctx)
543{
544	struct bpf_dynptr ptr;
545
546	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
547
548	/* this should fail */
549	val = *(int *)&ptr;
550
551	bpf_ringbuf_discard_dynptr(&ptr, 0);
552
553	return 0;
554}
555
556/* A direct read at an offset should fail */
557SEC("?raw_tp")
558__failure __msg("cannot pass in dynptr at an offset")
559int invalid_read2(void *ctx)
560{
561	struct bpf_dynptr ptr;
562	char read_data[64];
563
564	get_map_val_dynptr(&ptr);
565
566	/* this should fail */
567	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);
568
569	return 0;
570}
571
572/* A direct read at an offset into the lower stack slot should fail */
573SEC("?raw_tp")
574__failure __msg("invalid read from stack")
575int invalid_read3(void *ctx)
576{
577	struct bpf_dynptr ptr1, ptr2;
578
579	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);
580	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);
581
582	/* this should fail */
583	memcpy(&val, (void *)&ptr1 + 8, sizeof(val));
584
585	bpf_ringbuf_discard_dynptr(&ptr1, 0);
586	bpf_ringbuf_discard_dynptr(&ptr2, 0);
587
588	return 0;
589}
590
591static int invalid_read4_callback(__u32 index, void *data)
592{
593	/* this should fail */
594	val = *(__u32 *)data;
595
596	return 0;
597}
598
599/* A direct read within a callback function should fail */
600SEC("?raw_tp")
601__failure __msg("invalid read from stack")
602int invalid_read4(void *ctx)
603{
604	struct bpf_dynptr ptr;
605
606	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
607
608	bpf_loop(10, invalid_read4_callback, &ptr, 0);
609
610	bpf_ringbuf_submit_dynptr(&ptr, 0);
611
612	return 0;
613}
614
615/* Initializing a dynptr on an offset should fail */
616SEC("?raw_tp")
617__failure __msg("cannot pass in dynptr at an offset=0")
618int invalid_offset(void *ctx)
619{
620	struct bpf_dynptr ptr;
621
622	/* this should fail */
623	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);
624
625	bpf_ringbuf_discard_dynptr(&ptr, 0);
626
627	return 0;
628}
629
630/* Can't release a dynptr twice */
631SEC("?raw_tp")
632__failure __msg("arg 1 is an unacquired reference")
633int release_twice(void *ctx)
634{
635	struct bpf_dynptr ptr;
636
637	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
638
639	bpf_ringbuf_discard_dynptr(&ptr, 0);
640
641	/* this second release should fail */
642	bpf_ringbuf_discard_dynptr(&ptr, 0);
643
644	return 0;
645}
646
647static int release_twice_callback_fn(__u32 index, void *data)
648{
649	/* this should fail */
650	bpf_ringbuf_discard_dynptr(data, 0);
651
652	return 0;
653}
654
655/* Test that releasing a dynptr twice, where one of the releases happens
656 * within a callback function, fails
657 */
658SEC("?raw_tp")
659__failure __msg("arg 1 is an unacquired reference")
660int release_twice_callback(void *ctx)
661{
662	struct bpf_dynptr ptr;
663
664	bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);
665
666	bpf_ringbuf_discard_dynptr(&ptr, 0);
667
668	bpf_loop(10, release_twice_callback_fn, &ptr, 0);
669
670	return 0;
671}
672
673/* Reject unsupported local mem types for dynptr_from_mem API */
674SEC("?raw_tp")
675__failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data")
676int dynptr_from_mem_invalid_api(void *ctx)
677{
678	struct bpf_dynptr ptr;
679	int x = 0;
680
681	/* this should fail */
682	bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);
683
684	return 0;
685}
686
687SEC("?tc")
688__failure __msg("cannot overwrite referenced dynptr") __log_level(2)
689int dynptr_pruning_overwrite(struct __sk_buff *ctx)
690{
691	asm volatile (
692		"r9 = 0xeB9F;				\
693		 r6 = %[ringbuf] ll;			\
694		 r1 = r6;				\
695		 r2 = 8;				\
696		 r3 = 0;				\
697		 r4 = r10;				\
698		 r4 += -16;				\
699		 call %[bpf_ringbuf_reserve_dynptr];	\
700		 if r0 == 0 goto pjmp1;			\
701		 goto pjmp2;				\
702	pjmp1:						\
703		 *(u64 *)(r10 - 16) = r9;		\
704	pjmp2:						\
705		 r1 = r10;				\
706		 r1 += -16;				\
707		 r2 = 0;				\
708		 call %[bpf_ringbuf_discard_dynptr];	"
709		:
710		: __imm(bpf_ringbuf_reserve_dynptr),
711		  __imm(bpf_ringbuf_discard_dynptr),
712		  __imm_addr(ringbuf)
713		: __clobber_all
714	);
715	return 0;
716}
717
718SEC("?tc")
719__success __msg("12: safe") __log_level(2)
720int dynptr_pruning_stacksafe(struct __sk_buff *ctx)
721{
722	asm volatile (
723		"r9 = 0xeB9F;				\
724		 r6 = %[ringbuf] ll;			\
725		 r1 = r6;				\
726		 r2 = 8;				\
727		 r3 = 0;				\
728		 r4 = r10;				\
729		 r4 += -16;				\
730		 call %[bpf_ringbuf_reserve_dynptr];	\
731		 if r0 == 0 goto stjmp1;		\
732		 goto stjmp2;				\
733	stjmp1:						\
734		 r9 = r9;				\
735	stjmp2:						\
736		 r1 = r10;				\
737		 r1 += -16;				\
738		 r2 = 0;				\
739		 call %[bpf_ringbuf_discard_dynptr];	"
740		:
741		: __imm(bpf_ringbuf_reserve_dynptr),
742		  __imm(bpf_ringbuf_discard_dynptr),
743		  __imm_addr(ringbuf)
744		: __clobber_all
745	);
746	return 0;
747}
748
749SEC("?tc")
750__failure __msg("cannot overwrite referenced dynptr") __log_level(2)
751int dynptr_pruning_type_confusion(struct __sk_buff *ctx)
752{
753	asm volatile (
754		"r6 = %[array_map4] ll;			\
755		 r7 = %[ringbuf] ll;			\
756		 r1 = r6;				\
757		 r2 = r10;				\
758		 r2 += -8;				\
759		 r9 = 0;				\
760		 *(u64 *)(r2 + 0) = r9;			\
761		 r3 = r10;				\
762		 r3 += -24;				\
763		 r9 = 0xeB9FeB9F;			\
764		 *(u64 *)(r10 - 16) = r9;		\
765		 *(u64 *)(r10 - 24) = r9;		\
766		 r9 = 0;				\
767		 r4 = 0;				\
768		 r8 = r2;				\
769		 call %[bpf_map_update_elem];		\
770		 r1 = r6;				\
771		 r2 = r8;				\
772		 call %[bpf_map_lookup_elem];		\
773		 if r0 != 0 goto tjmp1;			\
774		 exit;					\
775	tjmp1:						\
776		 r8 = r0;				\
777		 r1 = r7;				\
778		 r2 = 8;				\
779		 r3 = 0;				\
780		 r4 = r10;				\
781		 r4 += -16;				\
782		 r0 = *(u64 *)(r0 + 0);			\
783		 call %[bpf_ringbuf_reserve_dynptr];	\
784		 if r0 == 0 goto tjmp2;			\
785		 r8 = r8;				\
786		 r8 = r8;				\
787		 r8 = r8;				\
788		 r8 = r8;				\
789		 r8 = r8;				\
790		 r8 = r8;				\
791		 r8 = r8;				\
792		 goto tjmp3;				\
793	tjmp2:						\
794		 *(u64 *)(r10 - 8) = r9;		\
795		 *(u64 *)(r10 - 16) = r9;		\
796		 r1 = r8;				\
797		 r1 += 8;				\
798		 r2 = 0;				\
799		 r3 = 0;				\
800		 r4 = r10;				\
801		 r4 += -16;				\
802		 call %[bpf_dynptr_from_mem];		\
803	tjmp3:						\
804		 r1 = r10;				\
805		 r1 += -16;				\
806		 r2 = 0;				\
807		 call %[bpf_ringbuf_discard_dynptr];	"
808		:
809		: __imm(bpf_map_update_elem),
810		  __imm(bpf_map_lookup_elem),
811		  __imm(bpf_ringbuf_reserve_dynptr),
812		  __imm(bpf_dynptr_from_mem),
813		  __imm(bpf_ringbuf_discard_dynptr),
814		  __imm_addr(array_map4),
815		  __imm_addr(ringbuf)
816		: __clobber_all
817	);
818	return 0;
819}
820
821SEC("?tc")
822__failure __msg("dynptr has to be at a constant offset") __log_level(2)
823int dynptr_var_off_overwrite(struct __sk_buff *ctx)
824{
825	asm volatile (
826		"r9 = 16;				\
827		 *(u32 *)(r10 - 4) = r9;		\
828		 r8 = *(u32 *)(r10 - 4);		\
829		 if r8 >= 0 goto vjmp1;			\
830		 r0 = 1;				\
831		 exit;					\
832	vjmp1:						\
833		 if r8 <= 16 goto vjmp2;		\
834		 r0 = 1;				\
835		 exit;					\
836	vjmp2:						\
837		 r8 &= 16;				\
838		 r1 = %[ringbuf] ll;			\
839		 r2 = 8;				\
840		 r3 = 0;				\
841		 r4 = r10;				\
842		 r4 += -32;				\
843		 r4 += r8;				\
844		 call %[bpf_ringbuf_reserve_dynptr];	\
845		 r9 = 0xeB9F;				\
846		 *(u64 *)(r10 - 16) = r9;		\
847		 r1 = r10;				\
848		 r1 += -32;				\
849		 r1 += r8;				\
850		 r2 = 0;				\
851		 call %[bpf_ringbuf_discard_dynptr];	"
852		:
853		: __imm(bpf_ringbuf_reserve_dynptr),
854		  __imm(bpf_ringbuf_discard_dynptr),
855		  __imm_addr(ringbuf)
856		: __clobber_all
857	);
858	return 0;
859}
860
861SEC("?tc")
862__failure __msg("cannot overwrite referenced dynptr") __log_level(2)
863int dynptr_partial_slot_invalidate(struct __sk_buff *ctx)
864{
865	asm volatile (
866		"r6 = %[ringbuf] ll;			\
867		 r7 = %[array_map4] ll;			\
868		 r1 = r7;				\
869		 r2 = r10;				\
870		 r2 += -8;				\
871		 r9 = 0;				\
872		 *(u64 *)(r2 + 0) = r9;			\
873		 r3 = r2;				\
874		 r4 = 0;				\
875		 r8 = r2;				\
876		 call %[bpf_map_update_elem];		\
877		 r1 = r7;				\
878		 r2 = r8;				\
879		 call %[bpf_map_lookup_elem];		\
880		 if r0 != 0 goto sjmp1;			\
881		 exit;					\
882	sjmp1:						\
883		 r7 = r0;				\
884		 r1 = r6;				\
885		 r2 = 8;				\
886		 r3 = 0;				\
887		 r4 = r10;				\
888		 r4 += -24;				\
889		 call %[bpf_ringbuf_reserve_dynptr];	\
890		 *(u64 *)(r10 - 16) = r9;		\
891		 r1 = r7;				\
892		 r2 = 8;				\
893		 r3 = 0;				\
894		 r4 = r10;				\
895		 r4 += -16;				\
896		 call %[bpf_dynptr_from_mem];		\
897		 r1 = r10;				\
898		 r1 += -512;				\
899		 r2 = 488;				\
900		 r3 = r10;				\
901		 r3 += -24;				\
902		 r4 = 0;				\
903		 r5 = 0;				\
904		 call %[bpf_dynptr_read];		\
905		 r8 = 1;				\
906		 if r0 != 0 goto sjmp2;			\
907		 r8 = 0;				\
908	sjmp2:						\
909		 r1 = r10;				\
910		 r1 += -24;				\
911		 r2 = 0;				\
912		 call %[bpf_ringbuf_discard_dynptr];	"
913		:
914		: __imm(bpf_map_update_elem),
915		  __imm(bpf_map_lookup_elem),
916		  __imm(bpf_ringbuf_reserve_dynptr),
917		  __imm(bpf_ringbuf_discard_dynptr),
918		  __imm(bpf_dynptr_from_mem),
919		  __imm(bpf_dynptr_read),
920		  __imm_addr(ringbuf),
921		  __imm_addr(array_map4)
922		: __clobber_all
923	);
924	return 0;
925}
926
927/* Test that it is allowed to overwrite unreferenced dynptr. */
928SEC("?raw_tp")
929__success
930int dynptr_overwrite_unref(void *ctx)
931{
932	struct bpf_dynptr ptr;
933
934	if (get_map_val_dynptr(&ptr))
935		return 0;
936	if (get_map_val_dynptr(&ptr))
937		return 0;
938	if (get_map_val_dynptr(&ptr))
939		return 0;
940
941	return 0;
942}
943
944/* Test that slices are invalidated on reinitializing a dynptr. */
945SEC("?raw_tp")
946__failure __msg("invalid mem access 'scalar'")
947int dynptr_invalidate_slice_reinit(void *ctx)
948{
949	struct bpf_dynptr ptr;
950	__u8 *p;
951
952	if (get_map_val_dynptr(&ptr))
953		return 0;
954	p = bpf_dynptr_data(&ptr, 0, 1);
955	if (!p)
956		return 0;
957	if (get_map_val_dynptr(&ptr))
958		return 0;
959	/* this should fail */
960	return *p;
961}
962
963/* Invalidation of dynptr slices on destruction of dynptr should not miss
964 * mem_or_null pointers.
965 */
966SEC("?raw_tp")
967__failure __msg("R1 type=scalar expected=percpu_ptr_")
968int dynptr_invalidate_slice_or_null(void *ctx)
969{
970	struct bpf_dynptr ptr;
971	__u8 *p;
972
973	if (get_map_val_dynptr(&ptr))
974		return 0;
975
976	p = bpf_dynptr_data(&ptr, 0, 1);
977	*(__u8 *)&ptr = 0;
978	/* this should fail */
979	bpf_this_cpu_ptr(p);
980	return 0;
981}
982
983/* Destruction of dynptr should also any slices obtained from it */
984SEC("?raw_tp")
985__failure __msg("R7 invalid mem access 'scalar'")
986int dynptr_invalidate_slice_failure(void *ctx)
987{
988	struct bpf_dynptr ptr1;
989	struct bpf_dynptr ptr2;
990	__u8 *p1, *p2;
991
992	if (get_map_val_dynptr(&ptr1))
993		return 0;
994	if (get_map_val_dynptr(&ptr2))
995		return 0;
996
997	p1 = bpf_dynptr_data(&ptr1, 0, 1);
998	if (!p1)
999		return 0;
1000	p2 = bpf_dynptr_data(&ptr2, 0, 1);
1001	if (!p2)
1002		return 0;
1003
1004	*(__u8 *)&ptr1 = 0;
1005	/* this should fail */
1006	return *p1;
1007}
1008
1009/* Invalidation of slices should be scoped and should not prevent dereferencing
1010 * slices of another dynptr after destroying unrelated dynptr
1011 */
1012SEC("?raw_tp")
1013__success
1014int dynptr_invalidate_slice_success(void *ctx)
1015{
1016	struct bpf_dynptr ptr1;
1017	struct bpf_dynptr ptr2;
1018	__u8 *p1, *p2;
1019
1020	if (get_map_val_dynptr(&ptr1))
1021		return 1;
1022	if (get_map_val_dynptr(&ptr2))
1023		return 1;
1024
1025	p1 = bpf_dynptr_data(&ptr1, 0, 1);
1026	if (!p1)
1027		return 1;
1028	p2 = bpf_dynptr_data(&ptr2, 0, 1);
1029	if (!p2)
1030		return 1;
1031
1032	*(__u8 *)&ptr1 = 0;
1033	return *p2;
1034}
1035
1036/* Overwriting referenced dynptr should be rejected */
1037SEC("?raw_tp")
1038__failure __msg("cannot overwrite referenced dynptr")
1039int dynptr_overwrite_ref(void *ctx)
1040{
1041	struct bpf_dynptr ptr;
1042
1043	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
1044	/* this should fail */
1045	if (get_map_val_dynptr(&ptr))
1046		bpf_ringbuf_discard_dynptr(&ptr, 0);
1047	return 0;
1048}
1049
1050/* Reject writes to dynptr slot from bpf_dynptr_read */
1051SEC("?raw_tp")
1052__failure __msg("potential write to dynptr at off=-16")
1053int dynptr_read_into_slot(void *ctx)
1054{
1055	union {
1056		struct {
1057			char _pad[48];
1058			struct bpf_dynptr ptr;
1059		};
1060		char buf[64];
1061	} data;
1062
1063	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &data.ptr);
1064	/* this should fail */
1065	bpf_dynptr_read(data.buf, sizeof(data.buf), &data.ptr, 0, 0);
1066
1067	return 0;
1068}
1069
1070/* bpf_dynptr_slice()s are read-only and cannot be written to */
1071SEC("?tc")
1072__failure __msg("R0 cannot write into rdonly_mem")
1073int skb_invalid_slice_write(struct __sk_buff *skb)
1074{
1075	struct bpf_dynptr ptr;
1076	struct ethhdr *hdr;
1077	char buffer[sizeof(*hdr)] = {};
1078
1079	bpf_dynptr_from_skb(skb, 0, &ptr);
1080
1081	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1082	if (!hdr)
1083		return SK_DROP;
1084
1085	/* this should fail */
1086	hdr->h_proto = 1;
1087
1088	return SK_PASS;
1089}
1090
1091/* The read-only data slice is invalidated whenever a helper changes packet data */
1092SEC("?tc")
1093__failure __msg("invalid mem access 'scalar'")
1094int skb_invalid_data_slice1(struct __sk_buff *skb)
1095{
1096	struct bpf_dynptr ptr;
1097	struct ethhdr *hdr;
1098	char buffer[sizeof(*hdr)] = {};
1099
1100	bpf_dynptr_from_skb(skb, 0, &ptr);
1101
1102	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1103	if (!hdr)
1104		return SK_DROP;
1105
1106	val = hdr->h_proto;
1107
1108	if (bpf_skb_pull_data(skb, skb->len))
1109		return SK_DROP;
1110
1111	/* this should fail */
1112	val = hdr->h_proto;
1113
1114	return SK_PASS;
1115}
1116
1117/* The read-write data slice is invalidated whenever a helper changes packet data */
1118SEC("?tc")
1119__failure __msg("invalid mem access 'scalar'")
1120int skb_invalid_data_slice2(struct __sk_buff *skb)
1121{
1122	struct bpf_dynptr ptr;
1123	struct ethhdr *hdr;
1124	char buffer[sizeof(*hdr)] = {};
1125
1126	bpf_dynptr_from_skb(skb, 0, &ptr);
1127
1128	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1129	if (!hdr)
1130		return SK_DROP;
1131
1132	hdr->h_proto = 123;
1133
1134	if (bpf_skb_pull_data(skb, skb->len))
1135		return SK_DROP;
1136
1137	/* this should fail */
1138	hdr->h_proto = 1;
1139
1140	return SK_PASS;
1141}
1142
1143/* The read-only data slice is invalidated whenever bpf_dynptr_write() is called */
1144SEC("?tc")
1145__failure __msg("invalid mem access 'scalar'")
1146int skb_invalid_data_slice3(struct __sk_buff *skb)
1147{
1148	char write_data[64] = "hello there, world!!";
1149	struct bpf_dynptr ptr;
1150	struct ethhdr *hdr;
1151	char buffer[sizeof(*hdr)] = {};
1152
1153	bpf_dynptr_from_skb(skb, 0, &ptr);
1154
1155	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1156	if (!hdr)
1157		return SK_DROP;
1158
1159	val = hdr->h_proto;
1160
1161	bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);
1162
1163	/* this should fail */
1164	val = hdr->h_proto;
1165
1166	return SK_PASS;
1167}
1168
1169/* The read-write data slice is invalidated whenever bpf_dynptr_write() is called */
1170SEC("?tc")
1171__failure __msg("invalid mem access 'scalar'")
1172int skb_invalid_data_slice4(struct __sk_buff *skb)
1173{
1174	char write_data[64] = "hello there, world!!";
1175	struct bpf_dynptr ptr;
1176	struct ethhdr *hdr;
1177	char buffer[sizeof(*hdr)] = {};
1178
1179	bpf_dynptr_from_skb(skb, 0, &ptr);
1180	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1181	if (!hdr)
1182		return SK_DROP;
1183
1184	hdr->h_proto = 123;
1185
1186	bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);
1187
1188	/* this should fail */
1189	hdr->h_proto = 1;
1190
1191	return SK_PASS;
1192}
1193
1194/* The read-only data slice is invalidated whenever a helper changes packet data */
1195SEC("?xdp")
1196__failure __msg("invalid mem access 'scalar'")
1197int xdp_invalid_data_slice1(struct xdp_md *xdp)
1198{
1199	struct bpf_dynptr ptr;
1200	struct ethhdr *hdr;
1201	char buffer[sizeof(*hdr)] = {};
1202
1203	bpf_dynptr_from_xdp(xdp, 0, &ptr);
1204	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1205	if (!hdr)
1206		return SK_DROP;
1207
1208	val = hdr->h_proto;
1209
1210	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1211		return XDP_DROP;
1212
1213	/* this should fail */
1214	val = hdr->h_proto;
1215
1216	return XDP_PASS;
1217}
1218
1219/* The read-write data slice is invalidated whenever a helper changes packet data */
1220SEC("?xdp")
1221__failure __msg("invalid mem access 'scalar'")
1222int xdp_invalid_data_slice2(struct xdp_md *xdp)
1223{
1224	struct bpf_dynptr ptr;
1225	struct ethhdr *hdr;
1226	char buffer[sizeof(*hdr)] = {};
1227
1228	bpf_dynptr_from_xdp(xdp, 0, &ptr);
1229	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1230	if (!hdr)
1231		return SK_DROP;
1232
1233	hdr->h_proto = 9;
1234
1235	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1236		return XDP_DROP;
1237
1238	/* this should fail */
1239	hdr->h_proto = 1;
1240
1241	return XDP_PASS;
1242}
1243
1244/* Only supported prog type can create skb-type dynptrs */
1245SEC("?raw_tp")
1246__failure __msg("calling kernel function bpf_dynptr_from_skb is not allowed")
1247int skb_invalid_ctx(void *ctx)
1248{
1249	struct bpf_dynptr ptr;
1250
1251	/* this should fail */
1252	bpf_dynptr_from_skb(ctx, 0, &ptr);
1253
1254	return 0;
1255}
1256
1257/* Reject writes to dynptr slot for uninit arg */
1258SEC("?raw_tp")
1259__failure __msg("potential write to dynptr at off=-16")
1260int uninit_write_into_slot(void *ctx)
1261{
1262	struct {
1263		char buf[64];
1264		struct bpf_dynptr ptr;
1265	} data;
1266
1267	bpf_ringbuf_reserve_dynptr(&ringbuf, 80, 0, &data.ptr);
1268	/* this should fail */
1269	bpf_get_current_comm(data.buf, 80);
1270
1271	return 0;
1272}
1273
1274/* Only supported prog type can create xdp-type dynptrs */
1275SEC("?raw_tp")
1276__failure __msg("calling kernel function bpf_dynptr_from_xdp is not allowed")
1277int xdp_invalid_ctx(void *ctx)
1278{
1279	struct bpf_dynptr ptr;
1280
1281	/* this should fail */
1282	bpf_dynptr_from_xdp(ctx, 0, &ptr);
1283
1284	return 0;
1285}
1286
1287__u32 hdr_size = sizeof(struct ethhdr);
1288/* Can't pass in variable-sized len to bpf_dynptr_slice */
1289SEC("?tc")
1290__failure __msg("unbounded memory access")
1291int dynptr_slice_var_len1(struct __sk_buff *skb)
1292{
1293	struct bpf_dynptr ptr;
1294	struct ethhdr *hdr;
1295	char buffer[sizeof(*hdr)] = {};
1296
1297	bpf_dynptr_from_skb(skb, 0, &ptr);
1298
1299	/* this should fail */
1300	hdr = bpf_dynptr_slice(&ptr, 0, buffer, hdr_size);
1301	if (!hdr)
1302		return SK_DROP;
1303
1304	return SK_PASS;
1305}
1306
1307/* Can't pass in variable-sized len to bpf_dynptr_slice */
1308SEC("?tc")
1309__failure __msg("must be a known constant")
1310int dynptr_slice_var_len2(struct __sk_buff *skb)
1311{
1312	char buffer[sizeof(struct ethhdr)] = {};
1313	struct bpf_dynptr ptr;
1314	struct ethhdr *hdr;
1315
1316	bpf_dynptr_from_skb(skb, 0, &ptr);
1317
1318	if (hdr_size <= sizeof(buffer)) {
1319		/* this should fail */
1320		hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, hdr_size);
1321		if (!hdr)
1322			return SK_DROP;
1323		hdr->h_proto = 12;
1324	}
1325
1326	return SK_PASS;
1327}
1328
1329static int callback(__u32 index, void *data)
1330{
1331        *(__u32 *)data = 123;
1332
1333        return 0;
1334}
1335
1336/* If the dynptr is written into in a callback function, its data
1337 * slices should be invalidated as well.
1338 */
1339SEC("?raw_tp")
1340__failure __msg("invalid mem access 'scalar'")
1341int invalid_data_slices(void *ctx)
1342{
1343	struct bpf_dynptr ptr;
1344	__u32 *slice;
1345
1346	if (get_map_val_dynptr(&ptr))
1347		return 0;
1348
1349	slice = bpf_dynptr_data(&ptr, 0, sizeof(__u32));
1350	if (!slice)
1351		return 0;
1352
1353	bpf_loop(10, callback, &ptr, 0);
1354
1355	/* this should fail */
1356	*slice = 1;
1357
1358	return 0;
1359}
1360
1361/* Program types that don't allow writes to packet data should fail if
1362 * bpf_dynptr_slice_rdwr is called
1363 */
1364SEC("cgroup_skb/ingress")
1365__failure __msg("the prog does not allow writes to packet data")
1366int invalid_slice_rdwr_rdonly(struct __sk_buff *skb)
1367{
1368	char buffer[sizeof(struct ethhdr)] = {};
1369	struct bpf_dynptr ptr;
1370	struct ethhdr *hdr;
1371
1372	bpf_dynptr_from_skb(skb, 0, &ptr);
1373
1374	/* this should fail since cgroup_skb doesn't allow
1375	 * changing packet data
1376	 */
1377	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1378	__sink(hdr);
1379
1380	return 0;
1381}
1382
1383/* bpf_dynptr_adjust can only be called on initialized dynptrs */
1384SEC("?raw_tp")
1385__failure __msg("Expected an initialized dynptr as arg #1")
1386int dynptr_adjust_invalid(void *ctx)
1387{
1388	struct bpf_dynptr ptr = {};
1389
1390	/* this should fail */
1391	bpf_dynptr_adjust(&ptr, 1, 2);
1392
1393	return 0;
1394}
1395
1396/* bpf_dynptr_is_null can only be called on initialized dynptrs */
1397SEC("?raw_tp")
1398__failure __msg("Expected an initialized dynptr as arg #1")
1399int dynptr_is_null_invalid(void *ctx)
1400{
1401	struct bpf_dynptr ptr = {};
1402
1403	/* this should fail */
1404	bpf_dynptr_is_null(&ptr);
1405
1406	return 0;
1407}
1408
1409/* bpf_dynptr_is_rdonly can only be called on initialized dynptrs */
1410SEC("?raw_tp")
1411__failure __msg("Expected an initialized dynptr as arg #1")
1412int dynptr_is_rdonly_invalid(void *ctx)
1413{
1414	struct bpf_dynptr ptr = {};
1415
1416	/* this should fail */
1417	bpf_dynptr_is_rdonly(&ptr);
1418
1419	return 0;
1420}
1421
1422/* bpf_dynptr_size can only be called on initialized dynptrs */
1423SEC("?raw_tp")
1424__failure __msg("Expected an initialized dynptr as arg #1")
1425int dynptr_size_invalid(void *ctx)
1426{
1427	struct bpf_dynptr ptr = {};
1428
1429	/* this should fail */
1430	bpf_dynptr_size(&ptr);
1431
1432	return 0;
1433}
1434
1435/* Only initialized dynptrs can be cloned */
1436SEC("?raw_tp")
1437__failure __msg("Expected an initialized dynptr as arg #1")
1438int clone_invalid1(void *ctx)
1439{
1440	struct bpf_dynptr ptr1 = {};
1441	struct bpf_dynptr ptr2;
1442
1443	/* this should fail */
1444	bpf_dynptr_clone(&ptr1, &ptr2);
1445
1446	return 0;
1447}
1448
1449/* Can't overwrite an existing dynptr when cloning */
1450SEC("?xdp")
1451__failure __msg("cannot overwrite referenced dynptr")
1452int clone_invalid2(struct xdp_md *xdp)
1453{
1454	struct bpf_dynptr ptr1;
1455	struct bpf_dynptr clone;
1456
1457	bpf_dynptr_from_xdp(xdp, 0, &ptr1);
1458
1459	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &clone);
1460
1461	/* this should fail */
1462	bpf_dynptr_clone(&ptr1, &clone);
1463
1464	bpf_ringbuf_submit_dynptr(&clone, 0);
1465
1466	return 0;
1467}
1468
1469/* Invalidating a dynptr should invalidate its clones */
1470SEC("?raw_tp")
1471__failure __msg("Expected an initialized dynptr as arg #3")
1472int clone_invalidate1(void *ctx)
1473{
1474	struct bpf_dynptr clone;
1475	struct bpf_dynptr ptr;
1476	char read_data[64];
1477
1478	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1479
1480	bpf_dynptr_clone(&ptr, &clone);
1481
1482	bpf_ringbuf_submit_dynptr(&ptr, 0);
1483
1484	/* this should fail */
1485	bpf_dynptr_read(read_data, sizeof(read_data), &clone, 0, 0);
1486
1487	return 0;
1488}
1489
1490/* Invalidating a dynptr should invalidate its parent */
1491SEC("?raw_tp")
1492__failure __msg("Expected an initialized dynptr as arg #3")
1493int clone_invalidate2(void *ctx)
1494{
1495	struct bpf_dynptr ptr;
1496	struct bpf_dynptr clone;
1497	char read_data[64];
1498
1499	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1500
1501	bpf_dynptr_clone(&ptr, &clone);
1502
1503	bpf_ringbuf_submit_dynptr(&clone, 0);
1504
1505	/* this should fail */
1506	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
1507
1508	return 0;
1509}
1510
1511/* Invalidating a dynptr should invalidate its siblings */
1512SEC("?raw_tp")
1513__failure __msg("Expected an initialized dynptr as arg #3")
1514int clone_invalidate3(void *ctx)
1515{
1516	struct bpf_dynptr ptr;
1517	struct bpf_dynptr clone1;
1518	struct bpf_dynptr clone2;
1519	char read_data[64];
1520
1521	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1522
1523	bpf_dynptr_clone(&ptr, &clone1);
1524
1525	bpf_dynptr_clone(&ptr, &clone2);
1526
1527	bpf_ringbuf_submit_dynptr(&clone2, 0);
1528
1529	/* this should fail */
1530	bpf_dynptr_read(read_data, sizeof(read_data), &clone1, 0, 0);
1531
1532	return 0;
1533}
1534
1535/* Invalidating a dynptr should invalidate any data slices
1536 * of its clones
1537 */
1538SEC("?raw_tp")
1539__failure __msg("invalid mem access 'scalar'")
1540int clone_invalidate4(void *ctx)
1541{
1542	struct bpf_dynptr ptr;
1543	struct bpf_dynptr clone;
1544	int *data;
1545
1546	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1547
1548	bpf_dynptr_clone(&ptr, &clone);
1549	data = bpf_dynptr_data(&clone, 0, sizeof(val));
1550	if (!data)
1551		return 0;
1552
1553	bpf_ringbuf_submit_dynptr(&ptr, 0);
1554
1555	/* this should fail */
1556	*data = 123;
1557
1558	return 0;
1559}
1560
1561/* Invalidating a dynptr should invalidate any data slices
1562 * of its parent
1563 */
1564SEC("?raw_tp")
1565__failure __msg("invalid mem access 'scalar'")
1566int clone_invalidate5(void *ctx)
1567{
1568	struct bpf_dynptr ptr;
1569	struct bpf_dynptr clone;
1570	int *data;
1571
1572	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1573	data = bpf_dynptr_data(&ptr, 0, sizeof(val));
1574	if (!data)
1575		return 0;
1576
1577	bpf_dynptr_clone(&ptr, &clone);
1578
1579	bpf_ringbuf_submit_dynptr(&clone, 0);
1580
1581	/* this should fail */
1582	*data = 123;
1583
1584	return 0;
1585}
1586
1587/* Invalidating a dynptr should invalidate any data slices
1588 * of its sibling
1589 */
1590SEC("?raw_tp")
1591__failure __msg("invalid mem access 'scalar'")
1592int clone_invalidate6(void *ctx)
1593{
1594	struct bpf_dynptr ptr;
1595	struct bpf_dynptr clone1;
1596	struct bpf_dynptr clone2;
1597	int *data;
1598
1599	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1600
1601	bpf_dynptr_clone(&ptr, &clone1);
1602
1603	bpf_dynptr_clone(&ptr, &clone2);
1604
1605	data = bpf_dynptr_data(&clone1, 0, sizeof(val));
1606	if (!data)
1607		return 0;
1608
1609	bpf_ringbuf_submit_dynptr(&clone2, 0);
1610
1611	/* this should fail */
1612	*data = 123;
1613
1614	return 0;
1615}
1616
1617/* A skb clone's data slices should be invalid anytime packet data changes */
1618SEC("?tc")
1619__failure __msg("invalid mem access 'scalar'")
1620int clone_skb_packet_data(struct __sk_buff *skb)
1621{
1622	char buffer[sizeof(__u32)] = {};
1623	struct bpf_dynptr clone;
1624	struct bpf_dynptr ptr;
1625	__u32 *data;
1626
1627	bpf_dynptr_from_skb(skb, 0, &ptr);
1628
1629	bpf_dynptr_clone(&ptr, &clone);
1630	data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));
1631	if (!data)
1632		return XDP_DROP;
1633
1634	if (bpf_skb_pull_data(skb, skb->len))
1635		return SK_DROP;
1636
1637	/* this should fail */
1638	*data = 123;
1639
1640	return 0;
1641}
1642
1643/* A xdp clone's data slices should be invalid anytime packet data changes */
1644SEC("?xdp")
1645__failure __msg("invalid mem access 'scalar'")
1646int clone_xdp_packet_data(struct xdp_md *xdp)
1647{
1648	char buffer[sizeof(__u32)] = {};
1649	struct bpf_dynptr clone;
1650	struct bpf_dynptr ptr;
1651	struct ethhdr *hdr;
1652	__u32 *data;
1653
1654	bpf_dynptr_from_xdp(xdp, 0, &ptr);
1655
1656	bpf_dynptr_clone(&ptr, &clone);
1657	data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));
1658	if (!data)
1659		return XDP_DROP;
1660
1661	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1662		return XDP_DROP;
1663
1664	/* this should fail */
1665	*data = 123;
1666
1667	return 0;
1668}
1669
1670/* Buffers that are provided must be sufficiently long */
1671SEC("?cgroup_skb/egress")
1672__failure __msg("memory, len pair leads to invalid memory access")
1673int test_dynptr_skb_small_buff(struct __sk_buff *skb)
1674{
1675	struct bpf_dynptr ptr;
1676	char buffer[8] = {};
1677	__u64 *data;
1678
1679	if (bpf_dynptr_from_skb(skb, 0, &ptr)) {
1680		err = 1;
1681		return 1;
1682	}
1683
1684	/* This may return NULL. SKB may require a buffer */
1685	data = bpf_dynptr_slice(&ptr, 0, buffer, 9);
1686
1687	return !!data;
1688}
1689