mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
net: fix frag_list leak in skb_segment_list() error path
skb_segment_list() detaches the frag_list from the head skb and moves
its members one by one to the skb->next chain. On error, err_linearize
frees that chain with kfree_skb_list(skb->next), relying on the members
not yet processed to still be linked after the current one.
This does not hold when the current member was shared: it is replaced
by skb_clone(), and __skb_clone() clears ->next. If __skb_linearize()
then fails on that clone, the remaining members are no longer reachable
from skb->next nor from skb_shinfo(skb)->frag_list, and they leak.
The skb_shared() error branch already relinks nskb->next to list_skb
before jumping to err_linearize. Do it unconditionally right after nskb
is added to the chain, so every error exit sees the remaining members.
On the last member list_skb is NULL, which still terminates the chain.
Fixes: 53475c5dd8 ("net: fix use-after-free when UDP GRO with shared fraglist")
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Cc: Simon Polack <spolack+git@mailbox.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Wang Zhan <wang.zhan@smartx.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Link: https://patch.msgid.link/20261021161858.761205-1-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c3a1ddd5e1
commit
546daf3444
|
|
@ -4782,10 +4782,13 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
|
|||
else
|
||||
tail->next = nskb;
|
||||
|
||||
if (unlikely(err)) {
|
||||
nskb->next = list_skb;
|
||||
/* nskb may be a clone with a NULL ->next: keep the remaining
|
||||
* members linked so that err_linearize frees them.
|
||||
*/
|
||||
nskb->next = list_skb;
|
||||
|
||||
if (unlikely(err))
|
||||
goto err_linearize;
|
||||
}
|
||||
|
||||
tail = nskb;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user