mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
Merge branch 'fix-skb-length-accounting-after-xdp-frag-adjustment'
Sun Jian says: ==================== fix skb length accounting after XDP frag adjustment This series fixes skb length accounting after an XDP program adjusts its fragment area, in both the generic XDP path (net/core/dev.c) and the veth native path (drivers/net/veth.c). When the fragment area is resized, skb->len and skb->data_len can go out of sync, and in the reproduced UDP receive path this leaked skb_shared_info contents (including a kernel pointer) to userspace while truncating real payload. ==================== Link: https://patch.msgid.link/20260804054040.613675-1-sun.jian.kdev@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
d47b06aa3e
|
|
@ -865,18 +865,24 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_rq *rq,
|
|||
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
/* check if bpf_xdp_adjust_tail was used */
|
||||
off = xdp->data_end - orig_data_end;
|
||||
if (off != 0)
|
||||
__skb_put(skb, off); /* positive on grow, negative on shrink */
|
||||
|
||||
/* XDP frag metadata (e.g. nr_frags) are updated in eBPF helpers
|
||||
* (e.g. bpf_xdp_adjust_tail), we need to update data_len here.
|
||||
* (e.g. bpf_xdp_adjust_tail). Remove the old fragment contribution
|
||||
* from skb->len before updating data_len, then add the new one back.
|
||||
*/
|
||||
if (xdp_buff_has_frags(xdp))
|
||||
skb->len -= skb->data_len;
|
||||
if (xdp_buff_has_frags(xdp)) {
|
||||
skb->data_len = skb_shinfo(skb)->xdp_frags_size;
|
||||
else
|
||||
skb->len += skb->data_len;
|
||||
} else {
|
||||
skb->data_len = 0;
|
||||
}
|
||||
|
||||
/* Synchronize the skb tail with XDP's updated linear area. */
|
||||
off = xdp->data_end - orig_data_end;
|
||||
if (off != 0) {
|
||||
skb_set_tail_pointer(skb, xdp->data_end - xdp->data);
|
||||
skb->len += off; /* positive on grow, negative on shrink */
|
||||
}
|
||||
|
||||
skb->protocol = eth_type_trans(skb, rq->dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -5517,12 +5517,16 @@ u32 bpf_prog_run_generic_xdp(struct sk_buff *skb, struct xdp_buff *xdp,
|
|||
}
|
||||
|
||||
/* XDP frag metadata (e.g. nr_frags) are updated in eBPF helpers
|
||||
* (e.g. bpf_xdp_adjust_tail), we need to update data_len here.
|
||||
* (e.g. bpf_xdp_adjust_tail). Remove the old fragment contribution
|
||||
* from skb->len before updating data_len, then add the new one back.
|
||||
*/
|
||||
if (xdp_buff_has_frags(xdp))
|
||||
skb->len -= skb->data_len;
|
||||
if (xdp_buff_has_frags(xdp)) {
|
||||
skb->data_len = skb_shinfo(skb)->xdp_frags_size;
|
||||
else
|
||||
skb->len += skb->data_len;
|
||||
} else {
|
||||
skb->data_len = 0;
|
||||
}
|
||||
|
||||
/* check if XDP changed eth hdr such SKB needs update */
|
||||
eth = (struct ethhdr *)xdp->data;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user