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