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

[PATCH net-next v4 05/15] net: skbuff: drop hw csum if trim can't checksum tail



For a CHECKSUM_COMPLETE skb, pskb_trim_rcsum() subtracts the checksum of
the trimmed bytes from skb->csum.  It gets that checksum from
skb_checksum(), which returns 0 if the trimmed range runs into an
unreadable frag_list member or past the end of the skb.  skb->csum then
still covers the trimmed bytes.

commit 2e357f002c61 ("net: Avoid checksumming unreadable skb tail on
trim") handles an skb that is itself unreadable, but not a readable head
with an unreadable frag_list member.

Use skb_checksum_full().  When it fails, do what pskb_trim_rcsum()
already does for an unreadable skb.  Set CHECKSUM_NONE if the remaining
packet can be read, so that software checksums it, and fail the trim
with -EFAULT if it can't.

The stale skb->csum was only reproduced with a hand-built skb in a test
module.

Fixes: 65249feb6b3d ("net: add support for skbs with unreadable frags")
Fixes: 20ddd0fd2fcd ("net: skbuff: don't BUG() on leftover length in 
skb_checksum() and friends")
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
 net/core/skbuff.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 43bfaa010db7..66ba9bfa8fc7 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2821,9 +2821,23 @@ static int pskb_trim_rcsum_complete(struct sk_buff *skb, 
unsigned int len)
        int delta = skb->len - len;
 
        if (skb_frags_readable(skb)) {
-               skb->csum = csum_block_sub(skb->csum,
-                                          skb_checksum(skb, len, delta, 0),
-                                          len);
+               __wsum csum = 0;
+               int err;
+
+               if (!skb_checksum_full(skb, len, delta, &csum)) {
+                       skb->csum = csum_block_sub(skb->csum, csum, len);
+                       return 0;
+               }
+
+               /* The trimmed bytes can't be checksummed, so skb->csum can't
+                * be adjusted.  Software can checksum the remaining packet
+                * after trimming, as long as it can read it.
+                */
+               csum = 0;
+               err = skb_checksum_full(skb, 0, len, &csum);
+               if (err)
+                       return err;
+               skb->ip_summed = CHECKSUM_NONE;
                return 0;
        }
 

-- 
2.55.0




 


Rackspace

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