10cf7052aSJoanne Koong // SPDX-License-Identifier: GPL-2.0
20cf7052aSJoanne Koong /* Copyright (c) 2022 Facebook */
30cf7052aSJoanne Koong 
40cf7052aSJoanne Koong #include <errno.h>
50cf7052aSJoanne Koong #include <string.h>
6*12852f8eSYonghong Song #include <stdbool.h>
70cf7052aSJoanne Koong #include <linux/bpf.h>
80cf7052aSJoanne Koong #include <bpf/bpf_helpers.h>
9cfa7b011SJoanne Koong #include <linux/if_ether.h>
100cf7052aSJoanne Koong #include "bpf_misc.h"
11cfa7b011SJoanne Koong #include "bpf_kfuncs.h"
120cf7052aSJoanne Koong 
130cf7052aSJoanne Koong char _license[] SEC("license") = "GPL";
140cf7052aSJoanne Koong 
150cf7052aSJoanne Koong struct test_info {
160cf7052aSJoanne Koong 	int x;
170cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
180cf7052aSJoanne Koong };
190cf7052aSJoanne Koong 
200cf7052aSJoanne Koong struct {
210cf7052aSJoanne Koong 	__uint(type, BPF_MAP_TYPE_ARRAY);
220cf7052aSJoanne Koong 	__uint(max_entries, 1);
230cf7052aSJoanne Koong 	__type(key, __u32);
240cf7052aSJoanne Koong 	__type(value, struct bpf_dynptr);
250cf7052aSJoanne Koong } array_map1 SEC(".maps");
260cf7052aSJoanne Koong 
270cf7052aSJoanne Koong struct {
280cf7052aSJoanne Koong 	__uint(type, BPF_MAP_TYPE_ARRAY);
290cf7052aSJoanne Koong 	__uint(max_entries, 1);
300cf7052aSJoanne Koong 	__type(key, __u32);
310cf7052aSJoanne Koong 	__type(value, struct test_info);
320cf7052aSJoanne Koong } array_map2 SEC(".maps");
330cf7052aSJoanne Koong 
340cf7052aSJoanne Koong struct {
350cf7052aSJoanne Koong 	__uint(type, BPF_MAP_TYPE_ARRAY);
360cf7052aSJoanne Koong 	__uint(max_entries, 1);
370cf7052aSJoanne Koong 	__type(key, __u32);
380cf7052aSJoanne Koong 	__type(value, __u32);
390cf7052aSJoanne Koong } array_map3 SEC(".maps");
400cf7052aSJoanne Koong 
41f4d24edfSKumar Kartikeya Dwivedi struct {
42f4d24edfSKumar Kartikeya Dwivedi 	__uint(type, BPF_MAP_TYPE_ARRAY);
43f4d24edfSKumar Kartikeya Dwivedi 	__uint(max_entries, 1);
44f4d24edfSKumar Kartikeya Dwivedi 	__type(key, __u32);
45f4d24edfSKumar Kartikeya Dwivedi 	__type(value, __u64);
46f4d24edfSKumar Kartikeya Dwivedi } array_map4 SEC(".maps");
47f4d24edfSKumar Kartikeya Dwivedi 
480cf7052aSJoanne Koong struct sample {
490cf7052aSJoanne Koong 	int pid;
500cf7052aSJoanne Koong 	long value;
510cf7052aSJoanne Koong 	char comm[16];
520cf7052aSJoanne Koong };
530cf7052aSJoanne Koong 
540cf7052aSJoanne Koong struct {
550cf7052aSJoanne Koong 	__uint(type, BPF_MAP_TYPE_RINGBUF);
5626c386ecSAndrii Nakryiko 	__uint(max_entries, 4096);
570cf7052aSJoanne Koong } ringbuf SEC(".maps");
580cf7052aSJoanne Koong 
590cf7052aSJoanne Koong int err, val;
600cf7052aSJoanne Koong 
get_map_val_dynptr(struct bpf_dynptr * ptr)610cf7052aSJoanne Koong static int get_map_val_dynptr(struct bpf_dynptr *ptr)
620cf7052aSJoanne Koong {
630cf7052aSJoanne Koong 	__u32 key = 0, *map_val;
640cf7052aSJoanne Koong 
650cf7052aSJoanne Koong 	bpf_map_update_elem(&array_map3, &key, &val, 0);
660cf7052aSJoanne Koong 
670cf7052aSJoanne Koong 	map_val = bpf_map_lookup_elem(&array_map3, &key);
680cf7052aSJoanne Koong 	if (!map_val)
690cf7052aSJoanne Koong 		return -ENOENT;
700cf7052aSJoanne Koong 
710cf7052aSJoanne Koong 	bpf_dynptr_from_mem(map_val, sizeof(*map_val), 0, ptr);
720cf7052aSJoanne Koong 
730cf7052aSJoanne Koong 	return 0;
740cf7052aSJoanne Koong }
750cf7052aSJoanne Koong 
760cf7052aSJoanne Koong /* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
770cf7052aSJoanne Koong  * bpf_ringbuf_submit/discard_dynptr call
780cf7052aSJoanne Koong  */
795653f55eSJoanne Koong SEC("?raw_tp")
80f8064ab9SKumar Kartikeya Dwivedi __failure __msg("Unreleased reference id=2")
ringbuf_missing_release1(void * ctx)810cf7052aSJoanne Koong int ringbuf_missing_release1(void *ctx)
820cf7052aSJoanne Koong {
830cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
840cf7052aSJoanne Koong 
850cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
860cf7052aSJoanne Koong 
870cf7052aSJoanne Koong 	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
880cf7052aSJoanne Koong 
890cf7052aSJoanne Koong 	return 0;
900cf7052aSJoanne Koong }
910cf7052aSJoanne Koong 
925653f55eSJoanne Koong SEC("?raw_tp")
93f8064ab9SKumar Kartikeya Dwivedi __failure __msg("Unreleased reference id=4")
ringbuf_missing_release2(void * ctx)940cf7052aSJoanne Koong int ringbuf_missing_release2(void *ctx)
950cf7052aSJoanne Koong {
960cf7052aSJoanne Koong 	struct bpf_dynptr ptr1, ptr2;
970cf7052aSJoanne Koong 	struct sample *sample;
980cf7052aSJoanne Koong 
990cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr1);
1000cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
1010cf7052aSJoanne Koong 
1020cf7052aSJoanne Koong 	sample = bpf_dynptr_data(&ptr1, 0, sizeof(*sample));
1030cf7052aSJoanne Koong 	if (!sample) {
1040cf7052aSJoanne Koong 		bpf_ringbuf_discard_dynptr(&ptr1, 0);
1050cf7052aSJoanne Koong 		bpf_ringbuf_discard_dynptr(&ptr2, 0);
1060cf7052aSJoanne Koong 		return 0;
1070cf7052aSJoanne Koong 	}
1080cf7052aSJoanne Koong 
1090cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr1, 0);
1100cf7052aSJoanne Koong 
1110cf7052aSJoanne Koong 	/* missing a call to bpf_ringbuf_discard/submit_dynptr on ptr2 */
1120cf7052aSJoanne Koong 
1130cf7052aSJoanne Koong 	return 0;
1140cf7052aSJoanne Koong }
1150cf7052aSJoanne Koong 
missing_release_callback_fn(__u32 index,void * data)1160cf7052aSJoanne Koong static int missing_release_callback_fn(__u32 index, void *data)
1170cf7052aSJoanne Koong {
1180cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
1190cf7052aSJoanne Koong 
1200cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1210cf7052aSJoanne Koong 
1220cf7052aSJoanne Koong 	/* missing a call to bpf_ringbuf_discard/submit_dynptr */
1230cf7052aSJoanne Koong 
1240cf7052aSJoanne Koong 	return 0;
1250cf7052aSJoanne Koong }
1260cf7052aSJoanne Koong 
1270cf7052aSJoanne Koong /* Any dynptr initialized within a callback must have bpf_dynptr_put called */
1285653f55eSJoanne Koong SEC("?raw_tp")
12926c386ecSAndrii Nakryiko __failure __msg("Unreleased reference id")
ringbuf_missing_release_callback(void * ctx)1300cf7052aSJoanne Koong int ringbuf_missing_release_callback(void *ctx)
1310cf7052aSJoanne Koong {
1320cf7052aSJoanne Koong 	bpf_loop(10, missing_release_callback_fn, NULL, 0);
1330cf7052aSJoanne Koong 	return 0;
1340cf7052aSJoanne Koong }
1350cf7052aSJoanne Koong 
1360cf7052aSJoanne Koong /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
1375653f55eSJoanne Koong SEC("?raw_tp")
13826c386ecSAndrii Nakryiko __failure __msg("arg 1 is an unacquired reference")
ringbuf_release_uninit_dynptr(void * ctx)1390cf7052aSJoanne Koong int ringbuf_release_uninit_dynptr(void *ctx)
1400cf7052aSJoanne Koong {
1410cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
1420cf7052aSJoanne Koong 
1430cf7052aSJoanne Koong 	/* this should fail */
1440cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
1450cf7052aSJoanne Koong 
1460cf7052aSJoanne Koong 	return 0;
1470cf7052aSJoanne Koong }
1480cf7052aSJoanne Koong 
1490cf7052aSJoanne Koong /* A dynptr can't be used after it has been invalidated */
1505653f55eSJoanne Koong SEC("?raw_tp")
15126c386ecSAndrii Nakryiko __failure __msg("Expected an initialized dynptr as arg #3")
use_after_invalid(void * ctx)1520cf7052aSJoanne Koong int use_after_invalid(void *ctx)
1530cf7052aSJoanne Koong {
1540cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
1550cf7052aSJoanne Koong 	char read_data[64];
1560cf7052aSJoanne Koong 
1570cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(read_data), 0, &ptr);
1580cf7052aSJoanne Koong 
159f8d3da4eSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
1600cf7052aSJoanne Koong 
1610cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
1620cf7052aSJoanne Koong 
1630cf7052aSJoanne Koong 	/* this should fail */
164f8d3da4eSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
1650cf7052aSJoanne Koong 
1660cf7052aSJoanne Koong 	return 0;
1670cf7052aSJoanne Koong }
1680cf7052aSJoanne Koong 
1690cf7052aSJoanne Koong /* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
1705653f55eSJoanne Koong SEC("?raw_tp")
17126c386ecSAndrii Nakryiko __failure __msg("type=mem expected=ringbuf_mem")
ringbuf_invalid_api(void * ctx)1720cf7052aSJoanne Koong int ringbuf_invalid_api(void *ctx)
1730cf7052aSJoanne Koong {
1740cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
1750cf7052aSJoanne Koong 	struct sample *sample;
1760cf7052aSJoanne Koong 
1770cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
1780cf7052aSJoanne Koong 	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
1790cf7052aSJoanne Koong 	if (!sample)
1800cf7052aSJoanne Koong 		goto done;
1810cf7052aSJoanne Koong 
1820cf7052aSJoanne Koong 	sample->pid = 123;
1830cf7052aSJoanne Koong 
1840cf7052aSJoanne Koong 	/* invalid API use. need to use dynptr API to submit/discard */
1850cf7052aSJoanne Koong 	bpf_ringbuf_submit(sample, 0);
1860cf7052aSJoanne Koong 
1870cf7052aSJoanne Koong done:
1880cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
1890cf7052aSJoanne Koong 	return 0;
1900cf7052aSJoanne Koong }
1910cf7052aSJoanne Koong 
1920cf7052aSJoanne Koong /* Can't add a dynptr to a map */
1935653f55eSJoanne Koong SEC("?raw_tp")
19426c386ecSAndrii Nakryiko __failure __msg("invalid indirect read from stack")
add_dynptr_to_map1(void * ctx)1950cf7052aSJoanne Koong int add_dynptr_to_map1(void *ctx)
1960cf7052aSJoanne Koong {
1970cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
1980cf7052aSJoanne Koong 	int key = 0;
1990cf7052aSJoanne Koong 
2000cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
2010cf7052aSJoanne Koong 
2020cf7052aSJoanne Koong 	/* this should fail */
2030cf7052aSJoanne Koong 	bpf_map_update_elem(&array_map1, &key, &ptr, 0);
2040cf7052aSJoanne Koong 
2050cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
2060cf7052aSJoanne Koong 
2070cf7052aSJoanne Koong 	return 0;
2080cf7052aSJoanne Koong }
2090cf7052aSJoanne Koong 
2100cf7052aSJoanne Koong /* Can't add a struct with an embedded dynptr to a map */
2115653f55eSJoanne Koong SEC("?raw_tp")
21226c386ecSAndrii Nakryiko __failure __msg("invalid indirect read from stack")
add_dynptr_to_map2(void * ctx)2130cf7052aSJoanne Koong int add_dynptr_to_map2(void *ctx)
2140cf7052aSJoanne Koong {
2150cf7052aSJoanne Koong 	struct test_info x;
2160cf7052aSJoanne Koong 	int key = 0;
2170cf7052aSJoanne Koong 
2180cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &x.ptr);
2190cf7052aSJoanne Koong 
2200cf7052aSJoanne Koong 	/* this should fail */
2210cf7052aSJoanne Koong 	bpf_map_update_elem(&array_map2, &key, &x, 0);
2220cf7052aSJoanne Koong 
2230cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&x.ptr, 0);
2240cf7052aSJoanne Koong 
2250cf7052aSJoanne Koong 	return 0;
2260cf7052aSJoanne Koong }
2270cf7052aSJoanne Koong 
2280cf7052aSJoanne Koong /* A data slice can't be accessed out of bounds */
2295653f55eSJoanne Koong SEC("?raw_tp")
23026c386ecSAndrii Nakryiko __failure __msg("value is outside of the allowed memory range")
data_slice_out_of_bounds_ringbuf(void * ctx)2310cf7052aSJoanne Koong int data_slice_out_of_bounds_ringbuf(void *ctx)
2320cf7052aSJoanne Koong {
2330cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
2340cf7052aSJoanne Koong 	void *data;
2350cf7052aSJoanne Koong 
2360cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
2370cf7052aSJoanne Koong 
2380cf7052aSJoanne Koong 	data  = bpf_dynptr_data(&ptr, 0, 8);
2390cf7052aSJoanne Koong 	if (!data)
2400cf7052aSJoanne Koong 		goto done;
2410cf7052aSJoanne Koong 
2420cf7052aSJoanne Koong 	/* can't index out of bounds of the data slice */
2430cf7052aSJoanne Koong 	val = *((char *)data + 8);
2440cf7052aSJoanne Koong 
2450cf7052aSJoanne Koong done:
2460cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
2470cf7052aSJoanne Koong 	return 0;
2480cf7052aSJoanne Koong }
2490cf7052aSJoanne Koong 
250cfa7b011SJoanne Koong /* A data slice can't be accessed out of bounds */
251cfa7b011SJoanne Koong SEC("?tc")
252cfa7b011SJoanne Koong __failure __msg("value is outside of the allowed memory range")
data_slice_out_of_bounds_skb(struct __sk_buff * skb)253cfa7b011SJoanne Koong int data_slice_out_of_bounds_skb(struct __sk_buff *skb)
254cfa7b011SJoanne Koong {
255cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
256cfa7b011SJoanne Koong 	struct ethhdr *hdr;
257cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
258cfa7b011SJoanne Koong 
259cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
260cfa7b011SJoanne Koong 
261cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
262cfa7b011SJoanne Koong 	if (!hdr)
263cfa7b011SJoanne Koong 		return SK_DROP;
264cfa7b011SJoanne Koong 
265cfa7b011SJoanne Koong 	/* this should fail */
266cfa7b011SJoanne Koong 	*(__u8*)(hdr + 1) = 1;
267cfa7b011SJoanne Koong 
268cfa7b011SJoanne Koong 	return SK_PASS;
269cfa7b011SJoanne Koong }
270cfa7b011SJoanne Koong 
2715653f55eSJoanne Koong SEC("?raw_tp")
27226c386ecSAndrii Nakryiko __failure __msg("value is outside of the allowed memory range")
data_slice_out_of_bounds_map_value(void * ctx)2730cf7052aSJoanne Koong int data_slice_out_of_bounds_map_value(void *ctx)
2740cf7052aSJoanne Koong {
275c8ed6685SAndrii Nakryiko 	__u32 map_val;
2760cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
2770cf7052aSJoanne Koong 	void *data;
2780cf7052aSJoanne Koong 
2790cf7052aSJoanne Koong 	get_map_val_dynptr(&ptr);
2800cf7052aSJoanne Koong 
2810cf7052aSJoanne Koong 	data  = bpf_dynptr_data(&ptr, 0, sizeof(map_val));
2820cf7052aSJoanne Koong 	if (!data)
2830cf7052aSJoanne Koong 		return 0;
2840cf7052aSJoanne Koong 
2850cf7052aSJoanne Koong 	/* can't index out of bounds of the data slice */
2860cf7052aSJoanne Koong 	val = *((char *)data + (sizeof(map_val) + 1));
2870cf7052aSJoanne Koong 
2880cf7052aSJoanne Koong 	return 0;
2890cf7052aSJoanne Koong }
2900cf7052aSJoanne Koong 
2910cf7052aSJoanne Koong /* A data slice can't be used after it has been released */
2925653f55eSJoanne Koong SEC("?raw_tp")
29326c386ecSAndrii Nakryiko __failure __msg("invalid mem access 'scalar'")
data_slice_use_after_release1(void * ctx)294dc444be8SJoanne Koong int data_slice_use_after_release1(void *ctx)
2950cf7052aSJoanne Koong {
2960cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
2970cf7052aSJoanne Koong 	struct sample *sample;
2980cf7052aSJoanne Koong 
2990cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr);
3000cf7052aSJoanne Koong 	sample = bpf_dynptr_data(&ptr, 0, sizeof(*sample));
3010cf7052aSJoanne Koong 	if (!sample)
3020cf7052aSJoanne Koong 		goto done;
3030cf7052aSJoanne Koong 
3040cf7052aSJoanne Koong 	sample->pid = 123;
3050cf7052aSJoanne Koong 
3060cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
3070cf7052aSJoanne Koong 
3080cf7052aSJoanne Koong 	/* this should fail */
3090cf7052aSJoanne Koong 	val = sample->pid;
3100cf7052aSJoanne Koong 
3110cf7052aSJoanne Koong 	return 0;
3120cf7052aSJoanne Koong 
3130cf7052aSJoanne Koong done:
3140cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
3150cf7052aSJoanne Koong 	return 0;
3160cf7052aSJoanne Koong }
3170cf7052aSJoanne Koong 
318dc444be8SJoanne Koong /* A data slice can't be used after it has been released.
319dc444be8SJoanne Koong  *
320dc444be8SJoanne Koong  * This tests the case where the data slice tracks a dynptr (ptr2)
321dc444be8SJoanne Koong  * that is at a non-zero offset from the frame pointer (ptr1 is at fp,
322dc444be8SJoanne Koong  * ptr2 is at fp - 16).
323dc444be8SJoanne Koong  */
324dc444be8SJoanne Koong SEC("?raw_tp")
32526c386ecSAndrii Nakryiko __failure __msg("invalid mem access 'scalar'")
data_slice_use_after_release2(void * ctx)326dc444be8SJoanne Koong int data_slice_use_after_release2(void *ctx)
327dc444be8SJoanne Koong {
328dc444be8SJoanne Koong 	struct bpf_dynptr ptr1, ptr2;
329dc444be8SJoanne Koong 	struct sample *sample;
330dc444be8SJoanne Koong 
331dc444be8SJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);
332dc444be8SJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
333dc444be8SJoanne Koong 
334dc444be8SJoanne Koong 	sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));
335dc444be8SJoanne Koong 	if (!sample)
336dc444be8SJoanne Koong 		goto done;
337dc444be8SJoanne Koong 
338dc444be8SJoanne Koong 	sample->pid = 23;
339dc444be8SJoanne Koong 
340dc444be8SJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr2, 0);
341dc444be8SJoanne Koong 
342dc444be8SJoanne Koong 	/* this should fail */
343dc444be8SJoanne Koong 	sample->pid = 23;
344dc444be8SJoanne Koong 
345dc444be8SJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr1, 0);
346dc444be8SJoanne Koong 
347dc444be8SJoanne Koong 	return 0;
348dc444be8SJoanne Koong 
349dc444be8SJoanne Koong done:
350dc444be8SJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr2, 0);
351dc444be8SJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr1, 0);
352dc444be8SJoanne Koong 	return 0;
353dc444be8SJoanne Koong }
354dc444be8SJoanne Koong 
3550cf7052aSJoanne Koong /* A data slice must be first checked for NULL */
3565653f55eSJoanne Koong SEC("?raw_tp")
35726c386ecSAndrii Nakryiko __failure __msg("invalid mem access 'mem_or_null'")
data_slice_missing_null_check1(void * ctx)3580cf7052aSJoanne Koong int data_slice_missing_null_check1(void *ctx)
3590cf7052aSJoanne Koong {
3600cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
3610cf7052aSJoanne Koong 	void *data;
3620cf7052aSJoanne Koong 
3630cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
3640cf7052aSJoanne Koong 
3650cf7052aSJoanne Koong 	data  = bpf_dynptr_data(&ptr, 0, 8);
3660cf7052aSJoanne Koong 
3670cf7052aSJoanne Koong 	/* missing if (!data) check */
3680cf7052aSJoanne Koong 
3690cf7052aSJoanne Koong 	/* this should fail */
3700cf7052aSJoanne Koong 	*(__u8 *)data = 3;
3710cf7052aSJoanne Koong 
3720cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
3730cf7052aSJoanne Koong 	return 0;
3740cf7052aSJoanne Koong }
3750cf7052aSJoanne Koong 
3760cf7052aSJoanne Koong /* A data slice can't be dereferenced if it wasn't checked for null */
3775653f55eSJoanne Koong SEC("?raw_tp")
37826c386ecSAndrii Nakryiko __failure __msg("invalid mem access 'mem_or_null'")
data_slice_missing_null_check2(void * ctx)3790cf7052aSJoanne Koong int data_slice_missing_null_check2(void *ctx)
3800cf7052aSJoanne Koong {
3810cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
3820cf7052aSJoanne Koong 	__u64 *data1, *data2;
3830cf7052aSJoanne Koong 
3840cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
3850cf7052aSJoanne Koong 
3860cf7052aSJoanne Koong 	data1 = bpf_dynptr_data(&ptr, 0, 8);
3870cf7052aSJoanne Koong 	data2 = bpf_dynptr_data(&ptr, 0, 8);
3880cf7052aSJoanne Koong 	if (data1)
3890cf7052aSJoanne Koong 		/* this should fail */
3900cf7052aSJoanne Koong 		*data2 = 3;
3910cf7052aSJoanne Koong 
3920cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
3930cf7052aSJoanne Koong 	return 0;
3940cf7052aSJoanne Koong }
3950cf7052aSJoanne Koong 
3960cf7052aSJoanne Koong /* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
3970cf7052aSJoanne Koong  * dynptr argument
3980cf7052aSJoanne Koong  */
3995653f55eSJoanne Koong SEC("?raw_tp")
40026c386ecSAndrii Nakryiko __failure __msg("invalid indirect read from stack")
invalid_helper1(void * ctx)4010cf7052aSJoanne Koong int invalid_helper1(void *ctx)
4020cf7052aSJoanne Koong {
4030cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
4040cf7052aSJoanne Koong 
4050cf7052aSJoanne Koong 	get_map_val_dynptr(&ptr);
4060cf7052aSJoanne Koong 
4070cf7052aSJoanne Koong 	/* this should fail */
4080cf7052aSJoanne Koong 	bpf_strncmp((const char *)&ptr, sizeof(ptr), "hello!");
4090cf7052aSJoanne Koong 
4100cf7052aSJoanne Koong 	return 0;
4110cf7052aSJoanne Koong }
4120cf7052aSJoanne Koong 
4130cf7052aSJoanne Koong /* A dynptr can't be passed into a helper function at a non-zero offset */
4145653f55eSJoanne Koong SEC("?raw_tp")
41579168a66SKumar Kartikeya Dwivedi __failure __msg("cannot pass in dynptr at an offset=-8")
invalid_helper2(void * ctx)4160cf7052aSJoanne Koong int invalid_helper2(void *ctx)
4170cf7052aSJoanne Koong {
4180cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
4190cf7052aSJoanne Koong 	char read_data[64];
4200cf7052aSJoanne Koong 
4210cf7052aSJoanne Koong 	get_map_val_dynptr(&ptr);
4220cf7052aSJoanne Koong 
4230cf7052aSJoanne Koong 	/* this should fail */
424f8d3da4eSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 8, 0, 0);
4250cf7052aSJoanne Koong 	return 0;
4260cf7052aSJoanne Koong }
4270cf7052aSJoanne Koong 
4280cf7052aSJoanne Koong /* A bpf_dynptr is invalidated if it's been written into */
4295653f55eSJoanne Koong SEC("?raw_tp")
43026c386ecSAndrii Nakryiko __failure __msg("Expected an initialized dynptr as arg #1")
invalid_write1(void * ctx)4310cf7052aSJoanne Koong int invalid_write1(void *ctx)
4320cf7052aSJoanne Koong {
4330cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
4340cf7052aSJoanne Koong 	void *data;
4350cf7052aSJoanne Koong 	__u8 x = 0;
4360cf7052aSJoanne Koong 
4370cf7052aSJoanne Koong 	get_map_val_dynptr(&ptr);
4380cf7052aSJoanne Koong 
4390cf7052aSJoanne Koong 	memcpy(&ptr, &x, sizeof(x));
4400cf7052aSJoanne Koong 
4410cf7052aSJoanne Koong 	/* this should fail */
4420cf7052aSJoanne Koong 	data = bpf_dynptr_data(&ptr, 0, 1);
443c8ed6685SAndrii Nakryiko 	__sink(data);
4440cf7052aSJoanne Koong 
4450cf7052aSJoanne Koong 	return 0;
4460cf7052aSJoanne Koong }
4470cf7052aSJoanne Koong 
4480cf7052aSJoanne Koong /*
4490cf7052aSJoanne Koong  * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed
4500cf7052aSJoanne Koong  * offset
4510cf7052aSJoanne Koong  */
4525653f55eSJoanne Koong SEC("?raw_tp")
453ef8fc7a0SKumar Kartikeya Dwivedi __failure __msg("cannot overwrite referenced dynptr")
invalid_write2(void * ctx)4540cf7052aSJoanne Koong int invalid_write2(void *ctx)
4550cf7052aSJoanne Koong {
4560cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
4570cf7052aSJoanne Koong 	char read_data[64];
4580cf7052aSJoanne Koong 	__u8 x = 0;
4590cf7052aSJoanne Koong 
4600cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
4610cf7052aSJoanne Koong 
4620cf7052aSJoanne Koong 	memcpy((void *)&ptr + 8, &x, sizeof(x));
4630cf7052aSJoanne Koong 
4640cf7052aSJoanne Koong 	/* this should fail */
465f8d3da4eSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
4660cf7052aSJoanne Koong 
4670cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
4680cf7052aSJoanne Koong 
4690cf7052aSJoanne Koong 	return 0;
4700cf7052aSJoanne Koong }
4710cf7052aSJoanne Koong 
4720cf7052aSJoanne Koong /*
4730cf7052aSJoanne Koong  * A bpf_dynptr can't be used as a dynptr if it has been written into at a
4740cf7052aSJoanne Koong  * non-const offset
4750cf7052aSJoanne Koong  */
4765653f55eSJoanne Koong SEC("?raw_tp")
477ef8fc7a0SKumar Kartikeya Dwivedi __failure __msg("cannot overwrite referenced dynptr")
invalid_write3(void * ctx)4780cf7052aSJoanne Koong int invalid_write3(void *ctx)
4790cf7052aSJoanne Koong {
4800cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
4810cf7052aSJoanne Koong 	char stack_buf[16];
4820cf7052aSJoanne Koong 	unsigned long len;
4830cf7052aSJoanne Koong 	__u8 x = 0;
4840cf7052aSJoanne Koong 
4850cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 8, 0, &ptr);
4860cf7052aSJoanne Koong 
4870cf7052aSJoanne Koong 	memcpy(stack_buf, &val, sizeof(val));
4880cf7052aSJoanne Koong 	len = stack_buf[0] & 0xf;
4890cf7052aSJoanne Koong 
4900cf7052aSJoanne Koong 	memcpy((void *)&ptr + len, &x, sizeof(x));
4910cf7052aSJoanne Koong 
4920cf7052aSJoanne Koong 	/* this should fail */
4930cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
4940cf7052aSJoanne Koong 
4950cf7052aSJoanne Koong 	return 0;
4960cf7052aSJoanne Koong }
4970cf7052aSJoanne Koong 
invalid_write4_callback(__u32 index,void * data)4980cf7052aSJoanne Koong static int invalid_write4_callback(__u32 index, void *data)
4990cf7052aSJoanne Koong {
5000cf7052aSJoanne Koong 	*(__u32 *)data = 123;
5010cf7052aSJoanne Koong 
5020cf7052aSJoanne Koong 	return 0;
5030cf7052aSJoanne Koong }
5040cf7052aSJoanne Koong 
5050cf7052aSJoanne Koong /* If the dynptr is written into in a callback function, it should
5060cf7052aSJoanne Koong  * be invalidated as a dynptr
5070cf7052aSJoanne Koong  */
5085653f55eSJoanne Koong SEC("?raw_tp")
509ef8fc7a0SKumar Kartikeya Dwivedi __failure __msg("cannot overwrite referenced dynptr")
invalid_write4(void * ctx)5100cf7052aSJoanne Koong int invalid_write4(void *ctx)
5110cf7052aSJoanne Koong {
5120cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
5130cf7052aSJoanne Koong 
5140cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
5150cf7052aSJoanne Koong 
5160cf7052aSJoanne Koong 	bpf_loop(10, invalid_write4_callback, &ptr, 0);
5170cf7052aSJoanne Koong 
5180cf7052aSJoanne Koong 	/* this should fail */
5190cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
5200cf7052aSJoanne Koong 
5210cf7052aSJoanne Koong 	return 0;
5220cf7052aSJoanne Koong }
5230cf7052aSJoanne Koong 
5240cf7052aSJoanne Koong /* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
5250cf7052aSJoanne Koong struct bpf_dynptr global_dynptr;
52626c386ecSAndrii Nakryiko 
5275653f55eSJoanne Koong SEC("?raw_tp")
52826c386ecSAndrii Nakryiko __failure __msg("type=map_value expected=fp")
global(void * ctx)5290cf7052aSJoanne Koong int global(void *ctx)
5300cf7052aSJoanne Koong {
5310cf7052aSJoanne Koong 	/* this should fail */
5320cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &global_dynptr);
5330cf7052aSJoanne Koong 
5340cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&global_dynptr, 0);
5350cf7052aSJoanne Koong 
5360cf7052aSJoanne Koong 	return 0;
5370cf7052aSJoanne Koong }
5380cf7052aSJoanne Koong 
5390cf7052aSJoanne Koong /* A direct read should fail */
5405653f55eSJoanne Koong SEC("?raw_tp")
54126c386ecSAndrii Nakryiko __failure __msg("invalid read from stack")
invalid_read1(void * ctx)5420cf7052aSJoanne Koong int invalid_read1(void *ctx)
5430cf7052aSJoanne Koong {
5440cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
5450cf7052aSJoanne Koong 
5460cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
5470cf7052aSJoanne Koong 
5480cf7052aSJoanne Koong 	/* this should fail */
5490cf7052aSJoanne Koong 	val = *(int *)&ptr;
5500cf7052aSJoanne Koong 
5510cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
5520cf7052aSJoanne Koong 
5530cf7052aSJoanne Koong 	return 0;
5540cf7052aSJoanne Koong }
5550cf7052aSJoanne Koong 
5560cf7052aSJoanne Koong /* A direct read at an offset should fail */
5575653f55eSJoanne Koong SEC("?raw_tp")
55826c386ecSAndrii Nakryiko __failure __msg("cannot pass in dynptr at an offset")
invalid_read2(void * ctx)5590cf7052aSJoanne Koong int invalid_read2(void *ctx)
5600cf7052aSJoanne Koong {
5610cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
5620cf7052aSJoanne Koong 	char read_data[64];
5630cf7052aSJoanne Koong 
5640cf7052aSJoanne Koong 	get_map_val_dynptr(&ptr);
5650cf7052aSJoanne Koong 
5660cf7052aSJoanne Koong 	/* this should fail */
567f8d3da4eSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), (void *)&ptr + 1, 0, 0);
5680cf7052aSJoanne Koong 
5690cf7052aSJoanne Koong 	return 0;
5700cf7052aSJoanne Koong }
5710cf7052aSJoanne Koong 
5720cf7052aSJoanne Koong /* A direct read at an offset into the lower stack slot should fail */
5735653f55eSJoanne Koong SEC("?raw_tp")
57426c386ecSAndrii Nakryiko __failure __msg("invalid read from stack")
invalid_read3(void * ctx)5750cf7052aSJoanne Koong int invalid_read3(void *ctx)
5760cf7052aSJoanne Koong {
5770cf7052aSJoanne Koong 	struct bpf_dynptr ptr1, ptr2;
5780cf7052aSJoanne Koong 
5790cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr1);
5800cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr2);
5810cf7052aSJoanne Koong 
5820cf7052aSJoanne Koong 	/* this should fail */
5830cf7052aSJoanne Koong 	memcpy(&val, (void *)&ptr1 + 8, sizeof(val));
5840cf7052aSJoanne Koong 
5850cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr1, 0);
5860cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr2, 0);
5870cf7052aSJoanne Koong 
5880cf7052aSJoanne Koong 	return 0;
5890cf7052aSJoanne Koong }
5900cf7052aSJoanne Koong 
invalid_read4_callback(__u32 index,void * data)5910cf7052aSJoanne Koong static int invalid_read4_callback(__u32 index, void *data)
5920cf7052aSJoanne Koong {
5930cf7052aSJoanne Koong 	/* this should fail */
5940cf7052aSJoanne Koong 	val = *(__u32 *)data;
5950cf7052aSJoanne Koong 
5960cf7052aSJoanne Koong 	return 0;
5970cf7052aSJoanne Koong }
5980cf7052aSJoanne Koong 
5990cf7052aSJoanne Koong /* A direct read within a callback function should fail */
6005653f55eSJoanne Koong SEC("?raw_tp")
60126c386ecSAndrii Nakryiko __failure __msg("invalid read from stack")
invalid_read4(void * ctx)6020cf7052aSJoanne Koong int invalid_read4(void *ctx)
6030cf7052aSJoanne Koong {
6040cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
6050cf7052aSJoanne Koong 
6060cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
6070cf7052aSJoanne Koong 
6080cf7052aSJoanne Koong 	bpf_loop(10, invalid_read4_callback, &ptr, 0);
6090cf7052aSJoanne Koong 
6100cf7052aSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
6110cf7052aSJoanne Koong 
6120cf7052aSJoanne Koong 	return 0;
6130cf7052aSJoanne Koong }
6140cf7052aSJoanne Koong 
6150cf7052aSJoanne Koong /* Initializing a dynptr on an offset should fail */
6165653f55eSJoanne Koong SEC("?raw_tp")
61779168a66SKumar Kartikeya Dwivedi __failure __msg("cannot pass in dynptr at an offset=0")
invalid_offset(void * ctx)6180cf7052aSJoanne Koong int invalid_offset(void *ctx)
6190cf7052aSJoanne Koong {
6200cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
6210cf7052aSJoanne Koong 
6220cf7052aSJoanne Koong 	/* this should fail */
6230cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr + 1);
6240cf7052aSJoanne Koong 
6250cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
6260cf7052aSJoanne Koong 
6270cf7052aSJoanne Koong 	return 0;
6280cf7052aSJoanne Koong }
6290cf7052aSJoanne Koong 
6300cf7052aSJoanne Koong /* Can't release a dynptr twice */
6315653f55eSJoanne Koong SEC("?raw_tp")
63226c386ecSAndrii Nakryiko __failure __msg("arg 1 is an unacquired reference")
release_twice(void * ctx)6330cf7052aSJoanne Koong int release_twice(void *ctx)
6340cf7052aSJoanne Koong {
6350cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
6360cf7052aSJoanne Koong 
6370cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 16, 0, &ptr);
6380cf7052aSJoanne Koong 
6390cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
6400cf7052aSJoanne Koong 
6410cf7052aSJoanne Koong 	/* this second release should fail */
6420cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
6430cf7052aSJoanne Koong 
6440cf7052aSJoanne Koong 	return 0;
6450cf7052aSJoanne Koong }
6460cf7052aSJoanne Koong 
release_twice_callback_fn(__u32 index,void * data)6470cf7052aSJoanne Koong static int release_twice_callback_fn(__u32 index, void *data)
6480cf7052aSJoanne Koong {
6490cf7052aSJoanne Koong 	/* this should fail */
6500cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(data, 0);
6510cf7052aSJoanne Koong 
6520cf7052aSJoanne Koong 	return 0;
6530cf7052aSJoanne Koong }
6540cf7052aSJoanne Koong 
6550cf7052aSJoanne Koong /* Test that releasing a dynptr twice, where one of the releases happens
656df71a42cSTaichi Nishimura  * within a callback function, fails
6570cf7052aSJoanne Koong  */
6585653f55eSJoanne Koong SEC("?raw_tp")
65926c386ecSAndrii Nakryiko __failure __msg("arg 1 is an unacquired reference")
release_twice_callback(void * ctx)6600cf7052aSJoanne Koong int release_twice_callback(void *ctx)
6610cf7052aSJoanne Koong {
6620cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
6630cf7052aSJoanne Koong 
6640cf7052aSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 32, 0, &ptr);
6650cf7052aSJoanne Koong 
6660cf7052aSJoanne Koong 	bpf_ringbuf_discard_dynptr(&ptr, 0);
6670cf7052aSJoanne Koong 
6680cf7052aSJoanne Koong 	bpf_loop(10, release_twice_callback_fn, &ptr, 0);
6690cf7052aSJoanne Koong 
6700cf7052aSJoanne Koong 	return 0;
6710cf7052aSJoanne Koong }
6720cf7052aSJoanne Koong 
6730cf7052aSJoanne Koong /* Reject unsupported local mem types for dynptr_from_mem API */
6745653f55eSJoanne Koong SEC("?raw_tp")
67526c386ecSAndrii Nakryiko __failure __msg("Unsupported reg type fp for bpf_dynptr_from_mem data")
dynptr_from_mem_invalid_api(void * ctx)6760cf7052aSJoanne Koong int dynptr_from_mem_invalid_api(void *ctx)
6770cf7052aSJoanne Koong {
6780cf7052aSJoanne Koong 	struct bpf_dynptr ptr;
6790cf7052aSJoanne Koong 	int x = 0;
6800cf7052aSJoanne Koong 
6810cf7052aSJoanne Koong 	/* this should fail */
6820cf7052aSJoanne Koong 	bpf_dynptr_from_mem(&x, sizeof(x), 0, &ptr);
6830cf7052aSJoanne Koong 
6840cf7052aSJoanne Koong 	return 0;
6850cf7052aSJoanne Koong }
686f4d24edfSKumar Kartikeya Dwivedi 
687f4d24edfSKumar Kartikeya Dwivedi SEC("?tc")
688f4d24edfSKumar Kartikeya Dwivedi __failure __msg("cannot overwrite referenced dynptr") __log_level(2)
dynptr_pruning_overwrite(struct __sk_buff * ctx)689f4d24edfSKumar Kartikeya Dwivedi int dynptr_pruning_overwrite(struct __sk_buff *ctx)
690f4d24edfSKumar Kartikeya Dwivedi {
691f4d24edfSKumar Kartikeya Dwivedi 	asm volatile (
692f4d24edfSKumar Kartikeya Dwivedi 		"r9 = 0xeB9F;				\
693f4d24edfSKumar Kartikeya Dwivedi 		 r6 = %[ringbuf] ll;			\
694f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r6;				\
695f4d24edfSKumar Kartikeya Dwivedi 		 r2 = 8;				\
696f4d24edfSKumar Kartikeya Dwivedi 		 r3 = 0;				\
697f4d24edfSKumar Kartikeya Dwivedi 		 r4 = r10;				\
698f4d24edfSKumar Kartikeya Dwivedi 		 r4 += -16;				\
699f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_reserve_dynptr];	\
700f4d24edfSKumar Kartikeya Dwivedi 		 if r0 == 0 goto pjmp1;			\
701f4d24edfSKumar Kartikeya Dwivedi 		 goto pjmp2;				\
702f4d24edfSKumar Kartikeya Dwivedi 	pjmp1:						\
703f4d24edfSKumar Kartikeya Dwivedi 		 *(u64 *)(r10 - 16) = r9;		\
704f4d24edfSKumar Kartikeya Dwivedi 	pjmp2:						\
705f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r10;				\
706f4d24edfSKumar Kartikeya Dwivedi 		 r1 += -16;				\
707f4d24edfSKumar Kartikeya Dwivedi 		 r2 = 0;				\
708f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_discard_dynptr];	"
709f4d24edfSKumar Kartikeya Dwivedi 		:
710f4d24edfSKumar Kartikeya Dwivedi 		: __imm(bpf_ringbuf_reserve_dynptr),
711f4d24edfSKumar Kartikeya Dwivedi 		  __imm(bpf_ringbuf_discard_dynptr),
712f4d24edfSKumar Kartikeya Dwivedi 		  __imm_addr(ringbuf)
713f4d24edfSKumar Kartikeya Dwivedi 		: __clobber_all
714f4d24edfSKumar Kartikeya Dwivedi 	);
715f4d24edfSKumar Kartikeya Dwivedi 	return 0;
716f4d24edfSKumar Kartikeya Dwivedi }
717f4d24edfSKumar Kartikeya Dwivedi 
718f4d24edfSKumar Kartikeya Dwivedi SEC("?tc")
719f4d24edfSKumar Kartikeya Dwivedi __success __msg("12: safe") __log_level(2)
dynptr_pruning_stacksafe(struct __sk_buff * ctx)720f4d24edfSKumar Kartikeya Dwivedi int dynptr_pruning_stacksafe(struct __sk_buff *ctx)
721f4d24edfSKumar Kartikeya Dwivedi {
722f4d24edfSKumar Kartikeya Dwivedi 	asm volatile (
723f4d24edfSKumar Kartikeya Dwivedi 		"r9 = 0xeB9F;				\
724f4d24edfSKumar Kartikeya Dwivedi 		 r6 = %[ringbuf] ll;			\
725f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r6;				\
726f4d24edfSKumar Kartikeya Dwivedi 		 r2 = 8;				\
727f4d24edfSKumar Kartikeya Dwivedi 		 r3 = 0;				\
728f4d24edfSKumar Kartikeya Dwivedi 		 r4 = r10;				\
729f4d24edfSKumar Kartikeya Dwivedi 		 r4 += -16;				\
730f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_reserve_dynptr];	\
731f4d24edfSKumar Kartikeya Dwivedi 		 if r0 == 0 goto stjmp1;		\
732f4d24edfSKumar Kartikeya Dwivedi 		 goto stjmp2;				\
733f4d24edfSKumar Kartikeya Dwivedi 	stjmp1:						\
734f4d24edfSKumar Kartikeya Dwivedi 		 r9 = r9;				\
735f4d24edfSKumar Kartikeya Dwivedi 	stjmp2:						\
736f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r10;				\
737f4d24edfSKumar Kartikeya Dwivedi 		 r1 += -16;				\
738f4d24edfSKumar Kartikeya Dwivedi 		 r2 = 0;				\
739f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_discard_dynptr];	"
740f4d24edfSKumar Kartikeya Dwivedi 		:
741f4d24edfSKumar Kartikeya Dwivedi 		: __imm(bpf_ringbuf_reserve_dynptr),
742f4d24edfSKumar Kartikeya Dwivedi 		  __imm(bpf_ringbuf_discard_dynptr),
743f4d24edfSKumar Kartikeya Dwivedi 		  __imm_addr(ringbuf)
744f4d24edfSKumar Kartikeya Dwivedi 		: __clobber_all
745f4d24edfSKumar Kartikeya Dwivedi 	);
746f4d24edfSKumar Kartikeya Dwivedi 	return 0;
747f4d24edfSKumar Kartikeya Dwivedi }
748f4d24edfSKumar Kartikeya Dwivedi 
749f4d24edfSKumar Kartikeya Dwivedi SEC("?tc")
750f4d24edfSKumar Kartikeya Dwivedi __failure __msg("cannot overwrite referenced dynptr") __log_level(2)
dynptr_pruning_type_confusion(struct __sk_buff * ctx)751f4d24edfSKumar Kartikeya Dwivedi int dynptr_pruning_type_confusion(struct __sk_buff *ctx)
752f4d24edfSKumar Kartikeya Dwivedi {
753f4d24edfSKumar Kartikeya Dwivedi 	asm volatile (
754f4d24edfSKumar Kartikeya Dwivedi 		"r6 = %[array_map4] ll;			\
755f4d24edfSKumar Kartikeya Dwivedi 		 r7 = %[ringbuf] ll;			\
756f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r6;				\
757f4d24edfSKumar Kartikeya Dwivedi 		 r2 = r10;				\
758f4d24edfSKumar Kartikeya Dwivedi 		 r2 += -8;				\
759f4d24edfSKumar Kartikeya Dwivedi 		 r9 = 0;				\
760f4d24edfSKumar Kartikeya Dwivedi 		 *(u64 *)(r2 + 0) = r9;			\
761f4d24edfSKumar Kartikeya Dwivedi 		 r3 = r10;				\
762f4d24edfSKumar Kartikeya Dwivedi 		 r3 += -24;				\
763f4d24edfSKumar Kartikeya Dwivedi 		 r9 = 0xeB9FeB9F;			\
764f4d24edfSKumar Kartikeya Dwivedi 		 *(u64 *)(r10 - 16) = r9;		\
765f4d24edfSKumar Kartikeya Dwivedi 		 *(u64 *)(r10 - 24) = r9;		\
766f4d24edfSKumar Kartikeya Dwivedi 		 r9 = 0;				\
767f4d24edfSKumar Kartikeya Dwivedi 		 r4 = 0;				\
768f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r2;				\
769f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_map_update_elem];		\
770f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r6;				\
771f4d24edfSKumar Kartikeya Dwivedi 		 r2 = r8;				\
772f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_map_lookup_elem];		\
773f4d24edfSKumar Kartikeya Dwivedi 		 if r0 != 0 goto tjmp1;			\
774f4d24edfSKumar Kartikeya Dwivedi 		 exit;					\
775f4d24edfSKumar Kartikeya Dwivedi 	tjmp1:						\
776f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r0;				\
777f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r7;				\
778f4d24edfSKumar Kartikeya Dwivedi 		 r2 = 8;				\
779f4d24edfSKumar Kartikeya Dwivedi 		 r3 = 0;				\
780f4d24edfSKumar Kartikeya Dwivedi 		 r4 = r10;				\
781f4d24edfSKumar Kartikeya Dwivedi 		 r4 += -16;				\
782f4d24edfSKumar Kartikeya Dwivedi 		 r0 = *(u64 *)(r0 + 0);			\
783f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_reserve_dynptr];	\
784f4d24edfSKumar Kartikeya Dwivedi 		 if r0 == 0 goto tjmp2;			\
785f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r8;				\
786f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r8;				\
787f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r8;				\
788f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r8;				\
789f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r8;				\
790f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r8;				\
791f4d24edfSKumar Kartikeya Dwivedi 		 r8 = r8;				\
792f4d24edfSKumar Kartikeya Dwivedi 		 goto tjmp3;				\
793f4d24edfSKumar Kartikeya Dwivedi 	tjmp2:						\
794f4d24edfSKumar Kartikeya Dwivedi 		 *(u64 *)(r10 - 8) = r9;		\
795f4d24edfSKumar Kartikeya Dwivedi 		 *(u64 *)(r10 - 16) = r9;		\
796f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r8;				\
797f4d24edfSKumar Kartikeya Dwivedi 		 r1 += 8;				\
798f4d24edfSKumar Kartikeya Dwivedi 		 r2 = 0;				\
799f4d24edfSKumar Kartikeya Dwivedi 		 r3 = 0;				\
800f4d24edfSKumar Kartikeya Dwivedi 		 r4 = r10;				\
801f4d24edfSKumar Kartikeya Dwivedi 		 r4 += -16;				\
802f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_dynptr_from_mem];		\
803f4d24edfSKumar Kartikeya Dwivedi 	tjmp3:						\
804f4d24edfSKumar Kartikeya Dwivedi 		 r1 = r10;				\
805f4d24edfSKumar Kartikeya Dwivedi 		 r1 += -16;				\
806f4d24edfSKumar Kartikeya Dwivedi 		 r2 = 0;				\
807f4d24edfSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_discard_dynptr];	"
808f4d24edfSKumar Kartikeya Dwivedi 		:
809f4d24edfSKumar Kartikeya Dwivedi 		: __imm(bpf_map_update_elem),
810f4d24edfSKumar Kartikeya Dwivedi 		  __imm(bpf_map_lookup_elem),
811f4d24edfSKumar Kartikeya Dwivedi 		  __imm(bpf_ringbuf_reserve_dynptr),
812f4d24edfSKumar Kartikeya Dwivedi 		  __imm(bpf_dynptr_from_mem),
813f4d24edfSKumar Kartikeya Dwivedi 		  __imm(bpf_ringbuf_discard_dynptr),
814f4d24edfSKumar Kartikeya Dwivedi 		  __imm_addr(array_map4),
815f4d24edfSKumar Kartikeya Dwivedi 		  __imm_addr(ringbuf)
816f4d24edfSKumar Kartikeya Dwivedi 		: __clobber_all
817f4d24edfSKumar Kartikeya Dwivedi 	);
818f4d24edfSKumar Kartikeya Dwivedi 	return 0;
819f4d24edfSKumar Kartikeya Dwivedi }
820ef481013SKumar Kartikeya Dwivedi 
821ef481013SKumar Kartikeya Dwivedi SEC("?tc")
822ef481013SKumar Kartikeya Dwivedi __failure __msg("dynptr has to be at a constant offset") __log_level(2)
dynptr_var_off_overwrite(struct __sk_buff * ctx)823ef481013SKumar Kartikeya Dwivedi int dynptr_var_off_overwrite(struct __sk_buff *ctx)
824ef481013SKumar Kartikeya Dwivedi {
825ef481013SKumar Kartikeya Dwivedi 	asm volatile (
826ef481013SKumar Kartikeya Dwivedi 		"r9 = 16;				\
827ef481013SKumar Kartikeya Dwivedi 		 *(u32 *)(r10 - 4) = r9;		\
828ef481013SKumar Kartikeya Dwivedi 		 r8 = *(u32 *)(r10 - 4);		\
829ef481013SKumar Kartikeya Dwivedi 		 if r8 >= 0 goto vjmp1;			\
830ef481013SKumar Kartikeya Dwivedi 		 r0 = 1;				\
831ef481013SKumar Kartikeya Dwivedi 		 exit;					\
832ef481013SKumar Kartikeya Dwivedi 	vjmp1:						\
833ef481013SKumar Kartikeya Dwivedi 		 if r8 <= 16 goto vjmp2;		\
834ef481013SKumar Kartikeya Dwivedi 		 r0 = 1;				\
835ef481013SKumar Kartikeya Dwivedi 		 exit;					\
836ef481013SKumar Kartikeya Dwivedi 	vjmp2:						\
837ef481013SKumar Kartikeya Dwivedi 		 r8 &= 16;				\
838ef481013SKumar Kartikeya Dwivedi 		 r1 = %[ringbuf] ll;			\
839ef481013SKumar Kartikeya Dwivedi 		 r2 = 8;				\
840ef481013SKumar Kartikeya Dwivedi 		 r3 = 0;				\
841ef481013SKumar Kartikeya Dwivedi 		 r4 = r10;				\
842ef481013SKumar Kartikeya Dwivedi 		 r4 += -32;				\
843ef481013SKumar Kartikeya Dwivedi 		 r4 += r8;				\
844ef481013SKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_reserve_dynptr];	\
845ef481013SKumar Kartikeya Dwivedi 		 r9 = 0xeB9F;				\
846ef481013SKumar Kartikeya Dwivedi 		 *(u64 *)(r10 - 16) = r9;		\
847ef481013SKumar Kartikeya Dwivedi 		 r1 = r10;				\
848ef481013SKumar Kartikeya Dwivedi 		 r1 += -32;				\
849ef481013SKumar Kartikeya Dwivedi 		 r1 += r8;				\
850ef481013SKumar Kartikeya Dwivedi 		 r2 = 0;				\
851ef481013SKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_discard_dynptr];	"
852ef481013SKumar Kartikeya Dwivedi 		:
853ef481013SKumar Kartikeya Dwivedi 		: __imm(bpf_ringbuf_reserve_dynptr),
854ef481013SKumar Kartikeya Dwivedi 		  __imm(bpf_ringbuf_discard_dynptr),
855ef481013SKumar Kartikeya Dwivedi 		  __imm_addr(ringbuf)
856ef481013SKumar Kartikeya Dwivedi 		: __clobber_all
857ef481013SKumar Kartikeya Dwivedi 	);
858ef481013SKumar Kartikeya Dwivedi 	return 0;
859ef481013SKumar Kartikeya Dwivedi }
860011edc8eSKumar Kartikeya Dwivedi 
861011edc8eSKumar Kartikeya Dwivedi SEC("?tc")
862011edc8eSKumar Kartikeya Dwivedi __failure __msg("cannot overwrite referenced dynptr") __log_level(2)
dynptr_partial_slot_invalidate(struct __sk_buff * ctx)863011edc8eSKumar Kartikeya Dwivedi int dynptr_partial_slot_invalidate(struct __sk_buff *ctx)
864011edc8eSKumar Kartikeya Dwivedi {
865011edc8eSKumar Kartikeya Dwivedi 	asm volatile (
866011edc8eSKumar Kartikeya Dwivedi 		"r6 = %[ringbuf] ll;			\
867011edc8eSKumar Kartikeya Dwivedi 		 r7 = %[array_map4] ll;			\
868011edc8eSKumar Kartikeya Dwivedi 		 r1 = r7;				\
869011edc8eSKumar Kartikeya Dwivedi 		 r2 = r10;				\
870011edc8eSKumar Kartikeya Dwivedi 		 r2 += -8;				\
871011edc8eSKumar Kartikeya Dwivedi 		 r9 = 0;				\
872011edc8eSKumar Kartikeya Dwivedi 		 *(u64 *)(r2 + 0) = r9;			\
873011edc8eSKumar Kartikeya Dwivedi 		 r3 = r2;				\
874011edc8eSKumar Kartikeya Dwivedi 		 r4 = 0;				\
875011edc8eSKumar Kartikeya Dwivedi 		 r8 = r2;				\
876011edc8eSKumar Kartikeya Dwivedi 		 call %[bpf_map_update_elem];		\
877011edc8eSKumar Kartikeya Dwivedi 		 r1 = r7;				\
878011edc8eSKumar Kartikeya Dwivedi 		 r2 = r8;				\
879011edc8eSKumar Kartikeya Dwivedi 		 call %[bpf_map_lookup_elem];		\
880011edc8eSKumar Kartikeya Dwivedi 		 if r0 != 0 goto sjmp1;			\
881011edc8eSKumar Kartikeya Dwivedi 		 exit;					\
882011edc8eSKumar Kartikeya Dwivedi 	sjmp1:						\
883011edc8eSKumar Kartikeya Dwivedi 		 r7 = r0;				\
884011edc8eSKumar Kartikeya Dwivedi 		 r1 = r6;				\
885011edc8eSKumar Kartikeya Dwivedi 		 r2 = 8;				\
886011edc8eSKumar Kartikeya Dwivedi 		 r3 = 0;				\
887011edc8eSKumar Kartikeya Dwivedi 		 r4 = r10;				\
888011edc8eSKumar Kartikeya Dwivedi 		 r4 += -24;				\
889011edc8eSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_reserve_dynptr];	\
890011edc8eSKumar Kartikeya Dwivedi 		 *(u64 *)(r10 - 16) = r9;		\
891011edc8eSKumar Kartikeya Dwivedi 		 r1 = r7;				\
892011edc8eSKumar Kartikeya Dwivedi 		 r2 = 8;				\
893011edc8eSKumar Kartikeya Dwivedi 		 r3 = 0;				\
894011edc8eSKumar Kartikeya Dwivedi 		 r4 = r10;				\
895011edc8eSKumar Kartikeya Dwivedi 		 r4 += -16;				\
896011edc8eSKumar Kartikeya Dwivedi 		 call %[bpf_dynptr_from_mem];		\
897011edc8eSKumar Kartikeya Dwivedi 		 r1 = r10;				\
898011edc8eSKumar Kartikeya Dwivedi 		 r1 += -512;				\
899011edc8eSKumar Kartikeya Dwivedi 		 r2 = 488;				\
900011edc8eSKumar Kartikeya Dwivedi 		 r3 = r10;				\
901011edc8eSKumar Kartikeya Dwivedi 		 r3 += -24;				\
902011edc8eSKumar Kartikeya Dwivedi 		 r4 = 0;				\
903011edc8eSKumar Kartikeya Dwivedi 		 r5 = 0;				\
904011edc8eSKumar Kartikeya Dwivedi 		 call %[bpf_dynptr_read];		\
905011edc8eSKumar Kartikeya Dwivedi 		 r8 = 1;				\
906011edc8eSKumar Kartikeya Dwivedi 		 if r0 != 0 goto sjmp2;			\
907011edc8eSKumar Kartikeya Dwivedi 		 r8 = 0;				\
908011edc8eSKumar Kartikeya Dwivedi 	sjmp2:						\
909011edc8eSKumar Kartikeya Dwivedi 		 r1 = r10;				\
910011edc8eSKumar Kartikeya Dwivedi 		 r1 += -24;				\
911011edc8eSKumar Kartikeya Dwivedi 		 r2 = 0;				\
912011edc8eSKumar Kartikeya Dwivedi 		 call %[bpf_ringbuf_discard_dynptr];	"
913011edc8eSKumar Kartikeya Dwivedi 		:
914011edc8eSKumar Kartikeya Dwivedi 		: __imm(bpf_map_update_elem),
915011edc8eSKumar Kartikeya Dwivedi 		  __imm(bpf_map_lookup_elem),
916011edc8eSKumar Kartikeya Dwivedi 		  __imm(bpf_ringbuf_reserve_dynptr),
917011edc8eSKumar Kartikeya Dwivedi 		  __imm(bpf_ringbuf_discard_dynptr),
918011edc8eSKumar Kartikeya Dwivedi 		  __imm(bpf_dynptr_from_mem),
919011edc8eSKumar Kartikeya Dwivedi 		  __imm(bpf_dynptr_read),
920011edc8eSKumar Kartikeya Dwivedi 		  __imm_addr(ringbuf),
921011edc8eSKumar Kartikeya Dwivedi 		  __imm_addr(array_map4)
922011edc8eSKumar Kartikeya Dwivedi 		: __clobber_all
923011edc8eSKumar Kartikeya Dwivedi 	);
924011edc8eSKumar Kartikeya Dwivedi 	return 0;
925011edc8eSKumar Kartikeya Dwivedi }
926ae8e354cSKumar Kartikeya Dwivedi 
927ae8e354cSKumar Kartikeya Dwivedi /* Test that it is allowed to overwrite unreferenced dynptr. */
928ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
929ae8e354cSKumar Kartikeya Dwivedi __success
dynptr_overwrite_unref(void * ctx)930ae8e354cSKumar Kartikeya Dwivedi int dynptr_overwrite_unref(void *ctx)
931ae8e354cSKumar Kartikeya Dwivedi {
932ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr;
933ae8e354cSKumar Kartikeya Dwivedi 
934ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
935ae8e354cSKumar Kartikeya Dwivedi 		return 0;
936ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
937ae8e354cSKumar Kartikeya Dwivedi 		return 0;
938ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
939ae8e354cSKumar Kartikeya Dwivedi 		return 0;
940ae8e354cSKumar Kartikeya Dwivedi 
941ae8e354cSKumar Kartikeya Dwivedi 	return 0;
942ae8e354cSKumar Kartikeya Dwivedi }
943ae8e354cSKumar Kartikeya Dwivedi 
944ae8e354cSKumar Kartikeya Dwivedi /* Test that slices are invalidated on reinitializing a dynptr. */
945ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
946ae8e354cSKumar Kartikeya Dwivedi __failure __msg("invalid mem access 'scalar'")
dynptr_invalidate_slice_reinit(void * ctx)947ae8e354cSKumar Kartikeya Dwivedi int dynptr_invalidate_slice_reinit(void *ctx)
948ae8e354cSKumar Kartikeya Dwivedi {
949ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr;
950ae8e354cSKumar Kartikeya Dwivedi 	__u8 *p;
951ae8e354cSKumar Kartikeya Dwivedi 
952ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
953ae8e354cSKumar Kartikeya Dwivedi 		return 0;
954ae8e354cSKumar Kartikeya Dwivedi 	p = bpf_dynptr_data(&ptr, 0, 1);
955ae8e354cSKumar Kartikeya Dwivedi 	if (!p)
956ae8e354cSKumar Kartikeya Dwivedi 		return 0;
957ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
958ae8e354cSKumar Kartikeya Dwivedi 		return 0;
959ae8e354cSKumar Kartikeya Dwivedi 	/* this should fail */
960ae8e354cSKumar Kartikeya Dwivedi 	return *p;
961ae8e354cSKumar Kartikeya Dwivedi }
962ae8e354cSKumar Kartikeya Dwivedi 
963ae8e354cSKumar Kartikeya Dwivedi /* Invalidation of dynptr slices on destruction of dynptr should not miss
964ae8e354cSKumar Kartikeya Dwivedi  * mem_or_null pointers.
965ae8e354cSKumar Kartikeya Dwivedi  */
966ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
967ae8e354cSKumar Kartikeya Dwivedi __failure __msg("R1 type=scalar expected=percpu_ptr_")
dynptr_invalidate_slice_or_null(void * ctx)968ae8e354cSKumar Kartikeya Dwivedi int dynptr_invalidate_slice_or_null(void *ctx)
969ae8e354cSKumar Kartikeya Dwivedi {
970ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr;
971ae8e354cSKumar Kartikeya Dwivedi 	__u8 *p;
972ae8e354cSKumar Kartikeya Dwivedi 
973ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
974ae8e354cSKumar Kartikeya Dwivedi 		return 0;
975ae8e354cSKumar Kartikeya Dwivedi 
976ae8e354cSKumar Kartikeya Dwivedi 	p = bpf_dynptr_data(&ptr, 0, 1);
977ae8e354cSKumar Kartikeya Dwivedi 	*(__u8 *)&ptr = 0;
978ae8e354cSKumar Kartikeya Dwivedi 	/* this should fail */
979ae8e354cSKumar Kartikeya Dwivedi 	bpf_this_cpu_ptr(p);
980ae8e354cSKumar Kartikeya Dwivedi 	return 0;
981ae8e354cSKumar Kartikeya Dwivedi }
982ae8e354cSKumar Kartikeya Dwivedi 
983ae8e354cSKumar Kartikeya Dwivedi /* Destruction of dynptr should also any slices obtained from it */
984ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
985ae8e354cSKumar Kartikeya Dwivedi __failure __msg("R7 invalid mem access 'scalar'")
dynptr_invalidate_slice_failure(void * ctx)986ae8e354cSKumar Kartikeya Dwivedi int dynptr_invalidate_slice_failure(void *ctx)
987ae8e354cSKumar Kartikeya Dwivedi {
988ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr1;
989ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr2;
990ae8e354cSKumar Kartikeya Dwivedi 	__u8 *p1, *p2;
991ae8e354cSKumar Kartikeya Dwivedi 
992ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr1))
993ae8e354cSKumar Kartikeya Dwivedi 		return 0;
994ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr2))
995ae8e354cSKumar Kartikeya Dwivedi 		return 0;
996ae8e354cSKumar Kartikeya Dwivedi 
997ae8e354cSKumar Kartikeya Dwivedi 	p1 = bpf_dynptr_data(&ptr1, 0, 1);
998ae8e354cSKumar Kartikeya Dwivedi 	if (!p1)
999ae8e354cSKumar Kartikeya Dwivedi 		return 0;
1000ae8e354cSKumar Kartikeya Dwivedi 	p2 = bpf_dynptr_data(&ptr2, 0, 1);
1001ae8e354cSKumar Kartikeya Dwivedi 	if (!p2)
1002ae8e354cSKumar Kartikeya Dwivedi 		return 0;
1003ae8e354cSKumar Kartikeya Dwivedi 
1004ae8e354cSKumar Kartikeya Dwivedi 	*(__u8 *)&ptr1 = 0;
1005ae8e354cSKumar Kartikeya Dwivedi 	/* this should fail */
1006ae8e354cSKumar Kartikeya Dwivedi 	return *p1;
1007ae8e354cSKumar Kartikeya Dwivedi }
1008ae8e354cSKumar Kartikeya Dwivedi 
1009ae8e354cSKumar Kartikeya Dwivedi /* Invalidation of slices should be scoped and should not prevent dereferencing
1010ae8e354cSKumar Kartikeya Dwivedi  * slices of another dynptr after destroying unrelated dynptr
1011ae8e354cSKumar Kartikeya Dwivedi  */
1012ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
1013ae8e354cSKumar Kartikeya Dwivedi __success
dynptr_invalidate_slice_success(void * ctx)1014ae8e354cSKumar Kartikeya Dwivedi int dynptr_invalidate_slice_success(void *ctx)
1015ae8e354cSKumar Kartikeya Dwivedi {
1016ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr1;
1017ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr2;
1018ae8e354cSKumar Kartikeya Dwivedi 	__u8 *p1, *p2;
1019ae8e354cSKumar Kartikeya Dwivedi 
1020ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr1))
1021ae8e354cSKumar Kartikeya Dwivedi 		return 1;
1022ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr2))
1023ae8e354cSKumar Kartikeya Dwivedi 		return 1;
1024ae8e354cSKumar Kartikeya Dwivedi 
1025ae8e354cSKumar Kartikeya Dwivedi 	p1 = bpf_dynptr_data(&ptr1, 0, 1);
1026ae8e354cSKumar Kartikeya Dwivedi 	if (!p1)
1027ae8e354cSKumar Kartikeya Dwivedi 		return 1;
1028ae8e354cSKumar Kartikeya Dwivedi 	p2 = bpf_dynptr_data(&ptr2, 0, 1);
1029ae8e354cSKumar Kartikeya Dwivedi 	if (!p2)
1030ae8e354cSKumar Kartikeya Dwivedi 		return 1;
1031ae8e354cSKumar Kartikeya Dwivedi 
1032ae8e354cSKumar Kartikeya Dwivedi 	*(__u8 *)&ptr1 = 0;
1033ae8e354cSKumar Kartikeya Dwivedi 	return *p2;
1034ae8e354cSKumar Kartikeya Dwivedi }
1035ae8e354cSKumar Kartikeya Dwivedi 
1036ae8e354cSKumar Kartikeya Dwivedi /* Overwriting referenced dynptr should be rejected */
1037ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
1038ae8e354cSKumar Kartikeya Dwivedi __failure __msg("cannot overwrite referenced dynptr")
dynptr_overwrite_ref(void * ctx)1039ae8e354cSKumar Kartikeya Dwivedi int dynptr_overwrite_ref(void *ctx)
1040ae8e354cSKumar Kartikeya Dwivedi {
1041ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr;
1042ae8e354cSKumar Kartikeya Dwivedi 
1043ae8e354cSKumar Kartikeya Dwivedi 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr);
1044ae8e354cSKumar Kartikeya Dwivedi 	/* this should fail */
1045ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
1046ae8e354cSKumar Kartikeya Dwivedi 		bpf_ringbuf_discard_dynptr(&ptr, 0);
1047ae8e354cSKumar Kartikeya Dwivedi 	return 0;
1048ae8e354cSKumar Kartikeya Dwivedi }
1049ae8e354cSKumar Kartikeya Dwivedi 
1050ae8e354cSKumar Kartikeya Dwivedi /* Reject writes to dynptr slot from bpf_dynptr_read */
1051ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
1052ae8e354cSKumar Kartikeya Dwivedi __failure __msg("potential write to dynptr at off=-16")
dynptr_read_into_slot(void * ctx)1053ae8e354cSKumar Kartikeya Dwivedi int dynptr_read_into_slot(void *ctx)
1054ae8e354cSKumar Kartikeya Dwivedi {
1055ae8e354cSKumar Kartikeya Dwivedi 	union {
1056ae8e354cSKumar Kartikeya Dwivedi 		struct {
1057ae8e354cSKumar Kartikeya Dwivedi 			char _pad[48];
1058ae8e354cSKumar Kartikeya Dwivedi 			struct bpf_dynptr ptr;
1059ae8e354cSKumar Kartikeya Dwivedi 		};
1060ae8e354cSKumar Kartikeya Dwivedi 		char buf[64];
1061ae8e354cSKumar Kartikeya Dwivedi 	} data;
1062ae8e354cSKumar Kartikeya Dwivedi 
1063ae8e354cSKumar Kartikeya Dwivedi 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &data.ptr);
1064ae8e354cSKumar Kartikeya Dwivedi 	/* this should fail */
1065ae8e354cSKumar Kartikeya Dwivedi 	bpf_dynptr_read(data.buf, sizeof(data.buf), &data.ptr, 0, 0);
1066ae8e354cSKumar Kartikeya Dwivedi 
1067ae8e354cSKumar Kartikeya Dwivedi 	return 0;
1068ae8e354cSKumar Kartikeya Dwivedi }
1069ae8e354cSKumar Kartikeya Dwivedi 
1070cfa7b011SJoanne Koong /* bpf_dynptr_slice()s are read-only and cannot be written to */
1071cfa7b011SJoanne Koong SEC("?tc")
1072cfa7b011SJoanne Koong __failure __msg("R0 cannot write into rdonly_mem")
skb_invalid_slice_write(struct __sk_buff * skb)1073cfa7b011SJoanne Koong int skb_invalid_slice_write(struct __sk_buff *skb)
1074cfa7b011SJoanne Koong {
1075cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1076cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1077cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1078cfa7b011SJoanne Koong 
1079cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1080cfa7b011SJoanne Koong 
1081cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1082cfa7b011SJoanne Koong 	if (!hdr)
1083cfa7b011SJoanne Koong 		return SK_DROP;
1084cfa7b011SJoanne Koong 
1085cfa7b011SJoanne Koong 	/* this should fail */
1086cfa7b011SJoanne Koong 	hdr->h_proto = 1;
1087cfa7b011SJoanne Koong 
1088cfa7b011SJoanne Koong 	return SK_PASS;
1089cfa7b011SJoanne Koong }
1090cfa7b011SJoanne Koong 
1091cfa7b011SJoanne Koong /* The read-only data slice is invalidated whenever a helper changes packet data */
1092cfa7b011SJoanne Koong SEC("?tc")
1093cfa7b011SJoanne Koong __failure __msg("invalid mem access 'scalar'")
skb_invalid_data_slice1(struct __sk_buff * skb)1094cfa7b011SJoanne Koong int skb_invalid_data_slice1(struct __sk_buff *skb)
1095cfa7b011SJoanne Koong {
1096cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1097cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1098cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1099cfa7b011SJoanne Koong 
1100cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1101cfa7b011SJoanne Koong 
1102cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1103cfa7b011SJoanne Koong 	if (!hdr)
1104cfa7b011SJoanne Koong 		return SK_DROP;
1105cfa7b011SJoanne Koong 
1106cfa7b011SJoanne Koong 	val = hdr->h_proto;
1107cfa7b011SJoanne Koong 
1108cfa7b011SJoanne Koong 	if (bpf_skb_pull_data(skb, skb->len))
1109cfa7b011SJoanne Koong 		return SK_DROP;
1110cfa7b011SJoanne Koong 
1111cfa7b011SJoanne Koong 	/* this should fail */
1112cfa7b011SJoanne Koong 	val = hdr->h_proto;
1113cfa7b011SJoanne Koong 
1114cfa7b011SJoanne Koong 	return SK_PASS;
1115cfa7b011SJoanne Koong }
1116cfa7b011SJoanne Koong 
1117cfa7b011SJoanne Koong /* The read-write data slice is invalidated whenever a helper changes packet data */
1118cfa7b011SJoanne Koong SEC("?tc")
1119cfa7b011SJoanne Koong __failure __msg("invalid mem access 'scalar'")
skb_invalid_data_slice2(struct __sk_buff * skb)1120cfa7b011SJoanne Koong int skb_invalid_data_slice2(struct __sk_buff *skb)
1121cfa7b011SJoanne Koong {
1122cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1123cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1124cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1125cfa7b011SJoanne Koong 
1126cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1127cfa7b011SJoanne Koong 
1128cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1129cfa7b011SJoanne Koong 	if (!hdr)
1130cfa7b011SJoanne Koong 		return SK_DROP;
1131cfa7b011SJoanne Koong 
1132cfa7b011SJoanne Koong 	hdr->h_proto = 123;
1133cfa7b011SJoanne Koong 
1134cfa7b011SJoanne Koong 	if (bpf_skb_pull_data(skb, skb->len))
1135cfa7b011SJoanne Koong 		return SK_DROP;
1136cfa7b011SJoanne Koong 
1137cfa7b011SJoanne Koong 	/* this should fail */
1138cfa7b011SJoanne Koong 	hdr->h_proto = 1;
1139cfa7b011SJoanne Koong 
1140cfa7b011SJoanne Koong 	return SK_PASS;
1141cfa7b011SJoanne Koong }
1142cfa7b011SJoanne Koong 
1143cfa7b011SJoanne Koong /* The read-only data slice is invalidated whenever bpf_dynptr_write() is called */
1144cfa7b011SJoanne Koong SEC("?tc")
1145cfa7b011SJoanne Koong __failure __msg("invalid mem access 'scalar'")
skb_invalid_data_slice3(struct __sk_buff * skb)1146cfa7b011SJoanne Koong int skb_invalid_data_slice3(struct __sk_buff *skb)
1147cfa7b011SJoanne Koong {
1148cfa7b011SJoanne Koong 	char write_data[64] = "hello there, world!!";
1149cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1150cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1151cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1152cfa7b011SJoanne Koong 
1153cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1154cfa7b011SJoanne Koong 
1155cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1156cfa7b011SJoanne Koong 	if (!hdr)
1157cfa7b011SJoanne Koong 		return SK_DROP;
1158cfa7b011SJoanne Koong 
1159cfa7b011SJoanne Koong 	val = hdr->h_proto;
1160cfa7b011SJoanne Koong 
1161cfa7b011SJoanne Koong 	bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);
1162cfa7b011SJoanne Koong 
1163cfa7b011SJoanne Koong 	/* this should fail */
1164cfa7b011SJoanne Koong 	val = hdr->h_proto;
1165cfa7b011SJoanne Koong 
1166cfa7b011SJoanne Koong 	return SK_PASS;
1167cfa7b011SJoanne Koong }
1168cfa7b011SJoanne Koong 
1169cfa7b011SJoanne Koong /* The read-write data slice is invalidated whenever bpf_dynptr_write() is called */
1170cfa7b011SJoanne Koong SEC("?tc")
1171cfa7b011SJoanne Koong __failure __msg("invalid mem access 'scalar'")
skb_invalid_data_slice4(struct __sk_buff * skb)1172cfa7b011SJoanne Koong int skb_invalid_data_slice4(struct __sk_buff *skb)
1173cfa7b011SJoanne Koong {
1174cfa7b011SJoanne Koong 	char write_data[64] = "hello there, world!!";
1175cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1176cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1177cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1178cfa7b011SJoanne Koong 
1179cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1180cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1181cfa7b011SJoanne Koong 	if (!hdr)
1182cfa7b011SJoanne Koong 		return SK_DROP;
1183cfa7b011SJoanne Koong 
1184cfa7b011SJoanne Koong 	hdr->h_proto = 123;
1185cfa7b011SJoanne Koong 
1186cfa7b011SJoanne Koong 	bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);
1187cfa7b011SJoanne Koong 
1188cfa7b011SJoanne Koong 	/* this should fail */
1189cfa7b011SJoanne Koong 	hdr->h_proto = 1;
1190cfa7b011SJoanne Koong 
1191cfa7b011SJoanne Koong 	return SK_PASS;
1192cfa7b011SJoanne Koong }
1193cfa7b011SJoanne Koong 
1194cfa7b011SJoanne Koong /* The read-only data slice is invalidated whenever a helper changes packet data */
1195cfa7b011SJoanne Koong SEC("?xdp")
1196cfa7b011SJoanne Koong __failure __msg("invalid mem access 'scalar'")
xdp_invalid_data_slice1(struct xdp_md * xdp)1197cfa7b011SJoanne Koong int xdp_invalid_data_slice1(struct xdp_md *xdp)
1198cfa7b011SJoanne Koong {
1199cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1200cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1201cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1202cfa7b011SJoanne Koong 
1203cfa7b011SJoanne Koong 	bpf_dynptr_from_xdp(xdp, 0, &ptr);
1204cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice(&ptr, 0, buffer, sizeof(buffer));
1205cfa7b011SJoanne Koong 	if (!hdr)
1206cfa7b011SJoanne Koong 		return SK_DROP;
1207cfa7b011SJoanne Koong 
1208cfa7b011SJoanne Koong 	val = hdr->h_proto;
1209cfa7b011SJoanne Koong 
1210cfa7b011SJoanne Koong 	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1211cfa7b011SJoanne Koong 		return XDP_DROP;
1212cfa7b011SJoanne Koong 
1213cfa7b011SJoanne Koong 	/* this should fail */
1214cfa7b011SJoanne Koong 	val = hdr->h_proto;
1215cfa7b011SJoanne Koong 
1216cfa7b011SJoanne Koong 	return XDP_PASS;
1217cfa7b011SJoanne Koong }
1218cfa7b011SJoanne Koong 
1219cfa7b011SJoanne Koong /* The read-write data slice is invalidated whenever a helper changes packet data */
1220cfa7b011SJoanne Koong SEC("?xdp")
1221cfa7b011SJoanne Koong __failure __msg("invalid mem access 'scalar'")
xdp_invalid_data_slice2(struct xdp_md * xdp)1222cfa7b011SJoanne Koong int xdp_invalid_data_slice2(struct xdp_md *xdp)
1223cfa7b011SJoanne Koong {
1224cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1225cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1226cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1227cfa7b011SJoanne Koong 
1228cfa7b011SJoanne Koong 	bpf_dynptr_from_xdp(xdp, 0, &ptr);
1229cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1230cfa7b011SJoanne Koong 	if (!hdr)
1231cfa7b011SJoanne Koong 		return SK_DROP;
1232cfa7b011SJoanne Koong 
1233cfa7b011SJoanne Koong 	hdr->h_proto = 9;
1234cfa7b011SJoanne Koong 
1235cfa7b011SJoanne Koong 	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1236cfa7b011SJoanne Koong 		return XDP_DROP;
1237cfa7b011SJoanne Koong 
1238cfa7b011SJoanne Koong 	/* this should fail */
1239cfa7b011SJoanne Koong 	hdr->h_proto = 1;
1240cfa7b011SJoanne Koong 
1241cfa7b011SJoanne Koong 	return XDP_PASS;
1242cfa7b011SJoanne Koong }
1243cfa7b011SJoanne Koong 
1244cfa7b011SJoanne Koong /* Only supported prog type can create skb-type dynptrs */
1245cfa7b011SJoanne Koong SEC("?raw_tp")
1246cfa7b011SJoanne Koong __failure __msg("calling kernel function bpf_dynptr_from_skb is not allowed")
skb_invalid_ctx(void * ctx)1247cfa7b011SJoanne Koong int skb_invalid_ctx(void *ctx)
1248cfa7b011SJoanne Koong {
1249cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1250cfa7b011SJoanne Koong 
1251cfa7b011SJoanne Koong 	/* this should fail */
1252cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(ctx, 0, &ptr);
1253cfa7b011SJoanne Koong 
1254cfa7b011SJoanne Koong 	return 0;
1255cfa7b011SJoanne Koong }
1256cfa7b011SJoanne Koong 
1257ae8e354cSKumar Kartikeya Dwivedi /* Reject writes to dynptr slot for uninit arg */
1258ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
1259ae8e354cSKumar Kartikeya Dwivedi __failure __msg("potential write to dynptr at off=-16")
uninit_write_into_slot(void * ctx)1260ae8e354cSKumar Kartikeya Dwivedi int uninit_write_into_slot(void *ctx)
1261ae8e354cSKumar Kartikeya Dwivedi {
1262ae8e354cSKumar Kartikeya Dwivedi 	struct {
1263ae8e354cSKumar Kartikeya Dwivedi 		char buf[64];
1264ae8e354cSKumar Kartikeya Dwivedi 		struct bpf_dynptr ptr;
1265ae8e354cSKumar Kartikeya Dwivedi 	} data;
1266ae8e354cSKumar Kartikeya Dwivedi 
1267ae8e354cSKumar Kartikeya Dwivedi 	bpf_ringbuf_reserve_dynptr(&ringbuf, 80, 0, &data.ptr);
1268ae8e354cSKumar Kartikeya Dwivedi 	/* this should fail */
1269ae8e354cSKumar Kartikeya Dwivedi 	bpf_get_current_comm(data.buf, 80);
1270ae8e354cSKumar Kartikeya Dwivedi 
1271ae8e354cSKumar Kartikeya Dwivedi 	return 0;
1272ae8e354cSKumar Kartikeya Dwivedi }
1273ae8e354cSKumar Kartikeya Dwivedi 
1274cfa7b011SJoanne Koong /* Only supported prog type can create xdp-type dynptrs */
1275cfa7b011SJoanne Koong SEC("?raw_tp")
1276cfa7b011SJoanne Koong __failure __msg("calling kernel function bpf_dynptr_from_xdp is not allowed")
xdp_invalid_ctx(void * ctx)1277cfa7b011SJoanne Koong int xdp_invalid_ctx(void *ctx)
1278cfa7b011SJoanne Koong {
1279cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1280cfa7b011SJoanne Koong 
1281cfa7b011SJoanne Koong 	/* this should fail */
1282cfa7b011SJoanne Koong 	bpf_dynptr_from_xdp(ctx, 0, &ptr);
1283cfa7b011SJoanne Koong 
1284cfa7b011SJoanne Koong 	return 0;
1285cfa7b011SJoanne Koong }
1286cfa7b011SJoanne Koong 
1287cfa7b011SJoanne Koong __u32 hdr_size = sizeof(struct ethhdr);
1288cfa7b011SJoanne Koong /* Can't pass in variable-sized len to bpf_dynptr_slice */
1289cfa7b011SJoanne Koong SEC("?tc")
1290cfa7b011SJoanne Koong __failure __msg("unbounded memory access")
dynptr_slice_var_len1(struct __sk_buff * skb)1291cfa7b011SJoanne Koong int dynptr_slice_var_len1(struct __sk_buff *skb)
1292cfa7b011SJoanne Koong {
1293cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1294cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1295cfa7b011SJoanne Koong 	char buffer[sizeof(*hdr)] = {};
1296cfa7b011SJoanne Koong 
1297cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1298cfa7b011SJoanne Koong 
1299cfa7b011SJoanne Koong 	/* this should fail */
1300cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice(&ptr, 0, buffer, hdr_size);
1301cfa7b011SJoanne Koong 	if (!hdr)
1302cfa7b011SJoanne Koong 		return SK_DROP;
1303cfa7b011SJoanne Koong 
1304cfa7b011SJoanne Koong 	return SK_PASS;
1305cfa7b011SJoanne Koong }
1306cfa7b011SJoanne Koong 
1307cfa7b011SJoanne Koong /* Can't pass in variable-sized len to bpf_dynptr_slice */
1308cfa7b011SJoanne Koong SEC("?tc")
1309cfa7b011SJoanne Koong __failure __msg("must be a known constant")
dynptr_slice_var_len2(struct __sk_buff * skb)1310cfa7b011SJoanne Koong int dynptr_slice_var_len2(struct __sk_buff *skb)
1311cfa7b011SJoanne Koong {
1312cfa7b011SJoanne Koong 	char buffer[sizeof(struct ethhdr)] = {};
1313cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1314cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1315cfa7b011SJoanne Koong 
1316cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1317cfa7b011SJoanne Koong 
1318cfa7b011SJoanne Koong 	if (hdr_size <= sizeof(buffer)) {
1319cfa7b011SJoanne Koong 		/* this should fail */
1320cfa7b011SJoanne Koong 		hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, hdr_size);
1321cfa7b011SJoanne Koong 		if (!hdr)
1322cfa7b011SJoanne Koong 			return SK_DROP;
1323cfa7b011SJoanne Koong 		hdr->h_proto = 12;
1324cfa7b011SJoanne Koong 	}
1325cfa7b011SJoanne Koong 
1326cfa7b011SJoanne Koong 	return SK_PASS;
1327cfa7b011SJoanne Koong }
1328cfa7b011SJoanne Koong 
callback(__u32 index,void * data)1329ae8e354cSKumar Kartikeya Dwivedi static int callback(__u32 index, void *data)
1330ae8e354cSKumar Kartikeya Dwivedi {
1331ae8e354cSKumar Kartikeya Dwivedi         *(__u32 *)data = 123;
1332ae8e354cSKumar Kartikeya Dwivedi 
1333ae8e354cSKumar Kartikeya Dwivedi         return 0;
1334ae8e354cSKumar Kartikeya Dwivedi }
1335ae8e354cSKumar Kartikeya Dwivedi 
1336ae8e354cSKumar Kartikeya Dwivedi /* If the dynptr is written into in a callback function, its data
1337ae8e354cSKumar Kartikeya Dwivedi  * slices should be invalidated as well.
1338ae8e354cSKumar Kartikeya Dwivedi  */
1339ae8e354cSKumar Kartikeya Dwivedi SEC("?raw_tp")
1340ae8e354cSKumar Kartikeya Dwivedi __failure __msg("invalid mem access 'scalar'")
invalid_data_slices(void * ctx)1341ae8e354cSKumar Kartikeya Dwivedi int invalid_data_slices(void *ctx)
1342ae8e354cSKumar Kartikeya Dwivedi {
1343ae8e354cSKumar Kartikeya Dwivedi 	struct bpf_dynptr ptr;
1344ae8e354cSKumar Kartikeya Dwivedi 	__u32 *slice;
1345ae8e354cSKumar Kartikeya Dwivedi 
1346ae8e354cSKumar Kartikeya Dwivedi 	if (get_map_val_dynptr(&ptr))
1347ae8e354cSKumar Kartikeya Dwivedi 		return 0;
1348ae8e354cSKumar Kartikeya Dwivedi 
1349ae8e354cSKumar Kartikeya Dwivedi 	slice = bpf_dynptr_data(&ptr, 0, sizeof(__u32));
1350ae8e354cSKumar Kartikeya Dwivedi 	if (!slice)
1351ae8e354cSKumar Kartikeya Dwivedi 		return 0;
1352ae8e354cSKumar Kartikeya Dwivedi 
1353ae8e354cSKumar Kartikeya Dwivedi 	bpf_loop(10, callback, &ptr, 0);
1354ae8e354cSKumar Kartikeya Dwivedi 
1355ae8e354cSKumar Kartikeya Dwivedi 	/* this should fail */
1356ae8e354cSKumar Kartikeya Dwivedi 	*slice = 1;
1357ae8e354cSKumar Kartikeya Dwivedi 
1358ae8e354cSKumar Kartikeya Dwivedi 	return 0;
1359ae8e354cSKumar Kartikeya Dwivedi }
1360cfa7b011SJoanne Koong 
1361cfa7b011SJoanne Koong /* Program types that don't allow writes to packet data should fail if
1362cfa7b011SJoanne Koong  * bpf_dynptr_slice_rdwr is called
1363cfa7b011SJoanne Koong  */
1364cfa7b011SJoanne Koong SEC("cgroup_skb/ingress")
1365cfa7b011SJoanne Koong __failure __msg("the prog does not allow writes to packet data")
invalid_slice_rdwr_rdonly(struct __sk_buff * skb)1366cfa7b011SJoanne Koong int invalid_slice_rdwr_rdonly(struct __sk_buff *skb)
1367cfa7b011SJoanne Koong {
1368cfa7b011SJoanne Koong 	char buffer[sizeof(struct ethhdr)] = {};
1369cfa7b011SJoanne Koong 	struct bpf_dynptr ptr;
1370cfa7b011SJoanne Koong 	struct ethhdr *hdr;
1371cfa7b011SJoanne Koong 
1372cfa7b011SJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1373cfa7b011SJoanne Koong 
1374cfa7b011SJoanne Koong 	/* this should fail since cgroup_skb doesn't allow
1375cfa7b011SJoanne Koong 	 * changing packet data
1376cfa7b011SJoanne Koong 	 */
1377cfa7b011SJoanne Koong 	hdr = bpf_dynptr_slice_rdwr(&ptr, 0, buffer, sizeof(buffer));
1378c8ed6685SAndrii Nakryiko 	__sink(hdr);
1379cfa7b011SJoanne Koong 
1380cfa7b011SJoanne Koong 	return 0;
1381cfa7b011SJoanne Koong }
1382d911ba7cSJoanne Koong 
1383d911ba7cSJoanne Koong /* bpf_dynptr_adjust can only be called on initialized dynptrs */
1384d911ba7cSJoanne Koong SEC("?raw_tp")
1385d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #1")
dynptr_adjust_invalid(void * ctx)1386d911ba7cSJoanne Koong int dynptr_adjust_invalid(void *ctx)
1387d911ba7cSJoanne Koong {
1388d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1389d911ba7cSJoanne Koong 
1390d911ba7cSJoanne Koong 	/* this should fail */
1391d911ba7cSJoanne Koong 	bpf_dynptr_adjust(&ptr, 1, 2);
1392d911ba7cSJoanne Koong 
1393d911ba7cSJoanne Koong 	return 0;
1394d911ba7cSJoanne Koong }
1395d911ba7cSJoanne Koong 
1396d911ba7cSJoanne Koong /* bpf_dynptr_is_null can only be called on initialized dynptrs */
1397d911ba7cSJoanne Koong SEC("?raw_tp")
1398d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #1")
dynptr_is_null_invalid(void * ctx)1399d911ba7cSJoanne Koong int dynptr_is_null_invalid(void *ctx)
1400d911ba7cSJoanne Koong {
1401d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1402d911ba7cSJoanne Koong 
1403d911ba7cSJoanne Koong 	/* this should fail */
1404d911ba7cSJoanne Koong 	bpf_dynptr_is_null(&ptr);
1405d911ba7cSJoanne Koong 
1406d911ba7cSJoanne Koong 	return 0;
1407d911ba7cSJoanne Koong }
1408d911ba7cSJoanne Koong 
1409d911ba7cSJoanne Koong /* bpf_dynptr_is_rdonly can only be called on initialized dynptrs */
1410d911ba7cSJoanne Koong SEC("?raw_tp")
1411d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #1")
dynptr_is_rdonly_invalid(void * ctx)1412d911ba7cSJoanne Koong int dynptr_is_rdonly_invalid(void *ctx)
1413d911ba7cSJoanne Koong {
1414d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1415d911ba7cSJoanne Koong 
1416d911ba7cSJoanne Koong 	/* this should fail */
1417d911ba7cSJoanne Koong 	bpf_dynptr_is_rdonly(&ptr);
1418d911ba7cSJoanne Koong 
1419d911ba7cSJoanne Koong 	return 0;
1420d911ba7cSJoanne Koong }
1421d911ba7cSJoanne Koong 
1422d911ba7cSJoanne Koong /* bpf_dynptr_size can only be called on initialized dynptrs */
1423d911ba7cSJoanne Koong SEC("?raw_tp")
1424d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #1")
dynptr_size_invalid(void * ctx)1425d911ba7cSJoanne Koong int dynptr_size_invalid(void *ctx)
1426d911ba7cSJoanne Koong {
1427d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1428d911ba7cSJoanne Koong 
1429d911ba7cSJoanne Koong 	/* this should fail */
1430d911ba7cSJoanne Koong 	bpf_dynptr_size(&ptr);
1431d911ba7cSJoanne Koong 
1432d911ba7cSJoanne Koong 	return 0;
1433d911ba7cSJoanne Koong }
1434d911ba7cSJoanne Koong 
1435d911ba7cSJoanne Koong /* Only initialized dynptrs can be cloned */
1436d911ba7cSJoanne Koong SEC("?raw_tp")
1437d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #1")
clone_invalid1(void * ctx)1438d911ba7cSJoanne Koong int clone_invalid1(void *ctx)
1439d911ba7cSJoanne Koong {
1440d911ba7cSJoanne Koong 	struct bpf_dynptr ptr1;
1441d911ba7cSJoanne Koong 	struct bpf_dynptr ptr2;
1442d911ba7cSJoanne Koong 
1443d911ba7cSJoanne Koong 	/* this should fail */
1444d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr1, &ptr2);
1445d911ba7cSJoanne Koong 
1446d911ba7cSJoanne Koong 	return 0;
1447d911ba7cSJoanne Koong }
1448d911ba7cSJoanne Koong 
1449d911ba7cSJoanne Koong /* Can't overwrite an existing dynptr when cloning */
1450d911ba7cSJoanne Koong SEC("?xdp")
1451d911ba7cSJoanne Koong __failure __msg("cannot overwrite referenced dynptr")
clone_invalid2(struct xdp_md * xdp)1452d911ba7cSJoanne Koong int clone_invalid2(struct xdp_md *xdp)
1453d911ba7cSJoanne Koong {
1454d911ba7cSJoanne Koong 	struct bpf_dynptr ptr1;
1455d911ba7cSJoanne Koong 	struct bpf_dynptr clone;
1456d911ba7cSJoanne Koong 
1457d911ba7cSJoanne Koong 	bpf_dynptr_from_xdp(xdp, 0, &ptr1);
1458d911ba7cSJoanne Koong 
1459d911ba7cSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &clone);
1460d911ba7cSJoanne Koong 
1461d911ba7cSJoanne Koong 	/* this should fail */
1462d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr1, &clone);
1463d911ba7cSJoanne Koong 
1464d911ba7cSJoanne Koong 	bpf_ringbuf_submit_dynptr(&clone, 0);
1465d911ba7cSJoanne Koong 
1466d911ba7cSJoanne Koong 	return 0;
1467d911ba7cSJoanne Koong }
1468d911ba7cSJoanne Koong 
1469d911ba7cSJoanne Koong /* Invalidating a dynptr should invalidate its clones */
1470d911ba7cSJoanne Koong SEC("?raw_tp")
1471d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #3")
clone_invalidate1(void * ctx)1472d911ba7cSJoanne Koong int clone_invalidate1(void *ctx)
1473d911ba7cSJoanne Koong {
1474d911ba7cSJoanne Koong 	struct bpf_dynptr clone;
1475d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1476d911ba7cSJoanne Koong 	char read_data[64];
1477d911ba7cSJoanne Koong 
1478d911ba7cSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1479d911ba7cSJoanne Koong 
1480d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone);
1481d911ba7cSJoanne Koong 
1482d911ba7cSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
1483d911ba7cSJoanne Koong 
1484d911ba7cSJoanne Koong 	/* this should fail */
1485d911ba7cSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), &clone, 0, 0);
1486d911ba7cSJoanne Koong 
1487d911ba7cSJoanne Koong 	return 0;
1488d911ba7cSJoanne Koong }
1489d911ba7cSJoanne Koong 
1490d911ba7cSJoanne Koong /* Invalidating a dynptr should invalidate its parent */
1491d911ba7cSJoanne Koong SEC("?raw_tp")
1492d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #3")
clone_invalidate2(void * ctx)1493d911ba7cSJoanne Koong int clone_invalidate2(void *ctx)
1494d911ba7cSJoanne Koong {
1495d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1496d911ba7cSJoanne Koong 	struct bpf_dynptr clone;
1497d911ba7cSJoanne Koong 	char read_data[64];
1498d911ba7cSJoanne Koong 
1499d911ba7cSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1500d911ba7cSJoanne Koong 
1501d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone);
1502d911ba7cSJoanne Koong 
1503d911ba7cSJoanne Koong 	bpf_ringbuf_submit_dynptr(&clone, 0);
1504d911ba7cSJoanne Koong 
1505d911ba7cSJoanne Koong 	/* this should fail */
1506d911ba7cSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
1507d911ba7cSJoanne Koong 
1508d911ba7cSJoanne Koong 	return 0;
1509d911ba7cSJoanne Koong }
1510d911ba7cSJoanne Koong 
1511d911ba7cSJoanne Koong /* Invalidating a dynptr should invalidate its siblings */
1512d911ba7cSJoanne Koong SEC("?raw_tp")
1513d911ba7cSJoanne Koong __failure __msg("Expected an initialized dynptr as arg #3")
clone_invalidate3(void * ctx)1514d911ba7cSJoanne Koong int clone_invalidate3(void *ctx)
1515d911ba7cSJoanne Koong {
1516d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1517d911ba7cSJoanne Koong 	struct bpf_dynptr clone1;
1518d911ba7cSJoanne Koong 	struct bpf_dynptr clone2;
1519d911ba7cSJoanne Koong 	char read_data[64];
1520d911ba7cSJoanne Koong 
1521d911ba7cSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1522d911ba7cSJoanne Koong 
1523d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone1);
1524d911ba7cSJoanne Koong 
1525d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone2);
1526d911ba7cSJoanne Koong 
1527d911ba7cSJoanne Koong 	bpf_ringbuf_submit_dynptr(&clone2, 0);
1528d911ba7cSJoanne Koong 
1529d911ba7cSJoanne Koong 	/* this should fail */
1530d911ba7cSJoanne Koong 	bpf_dynptr_read(read_data, sizeof(read_data), &clone1, 0, 0);
1531d911ba7cSJoanne Koong 
1532d911ba7cSJoanne Koong 	return 0;
1533d911ba7cSJoanne Koong }
1534d911ba7cSJoanne Koong 
1535d911ba7cSJoanne Koong /* Invalidating a dynptr should invalidate any data slices
1536d911ba7cSJoanne Koong  * of its clones
1537d911ba7cSJoanne Koong  */
1538d911ba7cSJoanne Koong SEC("?raw_tp")
1539d911ba7cSJoanne Koong __failure __msg("invalid mem access 'scalar'")
clone_invalidate4(void * ctx)1540d911ba7cSJoanne Koong int clone_invalidate4(void *ctx)
1541d911ba7cSJoanne Koong {
1542d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1543d911ba7cSJoanne Koong 	struct bpf_dynptr clone;
1544d911ba7cSJoanne Koong 	int *data;
1545d911ba7cSJoanne Koong 
1546d911ba7cSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1547d911ba7cSJoanne Koong 
1548d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone);
1549d911ba7cSJoanne Koong 	data = bpf_dynptr_data(&clone, 0, sizeof(val));
1550d911ba7cSJoanne Koong 	if (!data)
1551d911ba7cSJoanne Koong 		return 0;
1552d911ba7cSJoanne Koong 
1553d911ba7cSJoanne Koong 	bpf_ringbuf_submit_dynptr(&ptr, 0);
1554d911ba7cSJoanne Koong 
1555d911ba7cSJoanne Koong 	/* this should fail */
1556d911ba7cSJoanne Koong 	*data = 123;
1557d911ba7cSJoanne Koong 
1558d911ba7cSJoanne Koong 	return 0;
1559d911ba7cSJoanne Koong }
1560d911ba7cSJoanne Koong 
1561d911ba7cSJoanne Koong /* Invalidating a dynptr should invalidate any data slices
1562d911ba7cSJoanne Koong  * of its parent
1563d911ba7cSJoanne Koong  */
1564d911ba7cSJoanne Koong SEC("?raw_tp")
1565d911ba7cSJoanne Koong __failure __msg("invalid mem access 'scalar'")
clone_invalidate5(void * ctx)1566d911ba7cSJoanne Koong int clone_invalidate5(void *ctx)
1567d911ba7cSJoanne Koong {
1568d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1569d911ba7cSJoanne Koong 	struct bpf_dynptr clone;
1570d911ba7cSJoanne Koong 	int *data;
1571d911ba7cSJoanne Koong 
1572d911ba7cSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1573d911ba7cSJoanne Koong 	data = bpf_dynptr_data(&ptr, 0, sizeof(val));
1574d911ba7cSJoanne Koong 	if (!data)
1575d911ba7cSJoanne Koong 		return 0;
1576d911ba7cSJoanne Koong 
1577d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone);
1578d911ba7cSJoanne Koong 
1579d911ba7cSJoanne Koong 	bpf_ringbuf_submit_dynptr(&clone, 0);
1580d911ba7cSJoanne Koong 
1581d911ba7cSJoanne Koong 	/* this should fail */
1582d911ba7cSJoanne Koong 	*data = 123;
1583d911ba7cSJoanne Koong 
1584d911ba7cSJoanne Koong 	return 0;
1585d911ba7cSJoanne Koong }
1586d911ba7cSJoanne Koong 
1587d911ba7cSJoanne Koong /* Invalidating a dynptr should invalidate any data slices
1588d911ba7cSJoanne Koong  * of its sibling
1589d911ba7cSJoanne Koong  */
1590d911ba7cSJoanne Koong SEC("?raw_tp")
1591d911ba7cSJoanne Koong __failure __msg("invalid mem access 'scalar'")
clone_invalidate6(void * ctx)1592d911ba7cSJoanne Koong int clone_invalidate6(void *ctx)
1593d911ba7cSJoanne Koong {
1594d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1595d911ba7cSJoanne Koong 	struct bpf_dynptr clone1;
1596d911ba7cSJoanne Koong 	struct bpf_dynptr clone2;
1597d911ba7cSJoanne Koong 	int *data;
1598d911ba7cSJoanne Koong 
1599d911ba7cSJoanne Koong 	bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
1600d911ba7cSJoanne Koong 
1601d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone1);
1602d911ba7cSJoanne Koong 
1603d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone2);
1604d911ba7cSJoanne Koong 
1605d911ba7cSJoanne Koong 	data = bpf_dynptr_data(&clone1, 0, sizeof(val));
1606d911ba7cSJoanne Koong 	if (!data)
1607d911ba7cSJoanne Koong 		return 0;
1608d911ba7cSJoanne Koong 
1609d911ba7cSJoanne Koong 	bpf_ringbuf_submit_dynptr(&clone2, 0);
1610d911ba7cSJoanne Koong 
1611d911ba7cSJoanne Koong 	/* this should fail */
1612d911ba7cSJoanne Koong 	*data = 123;
1613d911ba7cSJoanne Koong 
1614d911ba7cSJoanne Koong 	return 0;
1615d911ba7cSJoanne Koong }
1616d911ba7cSJoanne Koong 
1617d911ba7cSJoanne Koong /* A skb clone's data slices should be invalid anytime packet data changes */
1618d911ba7cSJoanne Koong SEC("?tc")
1619d911ba7cSJoanne Koong __failure __msg("invalid mem access 'scalar'")
clone_skb_packet_data(struct __sk_buff * skb)1620d911ba7cSJoanne Koong int clone_skb_packet_data(struct __sk_buff *skb)
1621d911ba7cSJoanne Koong {
1622d911ba7cSJoanne Koong 	char buffer[sizeof(__u32)] = {};
1623d911ba7cSJoanne Koong 	struct bpf_dynptr clone;
1624d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1625d911ba7cSJoanne Koong 	__u32 *data;
1626d911ba7cSJoanne Koong 
1627d911ba7cSJoanne Koong 	bpf_dynptr_from_skb(skb, 0, &ptr);
1628d911ba7cSJoanne Koong 
1629d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone);
1630d911ba7cSJoanne Koong 	data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));
1631d911ba7cSJoanne Koong 	if (!data)
1632d911ba7cSJoanne Koong 		return XDP_DROP;
1633d911ba7cSJoanne Koong 
1634d911ba7cSJoanne Koong 	if (bpf_skb_pull_data(skb, skb->len))
1635d911ba7cSJoanne Koong 		return SK_DROP;
1636d911ba7cSJoanne Koong 
1637d911ba7cSJoanne Koong 	/* this should fail */
1638d911ba7cSJoanne Koong 	*data = 123;
1639d911ba7cSJoanne Koong 
1640d911ba7cSJoanne Koong 	return 0;
1641d911ba7cSJoanne Koong }
1642d911ba7cSJoanne Koong 
1643d911ba7cSJoanne Koong /* A xdp clone's data slices should be invalid anytime packet data changes */
1644d911ba7cSJoanne Koong SEC("?xdp")
1645d911ba7cSJoanne Koong __failure __msg("invalid mem access 'scalar'")
clone_xdp_packet_data(struct xdp_md * xdp)1646d911ba7cSJoanne Koong int clone_xdp_packet_data(struct xdp_md *xdp)
1647d911ba7cSJoanne Koong {
1648d911ba7cSJoanne Koong 	char buffer[sizeof(__u32)] = {};
1649d911ba7cSJoanne Koong 	struct bpf_dynptr clone;
1650d911ba7cSJoanne Koong 	struct bpf_dynptr ptr;
1651d911ba7cSJoanne Koong 	struct ethhdr *hdr;
1652d911ba7cSJoanne Koong 	__u32 *data;
1653d911ba7cSJoanne Koong 
1654d911ba7cSJoanne Koong 	bpf_dynptr_from_xdp(xdp, 0, &ptr);
1655d911ba7cSJoanne Koong 
1656d911ba7cSJoanne Koong 	bpf_dynptr_clone(&ptr, &clone);
1657d911ba7cSJoanne Koong 	data = bpf_dynptr_slice_rdwr(&clone, 0, buffer, sizeof(buffer));
1658d911ba7cSJoanne Koong 	if (!data)
1659d911ba7cSJoanne Koong 		return XDP_DROP;
1660d911ba7cSJoanne Koong 
1661d911ba7cSJoanne Koong 	if (bpf_xdp_adjust_head(xdp, 0 - (int)sizeof(*hdr)))
1662d911ba7cSJoanne Koong 		return XDP_DROP;
1663d911ba7cSJoanne Koong 
1664d911ba7cSJoanne Koong 	/* this should fail */
1665d911ba7cSJoanne Koong 	*data = 123;
1666d911ba7cSJoanne Koong 
1667d911ba7cSJoanne Koong 	return 0;
1668d911ba7cSJoanne Koong }
16693881fdfeSDaniel Rosenberg 
16703881fdfeSDaniel Rosenberg /* Buffers that are provided must be sufficiently long */
16713881fdfeSDaniel Rosenberg SEC("?cgroup_skb/egress")
16723881fdfeSDaniel Rosenberg __failure __msg("memory, len pair leads to invalid memory access")
test_dynptr_skb_small_buff(struct __sk_buff * skb)16733881fdfeSDaniel Rosenberg int test_dynptr_skb_small_buff(struct __sk_buff *skb)
16743881fdfeSDaniel Rosenberg {
16753881fdfeSDaniel Rosenberg 	struct bpf_dynptr ptr;
16763881fdfeSDaniel Rosenberg 	char buffer[8] = {};
16773881fdfeSDaniel Rosenberg 	__u64 *data;
16783881fdfeSDaniel Rosenberg 
16793881fdfeSDaniel Rosenberg 	if (bpf_dynptr_from_skb(skb, 0, &ptr)) {
16803881fdfeSDaniel Rosenberg 		err = 1;
16813881fdfeSDaniel Rosenberg 		return 1;
16823881fdfeSDaniel Rosenberg 	}
16833881fdfeSDaniel Rosenberg 
16843881fdfeSDaniel Rosenberg 	/* This may return NULL. SKB may require a buffer */
16853881fdfeSDaniel Rosenberg 	data = bpf_dynptr_slice(&ptr, 0, buffer, 9);
16863881fdfeSDaniel Rosenberg 
16873881fdfeSDaniel Rosenberg 	return !!data;
16883881fdfeSDaniel Rosenberg }
1689