From patchwork Mon Jan 23 23:58:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 718842 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3v6pF1271Fz9sCg for ; Tue, 24 Jan 2017 10:59:01 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="Wtl9/czM"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751895AbdAWX67 (ORCPT ); Mon, 23 Jan 2017 18:58:59 -0500 Received: from mail-pg0-f49.google.com ([74.125.83.49]:33703 "EHLO mail-pg0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751872AbdAWX6u (ORCPT ); Mon, 23 Jan 2017 18:58:50 -0500 Received: by mail-pg0-f49.google.com with SMTP id 204so49105515pge.0 for ; Mon, 23 Jan 2017 15:58:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=PHM0k6p886xM992bGHVeMKK8ThNEfcKE7rfFLJy1Fr8=; b=Wtl9/czMnTPL500BCgdarmLXg9JObONSxQTCEMKp87ir3GLBdWhHHxJ5yM4nxsUKzY APEpDw9EaDeMO4OKIQyLBB499c3HBOjT3Oj6Pe79oS15rAMx9y79i8/pdI5JljI3ZUcW h1VrLSwpslwF/lH/XpHWg8XDsFBo/kA1uIUz/VcQ1YdOfU4rxCIOuTVyUPthr9+E9PAV bYcOpKCHTGR2KFzPw7UKodMp6K7jDNJM0VZf0E8bHUyGkmB5N8DJabKZOAAWp899yXf9 kvEW4ADyYZttB1JihyS90O0QMYL2079p9bHoh1xzyzaaAUn7xKZglc7WiFfnTYbQSP4y KUyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=PHM0k6p886xM992bGHVeMKK8ThNEfcKE7rfFLJy1Fr8=; b=dc1NE3BB3PRbwaBSVtnCqoSpVEohEnR9xDzxbwIJlj8TnNolqbLF6wWBbKXZhTzRHq uNjB4J1Ts6oFFWHF28WOAjSUmhZqRhI7HBCnhjpydy/M9Gip5tpHMX18V8UWO88Xf5Ua 9zrvYhwWVJtFiMK3M/ZlntpovwX3bON/PM4e1KgJbgi7o6M7pTFrhFcU9lK9JRhn/xfR KJoifiu2RdtkroDdWx7khVmpKToKRXgPwAbTGJc/XHX/u4anCF5Z7Z2mM1na8eQilJS5 kMNQ8CSis3DfOEya1u34PEeQfxjbTEM/TYwP1d9Z8mffmz5XAtr+VOF7tcjoRE0oRbc3 FEzA== X-Gm-Message-State: AIkVDXKL2C/cPHIs+SEmQnFqENTyie2P+wEXhtW5pPSPV2QBMkoP+gXIUVbkN2Hy+FXvj7cq X-Received: by 10.84.198.3 with SMTP id o3mr46918451pld.170.1485215890573; Mon, 23 Jan 2017 15:58:10 -0800 (PST) Received: from localhost ([2620:0:1000:3012:d4a9:c8c9:66a4:80fd]) by smtp.gmail.com with ESMTPSA id r21sm39283178pfd.95.2017.01.23.15.58.09 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 23 Jan 2017 15:58:10 -0800 (PST) From: Eric Dumazet To: "David S . Miller" Cc: netdev , Eric Dumazet , Willem de Bruijn , Alexei Starovoitov , Eric Dumazet Subject: [PATCH net-next 2/2] ipv6: fix ip6_tnl_parse_tlv_enc_lim() Date: Mon, 23 Jan 2017 15:58:04 -0800 Message-Id: <20170123235804.29342-3-edumazet@google.com> X-Mailer: git-send-email 2.11.0.483.g087da7b7c-goog In-Reply-To: <20170123235804.29342-1-edumazet@google.com> References: <20170123235804.29342-1-edumazet@google.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This function suffers from multiple issues. First one is that pskb_may_pull() may reallocate skb->head, so the 'raw' pointer needs either to be reloaded or not used at all. Second issue is that NEXTHDR_DEST handling does not validate that the options are present in skb->data, so we might read garbage or access non existent memory. With help from Willem de Bruijn. Signed-off-by: Eric Dumazet Reported-by: Dmitry Vyukov Cc: Willem de Bruijn --- net/ipv6/ip6_tunnel.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 02923f956ac8ba5f3270e8d5282fd9637c2d..f9c43c9043f7e386108bca2f2aeb866cfb76 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -400,18 +400,18 @@ ip6_tnl_dev_uninit(struct net_device *dev) __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) { - const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; - __u8 nexthdr = ipv6h->nexthdr; - __u16 off = sizeof(*ipv6h); + const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)raw; + unsigned int nhoff = (raw - skb->data) + sizeof(*ipv6h); + u8 next, nexthdr = ipv6h->nexthdr; while (ipv6_ext_hdr(nexthdr) && nexthdr != NEXTHDR_NONE) { - __u16 optlen = 0; struct ipv6_opt_hdr *hdr; - if (raw + off + sizeof(*hdr) > skb->data && - !pskb_may_pull(skb, raw - skb->data + off + sizeof (*hdr))) + u16 optlen; + + if (!pskb_may_pull(skb, nhoff + sizeof(*hdr))) break; - hdr = (struct ipv6_opt_hdr *) (raw + off); + hdr = (struct ipv6_opt_hdr *)(skb->data + nhoff); if (nexthdr == NEXTHDR_FRAGMENT) { struct frag_hdr *frag_hdr = (struct frag_hdr *) hdr; if (frag_hdr->frag_off) @@ -422,13 +422,23 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) } else { optlen = ipv6_optlen(hdr); } + /* cache hdr->nexthdr, since pskb_may_pull() might + * invalidate hdr + */ + next = hdr->nexthdr; if (nexthdr == NEXTHDR_DEST) { - __u16 i = off + 2; + u16 i = 2; + + /* Remember : hdr is no longer valid at this point. */ + if (!pskb_may_pull(skb, nhoff + optlen)) + break; + + raw = skb->data + nhoff; while (1) { struct ipv6_tlv_tnl_enc_lim *tel; /* No more room for encapsulation limit */ - if (i + sizeof (*tel) > off + optlen) + if (i + sizeof(*tel) > optlen) break; tel = (struct ipv6_tlv_tnl_enc_lim *) &raw[i]; @@ -443,8 +453,8 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) i++; } } - nexthdr = hdr->nexthdr; - off += optlen; + nexthdr = next; + nhoff += optlen; } return 0; }