mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
selftests/bpf: Test using dynptr after freeing the underlying object
Make sure the verifier invalidates the dynptr and dynptr slice derived from an skb after the skb is freed. Signed-off-by: Amery Hung <ameryhung@gmail.com> Link: https://lore.kernel.org/r/20260529014936.2811085-14-ameryhung@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
3f75a757a3
commit
60c7c3b880
|
|
@ -0,0 +1,68 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <vmlinux.h>
|
||||
#include "bpf_experimental.h"
|
||||
#include "bpf_qdisc_common.h"
|
||||
#include "bpf_misc.h"
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
int proto;
|
||||
|
||||
SEC("struct_ops")
|
||||
__failure __msg("Expected an initialized dynptr as R1")
|
||||
int BPF_PROG(invalid_dynptr, struct sk_buff *skb, struct Qdisc *sch,
|
||||
struct bpf_sk_buff_ptr *to_free)
|
||||
{
|
||||
struct bpf_dynptr ptr;
|
||||
struct ethhdr *hdr;
|
||||
|
||||
bpf_dynptr_from_skb((struct __sk_buff *)skb, 0, &ptr);
|
||||
|
||||
bpf_qdisc_skb_drop(skb, to_free);
|
||||
|
||||
hdr = bpf_dynptr_slice(&ptr, 0, NULL, sizeof(*hdr));
|
||||
if (!hdr)
|
||||
return NET_XMIT_DROP;
|
||||
|
||||
proto = hdr->h_proto;
|
||||
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
struct sk_buff *BPF_PROG(bpf_qdisc_test_dequeue, struct Qdisc *sch)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
int BPF_PROG(bpf_qdisc_test_init, struct Qdisc *sch, struct nlattr *opt,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
void BPF_PROG(bpf_qdisc_test_reset, struct Qdisc *sch)
|
||||
{
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
void BPF_PROG(bpf_qdisc_test_destroy, struct Qdisc *sch)
|
||||
{
|
||||
}
|
||||
|
||||
SEC(".struct_ops")
|
||||
struct Qdisc_ops test = {
|
||||
.enqueue = (void *)invalid_dynptr,
|
||||
.dequeue = (void *)bpf_qdisc_test_dequeue,
|
||||
.init = (void *)bpf_qdisc_test_init,
|
||||
.reset = (void *)bpf_qdisc_test_reset,
|
||||
.destroy = (void *)bpf_qdisc_test_destroy,
|
||||
.id = "bpf_qdisc_test",
|
||||
};
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <vmlinux.h>
|
||||
#include "bpf_experimental.h"
|
||||
#include "bpf_qdisc_common.h"
|
||||
#include "bpf_misc.h"
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
int proto;
|
||||
|
||||
static __noinline int free_skb(struct sk_buff *skb)
|
||||
{
|
||||
bpf_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__failure __msg("invalid mem access 'scalar'")
|
||||
int BPF_PROG(invalid_dynptr_cross_frame, struct sk_buff *skb, struct Qdisc *sch,
|
||||
struct bpf_sk_buff_ptr *to_free)
|
||||
{
|
||||
struct bpf_dynptr ptr;
|
||||
struct ethhdr *hdr;
|
||||
|
||||
bpf_dynptr_from_skb((struct __sk_buff *)skb, 0, &ptr);
|
||||
|
||||
hdr = bpf_dynptr_slice(&ptr, 0, NULL, sizeof(*hdr));
|
||||
if (!hdr)
|
||||
return NET_XMIT_DROP;
|
||||
|
||||
free_skb(skb);
|
||||
|
||||
proto = hdr->h_proto;
|
||||
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
struct sk_buff *BPF_PROG(bpf_qdisc_test_dequeue, struct Qdisc *sch)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
int BPF_PROG(bpf_qdisc_test_init, struct Qdisc *sch, struct nlattr *opt,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
void BPF_PROG(bpf_qdisc_test_reset, struct Qdisc *sch)
|
||||
{
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
void BPF_PROG(bpf_qdisc_test_destroy, struct Qdisc *sch)
|
||||
{
|
||||
}
|
||||
|
||||
SEC(".struct_ops")
|
||||
struct Qdisc_ops test = {
|
||||
.enqueue = (void *)invalid_dynptr_cross_frame,
|
||||
.dequeue = (void *)bpf_qdisc_test_dequeue,
|
||||
.init = (void *)bpf_qdisc_test_init,
|
||||
.reset = (void *)bpf_qdisc_test_reset,
|
||||
.destroy = (void *)bpf_qdisc_test_destroy,
|
||||
.id = "bpf_qdisc_test",
|
||||
};
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <vmlinux.h>
|
||||
#include "bpf_experimental.h"
|
||||
#include "bpf_qdisc_common.h"
|
||||
#include "bpf_misc.h"
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
int proto;
|
||||
|
||||
SEC("struct_ops")
|
||||
__failure __msg("invalid mem access 'scalar'")
|
||||
int BPF_PROG(invalid_dynptr_slice, struct sk_buff *skb, struct Qdisc *sch,
|
||||
struct bpf_sk_buff_ptr *to_free)
|
||||
{
|
||||
struct bpf_dynptr ptr;
|
||||
struct ethhdr *hdr;
|
||||
|
||||
bpf_dynptr_from_skb((struct __sk_buff *)skb, 0, &ptr);
|
||||
|
||||
hdr = bpf_dynptr_slice(&ptr, 0, NULL, sizeof(*hdr));
|
||||
if (!hdr) {
|
||||
bpf_qdisc_skb_drop(skb, to_free);
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
|
||||
bpf_qdisc_skb_drop(skb, to_free);
|
||||
|
||||
proto = hdr->h_proto;
|
||||
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
struct sk_buff *BPF_PROG(bpf_qdisc_test_dequeue, struct Qdisc *sch)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
int BPF_PROG(bpf_qdisc_test_init, struct Qdisc *sch, struct nlattr *opt,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
void BPF_PROG(bpf_qdisc_test_reset, struct Qdisc *sch)
|
||||
{
|
||||
}
|
||||
|
||||
SEC("struct_ops")
|
||||
__auxiliary
|
||||
void BPF_PROG(bpf_qdisc_test_destroy, struct Qdisc *sch)
|
||||
{
|
||||
}
|
||||
|
||||
SEC(".struct_ops")
|
||||
struct Qdisc_ops test = {
|
||||
.enqueue = (void *)invalid_dynptr_slice,
|
||||
.dequeue = (void *)bpf_qdisc_test_dequeue,
|
||||
.init = (void *)bpf_qdisc_test_init,
|
||||
.reset = (void *)bpf_qdisc_test_reset,
|
||||
.destroy = (void *)bpf_qdisc_test_destroy,
|
||||
.id = "bpf_qdisc_test",
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user