[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH net-next v4 09/15] net: skbuff: reject data_len > len in copy_and_csum_dev



skb_headlen() is len - data_len in unsigned arithmetic, so it underflows
to about 4GB for an skb whose data_len is bigger than its len.
skb_copy_and_csum_dev() compares the checksum start against
skb_headlen(), so its checks don't catch such an skb:

 - Without CHECKSUM_PARTIAL the checksum start is skb_headlen() itself.
   On 64-bit the 4GB value becomes the length of the linear copy.
 - With CHECKSUM_PARTIAL any checksum start below len passes, whatever
   the linear area really holds.

The BUG_ON() that commit 56453199d28f ("net: skbuff: don't BUG() on a
bad csum_start in skb_copy_and_csum_dev()") replaced compared against
the same value, so this isn't new.  No path is known to build such an
skb.

Check for data_len > len before anything uses skb_headlen(), and zero
the frame.

Link: 
https://lore.kernel.org/all/179273112823.3134.12241973533522574538@xxxxxxxxxx/
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
 net/core/skbuff.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 2c246f563555..b017c9f861fe 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4165,6 +4165,15 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 
*to)
        __wsum csum;
        long csstart;
 
+       /* skb_headlen() underflows if data_len is bigger than len, and then
+        * the checks below don't bound the copy from the linear area.
+        */
+       if (unlikely(skb->data_len > skb->len)) {
+               DEBUG_NET_WARN_ON_ONCE(1);
+               memset(to, 0, skb->len);
+               return;
+       }
+
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                csstart = skb_checksum_start_offset(skb);
        else

-- 
2.55.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.