Skip to content

Commit 7e28155

Browse files
committed
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>
1 parent 8ae7085 commit 7e28155

2 files changed

Lines changed: 83 additions & 0 deletions

File tree

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "bpf_qdisc_fail__invalid_dynptr.skel.h"
1212
#include "bpf_qdisc_fail__invalid_dynptr_slice.skel.h"
1313
#include "bpf_qdisc_fail__invalid_dynptr_cross_frame.skel.h"
14+
#include "bpf_qdisc_dynptr_clone.skel.h"
1415

1516
#define LO_IFINDEX 1
1617

@@ -186,6 +187,17 @@ static void test_invalid_dynptr_cross_frame(void)
186187
bpf_qdisc_fail__invalid_dynptr_cross_frame__destroy(skel);
187188
}
188189

190+
static void test_dynptr_clone(void)
191+
{
192+
struct bpf_qdisc_dynptr_clone *skel;
193+
194+
skel = bpf_qdisc_dynptr_clone__open_and_load();
195+
if (!ASSERT_OK_PTR(skel, "bpf_qdisc_dynptr_clone__open_and_load"))
196+
return;
197+
198+
bpf_qdisc_dynptr_clone__destroy(skel);
199+
}
200+
189201
static int get_default_qdisc(char *qdisc_name)
190202
{
191203
FILE *f;
@@ -259,6 +271,8 @@ void test_ns_bpf_qdisc(void)
259271
test_invalid_dynptr_slice();
260272
if (test__start_subtest("invalid_dynptr_cross_frame"))
261273
test_invalid_dynptr_cross_frame();
274+
if (test__start_subtest("dynptr_clone"))
275+
test_dynptr_clone();
262276
}
263277

264278
void serial_test_bpf_qdisc_default(void)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <vmlinux.h>
4+
#include "bpf_experimental.h"
5+
#include "bpf_qdisc_common.h"
6+
7+
char _license[] SEC("license") = "GPL";
8+
9+
int proto;
10+
11+
SEC("struct_ops")
12+
int BPF_PROG(bpf_qdisc_test_enqueue, struct sk_buff *skb, struct Qdisc *sch,
13+
struct bpf_sk_buff_ptr *to_free)
14+
{
15+
struct bpf_dynptr ptr, ptr_clone;
16+
struct ethhdr *hdr;
17+
18+
bpf_dynptr_from_skb((struct __sk_buff *)skb, 0, &ptr);
19+
20+
bpf_dynptr_clone(&ptr, &ptr_clone);
21+
22+
hdr = bpf_dynptr_slice(&ptr_clone, 0, NULL, sizeof(*hdr));
23+
if (!hdr) {
24+
bpf_qdisc_skb_drop(skb, to_free);
25+
return NET_XMIT_DROP;
26+
}
27+
28+
*(int *)&ptr = 0;
29+
30+
proto = hdr->h_proto;
31+
32+
bpf_qdisc_skb_drop(skb, to_free);
33+
34+
return NET_XMIT_DROP;
35+
}
36+
37+
SEC("struct_ops")
38+
struct sk_buff *BPF_PROG(bpf_qdisc_test_dequeue, struct Qdisc *sch)
39+
{
40+
return NULL;
41+
}
42+
43+
SEC("struct_ops")
44+
int BPF_PROG(bpf_qdisc_test_init, struct Qdisc *sch, struct nlattr *opt,
45+
struct netlink_ext_ack *extack)
46+
{
47+
return 0;
48+
}
49+
50+
SEC("struct_ops")
51+
void BPF_PROG(bpf_qdisc_test_reset, struct Qdisc *sch)
52+
{
53+
}
54+
55+
SEC("struct_ops")
56+
void BPF_PROG(bpf_qdisc_test_destroy, struct Qdisc *sch)
57+
{
58+
}
59+
60+
SEC(".struct_ops")
61+
struct Qdisc_ops test = {
62+
.enqueue = (void *)bpf_qdisc_test_enqueue,
63+
.dequeue = (void *)bpf_qdisc_test_dequeue,
64+
.init = (void *)bpf_qdisc_test_init,
65+
.reset = (void *)bpf_qdisc_test_reset,
66+
.destroy = (void *)bpf_qdisc_test_destroy,
67+
.id = "bpf_qdisc_test",
68+
};
69+

0 commit comments

Comments
 (0)