Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp5033391pxu; Thu, 10 Dec 2020 11:11:37 -0800 (PST) X-Google-Smtp-Source: ABdhPJxm0fIbtQRljdgH/I+RxapnTdQziwgQBznMrDk1Yq5n024zRV7812Y/mL/R2STvQ13H+Q86 X-Received: by 2002:a17:906:7fcf:: with SMTP id r15mr8206682ejs.79.1607627496302; Thu, 10 Dec 2020 11:11:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1607627496; cv=none; d=google.com; s=arc-20160816; b=d+Z5Wj+sy7nk3GpRap7dKHxMkr77JqKbPpWm6INUFiX/sU5d292PuC+YUZa2dXvpij v9+V8SG4Rx0f1ld5zFxtdSp2flE4AfJvsNjBAQzoNkc8zWfvB2iX5/qV4VZPrYyBw6gx 6BdI8Ujt1mD+VC/koprvmftIpBRDl4I3OFanqcq0sXrk/DTMq2vQx9fAdz3dq5rsCfCL l1L2UHIdlKFfKh79cDFpG9TegWAri5nMGEHiBR+UUNYdpsvWcab1zVKfG6Vds5WXYWbu dsXbJW6Wo22YyAsMK58eKU6T3/g/YdBlb+o+Oxtylj+qcbKHF7QBFyml56GgCQwbRbPK F6hg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from; bh=Ilo2aCHFK5PF0hWZIbiH5SFOI/T7HXLPZKv7U+Q3AHo=; b=QqkCRQZSeCZTJ8zVHTmOyTHuCaS7FDLEt5i4yrbUI5F880I6FnMeuhwOu3WoDUWWt3 Unrkup1BlV6SREpPjCaq6qQwwGHCJw+2MxAnk1Xsfepg/lsfaZ3hwriv5sAOyOarlqQ/ Q6BqKud8j/MTG5o7sx/BpScubxWM3K6rMw/CqChLDt0fOWL8gF8QgL6eoUla5qmcZSYR qc3rTlwpdqgIKuKbpxTA6oB28S5HMe95uUBc18Nn8r1PB6KJn2EWFA2kDmgZA03EhAA2 USw1UwxjHTtse3ANBBC5fQLJ0vTyp7vZMnheTegpCogyeWNAw437ERsm7uaz+n3JKfQO WipA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id c7si3099727eje.347.2020.12.10.11.11.13; Thu, 10 Dec 2020 11:11:36 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404237AbgLJTGy (ORCPT + 99 others); Thu, 10 Dec 2020 14:06:54 -0500 Received: from mail.kernel.org ([198.145.29.99]:38740 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390470AbgLJObC (ORCPT ); Thu, 10 Dec 2020 09:31:02 -0500 From: Greg Kroah-Hartman Authentication-Results: mail.kernel.org; dkim=permerror (bad message/signature format) To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Toshiaki Makita , Daniel Borkmann , =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= , "David S. Miller" , Sasha Levin Subject: [PATCH 4.14 03/31] vlan: consolidate VLAN parsing code and limit max parsing depth Date: Thu, 10 Dec 2020 15:26:40 +0100 Message-Id: <20201210142602.272144390@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201210142602.099683598@linuxfoundation.org> References: <20201210142602.099683598@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Toke Høiland-Jørgensen [ Upstream commit 469aceddfa3ed16e17ee30533fae45e90f62efd8 ] Toshiaki pointed out that we now have two very similar functions to extract the L3 protocol number in the presence of VLAN tags. And Daniel pointed out that the unbounded parsing loop makes it possible for maliciously crafted packets to loop through potentially hundreds of tags. Fix both of these issues by consolidating the two parsing functions and limiting the VLAN tag parsing to a max depth of 8 tags. As part of this, switch over __vlan_get_protocol() to use skb_header_pointer() instead of pskb_may_pull(), to avoid the possible side effects of the latter and keep the skb pointer 'const' through all the parsing functions. v2: - Use limit of 8 tags instead of 32 (matching XMIT_RECURSION_LIMIT) Reported-by: Toshiaki Makita Reported-by: Daniel Borkmann Fixes: d7bf2ebebc2b ("sched: consistently handle layer3 header accesses in the presence of VLANs") Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- include/linux/if_vlan.h | 29 ++++++++++++++++++++++------- include/net/inet_ecn.h | 1 + 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 87b8c20d5b27c..af4f2a7f8e9a0 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -30,6 +30,8 @@ #define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ #define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ +#define VLAN_MAX_DEPTH 8 /* Max. number of nested VLAN tags parsed */ + /* * struct vlan_hdr - vlan header * @h_vlan_TCI: priority and VLAN ID @@ -534,10 +536,10 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) * Returns the EtherType of the packet, regardless of whether it is * vlan encapsulated (normal or hardware accelerated) or not. */ -static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type, +static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type, int *depth) { - unsigned int vlan_depth = skb->mac_len; + unsigned int vlan_depth = skb->mac_len, parse_depth = VLAN_MAX_DEPTH; /* if type is 802.1Q/AD then the header should already be * present at mac_len - VLAN_HLEN (if mac_len > 0), or at @@ -552,13 +554,12 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type, vlan_depth = ETH_HLEN; } do { - struct vlan_hdr *vh; + struct vlan_hdr vhdr, *vh; - if (unlikely(!pskb_may_pull(skb, - vlan_depth + VLAN_HLEN))) + vh = skb_header_pointer(skb, vlan_depth, sizeof(vhdr), &vhdr); + if (unlikely(!vh || !--parse_depth)) return 0; - vh = (struct vlan_hdr *)(skb->data + vlan_depth); type = vh->h_vlan_encapsulated_proto; vlan_depth += VLAN_HLEN; } while (eth_type_vlan(type)); @@ -577,11 +578,25 @@ static inline __be16 __vlan_get_protocol(struct sk_buff *skb, __be16 type, * Returns the EtherType of the packet, regardless of whether it is * vlan encapsulated (normal or hardware accelerated) or not. */ -static inline __be16 vlan_get_protocol(struct sk_buff *skb) +static inline __be16 vlan_get_protocol(const struct sk_buff *skb) { return __vlan_get_protocol(skb, skb->protocol, NULL); } +/* A getter for the SKB protocol field which will handle VLAN tags consistently + * whether VLAN acceleration is enabled or not. + */ +static inline __be16 skb_protocol(const struct sk_buff *skb, bool skip_vlan) +{ + if (!skip_vlan) + /* VLAN acceleration strips the VLAN header from the skb and + * moves it to skb->vlan_proto + */ + return skb_vlan_tag_present(skb) ? skb->vlan_proto : skb->protocol; + + return vlan_get_protocol(skb); +} + static inline void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr) { diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index d30e4c869438c..09ed8a48b4548 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -4,6 +4,7 @@ #include #include +#include #include #include -- 2.27.0