Skip to content

Commit 9253206

Browse files
ameryhungAlexei Starovoitov
authored andcommitted
selftests/bpf: Test using slice after invalidating dynptr clone
The parent object of a cloned dynptr is skb not the original dynptr. Invalidate the original dynptr should not prevent the program from using the slice derived from the cloned dynptr. Signed-off-by: Amery Hung <ameryhung@gmail.com> Link: https://lore.kernel.org/r/20260529014936.2811085-12-ameryhung@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent fbcc68a commit 9253206

2 files changed

Lines changed: 82 additions & 0 deletions

File tree

tools/testing/selftests/bpf/prog_tests/bpf_qdisc.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#include "bpf_qdisc_fifo.skel.h"
99
#include "bpf_qdisc_fq.skel.h"
1010
#include "bpf_qdisc_fail__incompl_ops.skel.h"
11+
#include "bpf_qdisc_fail__invalid_dynptr.skel.h"
12+
#include "bpf_qdisc_fail__invalid_dynptr_slice.skel.h"
13+
#include "bpf_qdisc_fail__invalid_dynptr_cross_frame.skel.h"
14+
#include "bpf_qdisc_dynptr_use_after_invalidate_clone.skel.h"
1115

1216
#define LO_IFINDEX 1
1317

@@ -223,6 +227,10 @@ void test_ns_bpf_qdisc(void)
223227
test_qdisc_attach_to_non_root();
224228
if (test__start_subtest("incompl_ops"))
225229
test_incompl_ops();
230+
RUN_TESTS(bpf_qdisc_fail__invalid_dynptr);
231+
RUN_TESTS(bpf_qdisc_fail__invalid_dynptr_cross_frame);
232+
RUN_TESTS(bpf_qdisc_fail__invalid_dynptr_slice);
233+
RUN_TESTS(bpf_qdisc_dynptr_use_after_invalidate_clone);
226234
}
227235

228236
void serial_test_bpf_qdisc_default(void)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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+
int proto;
11+
12+
SEC("struct_ops")
13+
__success
14+
int BPF_PROG(dynptr_use_after_invalidate_clone, struct sk_buff *skb, struct Qdisc *sch,
15+
struct bpf_sk_buff_ptr *to_free)
16+
{
17+
struct bpf_dynptr ptr, ptr_clone;
18+
struct ethhdr *hdr;
19+
20+
bpf_dynptr_from_skb((struct __sk_buff *)skb, 0, &ptr);
21+
22+
bpf_dynptr_clone(&ptr, &ptr_clone);
23+
24+
hdr = bpf_dynptr_slice(&ptr_clone, 0, NULL, sizeof(*hdr));
25+
if (!hdr) {
26+
bpf_qdisc_skb_drop(skb, to_free);
27+
return NET_XMIT_DROP;
28+
}
29+
30+
*(int *)&ptr = 0;
31+
32+
proto = hdr->h_proto;
33+
34+
bpf_qdisc_skb_drop(skb, to_free);
35+
36+
return NET_XMIT_DROP;
37+
}
38+
39+
SEC("struct_ops")
40+
__auxiliary
41+
struct sk_buff *BPF_PROG(bpf_qdisc_test_dequeue, struct Qdisc *sch)
42+
{
43+
return NULL;
44+
}
45+
46+
SEC("struct_ops")
47+
__auxiliary
48+
int BPF_PROG(bpf_qdisc_test_init, struct Qdisc *sch, struct nlattr *opt,
49+
struct netlink_ext_ack *extack)
50+
{
51+
return 0;
52+
}
53+
54+
SEC("struct_ops")
55+
__auxiliary
56+
void BPF_PROG(bpf_qdisc_test_reset, struct Qdisc *sch)
57+
{
58+
}
59+
60+
SEC("struct_ops")
61+
__auxiliary
62+
void BPF_PROG(bpf_qdisc_test_destroy, struct Qdisc *sch)
63+
{
64+
}
65+
66+
SEC(".struct_ops")
67+
struct Qdisc_ops test = {
68+
.enqueue = (void *)dynptr_use_after_invalidate_clone,
69+
.dequeue = (void *)bpf_qdisc_test_dequeue,
70+
.init = (void *)bpf_qdisc_test_init,
71+
.reset = (void *)bpf_qdisc_test_reset,
72+
.destroy = (void *)bpf_qdisc_test_destroy,
73+
.id = "bpf_qdisc_test",
74+
};

0 commit comments

Comments
 (0)