From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from youngberry.canonical.com ([91.189.89.112]:45773 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932440AbbJZNpB (ORCPT ); Mon, 26 Oct 2015 09:45:01 -0400 From: Luis Henriques To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com Cc: Pravin B Shelar , "David S. Miller" , Luis Henriques Subject: [PATCH 3.16.y-ckt 098/104] skbuff: Fix skb checksum partial check. Date: Mon, 26 Oct 2015 13:43:20 +0000 Message-Id: <1445867006-18048-99-git-send-email-luis.henriques@canonical.com> In-Reply-To: <1445867006-18048-1-git-send-email-luis.henriques@canonical.com> References: <1445867006-18048-1-git-send-email-luis.henriques@canonical.com> Sender: stable-owner@vger.kernel.org List-ID: 3.16.7-ckt19 -stable review patch. If anyone has any objections, please let me know. ------------------ From: Pravin B Shelar commit 31b33dfb0a144469dd805514c9e63f4993729a48 upstream. Earlier patch 6ae459bda tried to detect void ckecksum partial skb by comparing pull length to checksum offset. But it does not work for all cases since checksum-offset depends on updates to skb->data. Following patch fixes it by validating checksum start offset after skb-data pointer is updated. Negative value of checksum offset start means there is no need to checksum. Fixes: 6ae459bda ("skbuff: Fix skb checksum flag on skb pull") Reported-by: Andrew Vagin Signed-off-by: Pravin B Shelar Signed-off-by: David S. Miller Signed-off-by: Luis Henriques --- include/linux/skbuff.h | 2 +- net/core/skbuff.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index cfe9676d2e71..010bc80be91c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2439,7 +2439,7 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb, if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); else if (skb->ip_summed == CHECKSUM_PARTIAL && - skb_checksum_start_offset(skb) <= len) + skb_checksum_start_offset(skb) < 0) skb->ip_summed = CHECKSUM_NONE; } diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 167a92c896b9..a280d04a3414 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2869,11 +2869,12 @@ EXPORT_SYMBOL(skb_append_datato_frags); */ unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) { + unsigned char *data = skb->data; + BUG_ON(len > skb->len); - skb->len -= len; - BUG_ON(skb->len < skb->data_len); - skb_postpull_rcsum(skb, skb->data, len); - return skb->data += len; + __skb_pull(skb, len); + skb_postpull_rcsum(skb, data, len); + return skb->data; } EXPORT_SYMBOL_GPL(skb_pull_rcsum);