mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
bpf, cgroup: Keep the skb network offset signed
cgroup_skb progs see a packet from its network header. While they run,
__cgroup_bpf_run_filter_skb() moves skb->data there. It assumes that the
network header is not after skb->data. It negates skb_network_offset(skb)
and pushes skb->data by this offset. The offset is an unsigned int.
But ip6mr_cache_report() and bpf_lwt_xmit_reroute() can pass an skb that
has data before the network header. Then the offset wraps. On a 64-bit
kernel skb->data is then far below skb->head.
skb->len has 32 bits and wraps to the correct value, thus only skb->data is
wrong. A read of packet data faults or gets other memory.
Keep the offset in an int. Pull skb->data when the network header is after
it. Otherwise push it, as today.
Fixes: 3007098494 ("cgroup: add support for eBPF programs")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-15-alexei.starovoitov@gmail.com
This commit is contained in:
parent
2962329f7c
commit
3f9780d62d
|
|
@ -1790,7 +1790,7 @@ int __cgroup_bpf_run_filter_skb(struct sock *sk,
|
|||
struct sk_buff *skb,
|
||||
enum cgroup_bpf_attach_type atype)
|
||||
{
|
||||
unsigned int offset = -skb_network_offset(skb);
|
||||
int offset = skb_network_offset(skb);
|
||||
struct sock *save_sk;
|
||||
void *saved_data_end;
|
||||
struct cgroup *cgrp;
|
||||
|
|
@ -1802,7 +1802,15 @@ int __cgroup_bpf_run_filter_skb(struct sock *sk,
|
|||
cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
|
||||
save_sk = skb->sk;
|
||||
skb->sk = sk;
|
||||
__skb_push(skb, offset);
|
||||
|
||||
/*
|
||||
* The program sees the packet from its network header on, on
|
||||
* whichever side of skb->data that header lies.
|
||||
*/
|
||||
if (offset > 0)
|
||||
__skb_pull(skb, offset);
|
||||
else
|
||||
__skb_push(skb, -offset);
|
||||
|
||||
/* compute pointers for the bpf prog */
|
||||
bpf_compute_and_save_data_end(skb, &saved_data_end);
|
||||
|
|
@ -1844,7 +1852,10 @@ int __cgroup_bpf_run_filter_skb(struct sock *sk,
|
|||
ret = -EFAULT;
|
||||
}
|
||||
bpf_restore_data_end(skb, saved_data_end);
|
||||
__skb_pull(skb, offset);
|
||||
if (offset > 0)
|
||||
__skb_push(skb, offset);
|
||||
else
|
||||
__skb_pull(skb, -offset);
|
||||
skb->sk = save_sk;
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user