diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c69c3d4cc8f4..93c2f440b9ec 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -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