Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp2472895imj; Mon, 18 Feb 2019 06:37:41 -0800 (PST) X-Google-Smtp-Source: AHgI3IaVBiNmM+HpkIV/TD7YVIDC+VK/ApkEzNNEQEuPZLyHAUKxME+Ket+jLi9frGIlcBjkAwB+ X-Received: by 2002:a63:2882:: with SMTP id o124mr19314705pgo.446.1550500661330; Mon, 18 Feb 2019 06:37:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1550500661; cv=none; d=google.com; s=arc-20160816; b=M1GkAj645BhTTrdiLv9Sv4ncDsVQctdYzLsvmIzqqVck4uktreJmiaFp+byviA2rCC UY24c+mrhSNlomgEKuZj0JWcy++f2tE8n6/8L1Lc6qYud5invj17Imyf1beHwgl7C1T1 eFIaEK+NutVYvOhYJ3FByLZxKuUjKZEg2G2prRGN7H6tiDM6lcJL7xfh55neu6Ewo4ZO gV1HFK9hdWN9sSXJ6X1lR3V336GWE3b1wBzyWegegcb9mrOTbHCwyQfBBWeUOjtVBZFY IzTm/U7nX7L1DJH/3IoL41ebQ5TbsUjP5u4dwkDf5K5ilSk0J1c+DUmbE+n60Y4rl0OA Ky/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Txg6Bvxnbrn1ok7OlH36mfeenlY+zIGOFlRluj6LEs8=; b=JSb51EAy+oW9B81TnMvDRj23sy1u+y5RzOcTnkKasNAYdtoYOJKQA3/RXPOAf/z8Z8 mmRap1h2TaldLUNuBqcFga/Klzjtc0pfPf4kN6ED5cVdpWZ6cTxC/itGCcIr1o7Jqo15 CEr1izN6HuaoPwBVosMuRyTtkzMrQY3RUs4e/TRuoslLEtGC7lMk/aP1n+YwQQ53WX0a 15dDfGGzXxWLLUTXx/Zv0uxUqfWb/qmWu5NYz188tWb+4xPLFOXS70uNy+4ujioPxlJD N6q3ZckArW6wfwLNCjdbHBl7pWL/dRenCiPQ1MwO8dWUNlWMsB5iRgLqrh2AbAH1GwDZ gyKw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fI1jtnsz; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t14si12739256pgv.125.2019.02.18.06.37.25; Mon, 18 Feb 2019 06:37:41 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fI1jtnsz; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387517AbfBRNzX (ORCPT + 99 others); Mon, 18 Feb 2019 08:55:23 -0500 Received: from mail.kernel.org ([198.145.29.99]:35400 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387432AbfBRNzV (ORCPT ); Mon, 18 Feb 2019 08:55:21 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 41A8B2077B; Mon, 18 Feb 2019 13:55:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1550498120; bh=DDvg8cwB/nrY1/y+TkFUE6r3UbnxBgrdNq/b5/UvBTQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fI1jtnszlG7VnR90qrOwFDmmdyhGCeB7ACxdTF/oR6AVD8kQuEstHpbjl53AZ276x dQc/ThBGvrr3yeqtmz5d2cecxwpBuXU3g5EZjfo6MGYsd0zi0MPwEHUnCEOvZFFdDX /aCCSrH5p1qQ81rToUpiWDhAdnZ7AEa4oxEcY1t0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Daniel Axtens , "David S. Miller" , Jack Wang , Sasha Levin Subject: [PATCH 4.14 22/62] net: create skb_gso_validate_mac_len() Date: Mon, 18 Feb 2019 14:43:28 +0100 Message-Id: <20190218133507.858947854@linuxfoundation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190218133505.801423074@linuxfoundation.org> References: <20190218133505.801423074@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ commit 2b16f048729bf35e6c28a40cbfad07239f9dcd90 upstream If you take a GSO skb, and split it into packets, will the MAC length (L2 + L3 + L4 headers + payload) of those packets be small enough to fit within a given length? Move skb_gso_mac_seglen() to skbuff.h with other related functions like skb_gso_network_seglen() so we can use it, and then create skb_gso_validate_mac_len to do the full calculation. Signed-off-by: Daniel Axtens Signed-off-by: David S. Miller [jwang: cherry pick for CVE-2018-1000026] Signed-off-by: Jack Wang Signed-off-by: Sasha Levin --- include/linux/skbuff.h | 16 +++++++++++ net/core/skbuff.c | 63 +++++++++++++++++++++++++++++++++--------- net/sched/sch_tbf.c | 10 ------- 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 39c2570ddcf6..50a4a5968f3a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3317,6 +3317,7 @@ int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen); void skb_scrub_packet(struct sk_buff *skb, bool xnet); unsigned int skb_gso_transport_seglen(const struct sk_buff *skb); bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu); +bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len); struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features); struct sk_buff *skb_vlan_untag(struct sk_buff *skb); int skb_ensure_writable(struct sk_buff *skb, int write_len); @@ -4087,6 +4088,21 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb) return hdr_len + skb_gso_transport_seglen(skb); } +/** + * skb_gso_mac_seglen - Return length of individual segments of a gso packet + * + * @skb: GSO skb + * + * skb_gso_mac_seglen is used to determine the real size of the + * individual segments, including MAC/L2, Layer3 (IP, IPv6) and L4 + * headers (TCP/UDP). + */ +static inline unsigned int skb_gso_mac_seglen(const struct sk_buff *skb) +{ + unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb); + return hdr_len + skb_gso_transport_seglen(skb); +} + /* Local Checksum Offload. * Compute outer checksum based on the assumption that the * inner checksum will be offloaded later. diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 873032d1a083..6dbd2c54b2c9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4930,37 +4930,74 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); /** - * skb_gso_validate_mtu - Return in case such skb fits a given MTU + * skb_gso_size_check - check the skb size, considering GSO_BY_FRAGS * - * @skb: GSO skb - * @mtu: MTU to validate against + * There are a couple of instances where we have a GSO skb, and we + * want to determine what size it would be after it is segmented. * - * skb_gso_validate_mtu validates if a given skb will fit a wanted MTU - * once split. + * We might want to check: + * - L3+L4+payload size (e.g. IP forwarding) + * - L2+L3+L4+payload size (e.g. sanity check before passing to driver) + * + * This is a helper to do that correctly considering GSO_BY_FRAGS. + * + * @seg_len: The segmented length (from skb_gso_*_seglen). In the + * GSO_BY_FRAGS case this will be [header sizes + GSO_BY_FRAGS]. + * + * @max_len: The maximum permissible length. + * + * Returns true if the segmented length <= max length. */ -bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu) -{ +static inline bool skb_gso_size_check(const struct sk_buff *skb, + unsigned int seg_len, + unsigned int max_len) { const struct skb_shared_info *shinfo = skb_shinfo(skb); const struct sk_buff *iter; - unsigned int hlen; - - hlen = skb_gso_network_seglen(skb); if (shinfo->gso_size != GSO_BY_FRAGS) - return hlen <= mtu; + return seg_len <= max_len; /* Undo this so we can re-use header sizes */ - hlen -= GSO_BY_FRAGS; + seg_len -= GSO_BY_FRAGS; skb_walk_frags(skb, iter) { - if (hlen + skb_headlen(iter) > mtu) + if (seg_len + skb_headlen(iter) > max_len) return false; } return true; } + +/** + * skb_gso_validate_mtu - Return in case such skb fits a given MTU + * + * @skb: GSO skb + * @mtu: MTU to validate against + * + * skb_gso_validate_mtu validates if a given skb will fit a wanted MTU + * once split. + */ +bool skb_gso_validate_mtu(const struct sk_buff *skb, unsigned int mtu) +{ + return skb_gso_size_check(skb, skb_gso_network_seglen(skb), mtu); +} EXPORT_SYMBOL_GPL(skb_gso_validate_mtu); +/** + * skb_gso_validate_mac_len - Will a split GSO skb fit in a given length? + * + * @skb: GSO skb + * @len: length to validate against + * + * skb_gso_validate_mac_len validates if a given skb will fit a wanted + * length once split, including L2, L3 and L4 headers and the payload. + */ +bool skb_gso_validate_mac_len(const struct sk_buff *skb, unsigned int len) +{ + return skb_gso_size_check(skb, skb_gso_mac_seglen(skb), len); +} +EXPORT_SYMBOL_GPL(skb_gso_validate_mac_len); + static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) { int mac_len; diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index b36ecb58aa6e..107cc76b6e24 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -142,16 +142,6 @@ static u64 psched_ns_t2l(const struct psched_ratecfg *r, return len; } -/* - * Return length of individual segments of a gso packet, - * including all headers (MAC, IP, TCP/UDP) - */ -static unsigned int skb_gso_mac_seglen(const struct sk_buff *skb) -{ - unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb); - return hdr_len + skb_gso_transport_seglen(skb); -} - /* GSO packet is too big, segment it so that tbf can transmit * each segment in time */ -- 2.19.1