mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-23 12:10:10 -04:00
eth: fbnic: don't cache shinfo across skb realloc
fbnic_tx_lso() calls skb_cow_head() which may reallocate the skb
including the shared info. We can't use the pointer calculated
before the call.
BUG: KASAN: slab-use-after-free in fbnic_tx_lso.isra.0+0x668/0x8e0
Read of size 4 at addr ff110000262edd98 by task swapper/5/0
Call Trace:
fbnic_tx_lso.isra.0+0x668/0x8e0
fbnic_xmit_frame+0x622/0xba0
dev_hard_start_xmit+0xf4/0x620
Allocated by task 8653:
__alloc_skb+0x11e/0x5f0
alloc_skb_with_frags+0xcc/0x6c0
sock_alloc_send_pskb+0x327/0x3f0
__ip_append_data+0x188b/0x47a0
ip_make_skb+0x24a/0x300
udp_sendmsg+0x14d2/0x21e0
Freed by task 0:
kfree+0x123/0x5a0
pskb_expand_head+0x36c/0xfa0
fbnic_tx_lso.isra.0+0x500/0x8e0
fbnic_xmit_frame+0x622/0xba0
dev_hard_start_xmit+0xf4/0x620
sch_direct_xmit+0x25b/0x1100
The buggy address belongs to the object at ff110000262edc40
which belongs to the cache skbuff_small_head of size 640
The buggy address is located 344 bytes inside of
freed 640-byte region [ff110000262edc40, ff110000262ede
Link: https://netdev.bots.linux.dev/logs/vmksft/fbnic-qemu-dbg/results/705762/15-uso-py/stderr
Fixes: b0b0f52042 ("eth: fbnic: support TCP segmentation offload")
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Link: https://patch.msgid.link/20260625160508.3327986-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -194,16 +194,18 @@ static bool fbnic_tx_tstamp(struct sk_buff *skb)
|
||||
|
||||
static bool
|
||||
fbnic_tx_lso(struct fbnic_ring *ring, struct sk_buff *skb,
|
||||
struct skb_shared_info *shinfo, __le64 *meta,
|
||||
unsigned int *l2len, unsigned int *i3len)
|
||||
__le64 *meta, unsigned int *l2len, unsigned int *i3len)
|
||||
{
|
||||
unsigned int l3_type, l4_type, l4len, hdrlen;
|
||||
struct skb_shared_info *shinfo;
|
||||
unsigned char *l4hdr;
|
||||
__be16 payload_len;
|
||||
|
||||
if (unlikely(skb_cow_head(skb, 0)))
|
||||
return true;
|
||||
|
||||
shinfo = skb_shinfo(skb);
|
||||
|
||||
if (shinfo->gso_type & SKB_GSO_PARTIAL) {
|
||||
l3_type = FBNIC_TWD_L3_TYPE_OTHER;
|
||||
} else if (!skb->encapsulation) {
|
||||
@@ -258,7 +260,6 @@ fbnic_tx_lso(struct fbnic_ring *ring, struct sk_buff *skb,
|
||||
static bool
|
||||
fbnic_tx_offloads(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
|
||||
{
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
unsigned int l2len, i3len;
|
||||
|
||||
if (fbnic_tx_tstamp(skb))
|
||||
@@ -273,8 +274,8 @@ fbnic_tx_offloads(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
|
||||
*meta |= cpu_to_le64(FIELD_PREP(FBNIC_TWD_CSUM_OFFSET_MASK,
|
||||
skb->csum_offset / 2));
|
||||
|
||||
if (shinfo->gso_size) {
|
||||
if (fbnic_tx_lso(ring, skb, shinfo, meta, &l2len, &i3len))
|
||||
if (skb_is_gso(skb)) {
|
||||
if (fbnic_tx_lso(ring, skb, meta, &l2len, &i3len))
|
||||
return true;
|
||||
} else {
|
||||
*meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_CSO);
|
||||
|
||||
Reference in New Issue
Block a user