mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
net: skbuff: remove the BUG_ON()s from skb_shift()
skb_shift() has two BUG_ON()s. The first fires if the caller asks to shift more than @skb holds. Nothing has been touched yet, and returning 0 already means "shifted nothing", which the TCP callers handle by falling back. Return 0, with a DEBUG_NET_WARN_ON_ONCE() for debug kernels. The second fires if the frags run out before @shiftlen does, but it only checks after the shift has been committed to both skbs, when there's nothing left to back out to. The loop that builds the new frag layout only writes @tgt's frag slots past its nr_frags, and the one branch that modifies @skb's frags also finishes the shift. So if the loop ends with bytes still left to shift, nothing visible has changed yet. That's the same state the MAX_SKB_FRAGS bail-out inside the loop returns 0 from. Move the check up to just before the commit and return 0 there the same way. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Link: https://patch.msgid.link/20261007-b4-skbuff-bug-on-v2-8-b9a5f732895b@toxicpanda.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
433380f5ab
commit
e6974aad4b
|
|
@ -4335,7 +4335,10 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
|
|||
int from, to, merge, todo;
|
||||
skb_frag_t *fragfrom, *fragto;
|
||||
|
||||
BUG_ON(shiftlen > skb->len);
|
||||
if (unlikely(shiftlen > skb->len)) {
|
||||
DEBUG_NET_WARN_ON_ONCE(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (skb_headlen(skb))
|
||||
return 0;
|
||||
|
|
@ -4415,6 +4418,14 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
|
|||
}
|
||||
}
|
||||
|
||||
/* The frags ran out before shiftlen did. Nothing has been committed
|
||||
* yet, so back out.
|
||||
*/
|
||||
if (unlikely(todo > 0)) {
|
||||
DEBUG_NET_WARN_ON_ONCE(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ready to "commit" this state change to tgt */
|
||||
skb_shinfo(tgt)->nr_frags = to;
|
||||
|
||||
|
|
@ -4432,8 +4443,6 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen)
|
|||
skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++];
|
||||
skb_shinfo(skb)->nr_frags = to;
|
||||
|
||||
BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags);
|
||||
|
||||
onlymerged:
|
||||
/* Most likely the tgt won't ever need its checksum anymore, skb on
|
||||
* the other hand might need it if it needs to be resent
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user