xref: /linux/tools/testing/selftests/bpf/progs/bpf_qdisc_fail__untrusted_write.c (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <vmlinux.h>
4 #include "bpf_experimental.h"
5 #include "bpf_qdisc_common.h"
6 #include "bpf_misc.h"
7 
8 char _license[] SEC("license") = "GPL";
9 
10 SEC("struct_ops")
11 __failure __msg("only read is supported")
BPF_PROG(untrusted_write,struct sk_buff * skb,struct Qdisc * sch,struct bpf_sk_buff_ptr * to_free)12 int BPF_PROG(untrusted_write, struct sk_buff *skb, struct Qdisc *sch,
13 	     struct bpf_sk_buff_ptr *to_free)
14 {
15 	struct Qdisc *next = sch->next_sched;
16 
17 	/*
18 	 * sch is trusted, but the walk of next_sched yields a plain
19 	 * PTR_TO_BTF_ID which may fault on a dereference. A store through
20 	 * it does not get an exception table entry, there is no probed
21 	 * store to rewrite it into, hence it has to be rejected before
22 	 * bpf_qdisc_btf_struct_access() gets to allow the write to limit.
23 	 */
24 	next->limit = 1000;
25 
26 	bpf_qdisc_skb_drop(skb, to_free);
27 	return NET_XMIT_DROP;
28 }
29 
30 SEC("struct_ops")
31 __auxiliary
BPF_PROG(bpf_qdisc_test_dequeue,struct Qdisc * sch)32 struct sk_buff *BPF_PROG(bpf_qdisc_test_dequeue, struct Qdisc *sch)
33 {
34 	return NULL;
35 }
36 
37 SEC("struct_ops")
38 __auxiliary
BPF_PROG(bpf_qdisc_test_init,struct Qdisc * sch,struct nlattr * opt,struct netlink_ext_ack * extack)39 int BPF_PROG(bpf_qdisc_test_init, struct Qdisc *sch, struct nlattr *opt,
40 	     struct netlink_ext_ack *extack)
41 {
42 	return 0;
43 }
44 
45 SEC("struct_ops")
46 __auxiliary
BPF_PROG(bpf_qdisc_test_reset,struct Qdisc * sch)47 void BPF_PROG(bpf_qdisc_test_reset, struct Qdisc *sch)
48 {
49 }
50 
51 SEC("struct_ops")
52 __auxiliary
BPF_PROG(bpf_qdisc_test_destroy,struct Qdisc * sch)53 void BPF_PROG(bpf_qdisc_test_destroy, struct Qdisc *sch)
54 {
55 }
56 
57 SEC(".struct_ops")
58 struct Qdisc_ops test = {
59 	.enqueue   = (void *)untrusted_write,
60 	.dequeue   = (void *)bpf_qdisc_test_dequeue,
61 	.init      = (void *)bpf_qdisc_test_init,
62 	.reset     = (void *)bpf_qdisc_test_reset,
63 	.destroy   = (void *)bpf_qdisc_test_destroy,
64 	.id        = "bpf_qdisc_test",
65 };
66