Received: by 2002:a25:c593:0:0:0:0:0 with SMTP id v141csp6240803ybe; Tue, 17 Sep 2019 23:38:16 -0700 (PDT) X-Google-Smtp-Source: APXvYqxqEqwPaFpOqSEvJVeITv8h1RunSJEzaEkjVe2E0mRIELNz/iE3AWh4yXGIQvbJF4xQFENT X-Received: by 2002:aa7:dc55:: with SMTP id g21mr4956914edu.210.1568788696661; Tue, 17 Sep 2019 23:38:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1568788696; cv=none; d=google.com; s=arc-20160816; b=oDfad1ufIFg32hK6U4P4XThke3qPKmYtb9msBurbnVSFnoJloJ9jWpzfGMU0ktj5ux cMkuIMn3pcbecTbCiC0SKMK8DaA1HDlWo9bjzbbajJYEnVfqokVtUGtXn5v1ykJ3jfik O9iYNGMC9d6Szfiy195VviTOi7LD4HvgOTarjFsTVdgxTzsw1dZ0W6ELt5iGtC1bNeP1 8Czbkvy3lxEkrfCiTUPbTWOIFTHLjZ/ZUFZS8MihhOgdDdmkJBSHZdtP/dL3ST4vhZEf U1jFfjtIDabx9aUnLStUjqjkJH8J3kbmToVxYOt1jpVL8t6vDAmuJjNI9TeXuLOS8Ywa tULg== 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=cQ3PLeZQQyCmRgOIlgaJR8ebLWEPDdP62St30PIIANM=; b=XIyC1GmT7/TRo9TdlRDMwd9oh7MS0pJMx0seB5bIqhbzZJLo2FfASQ4fkm2Q9VeMtg 4IS8ry/lfBUD5Vrita74mQll1QsU7IkEz0Aw0x2NshyReX0Q423y7u80CPODzLF9XWr/ LXO308yM36EAvWlV9GWxeU0IcY69IxBE2DXsrzt2ojgaGrXOF4uRqm8iMhx1kvbjEfho htc2k6D4qzKhHUG3E+A/ztQ6MhjGzhQdtpqXsrzJoCH1CZ4PwB32RzcY95Z8qlZrh8NH 94QMqj5z8a93SMi2QJOWAK6ax2N7po0vEH6bY2HejkcEbLY+AFIt7/olT910CQdc6SNA uu2g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=e5AjyEpD; 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 o49si2776082edc.261.2019.09.17.23.37.53; Tue, 17 Sep 2019 23:38:16 -0700 (PDT) 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=e5AjyEpD; 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 S1729139AbfIRGVb (ORCPT + 99 others); Wed, 18 Sep 2019 02:21:31 -0400 Received: from mail.kernel.org ([198.145.29.99]:40768 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729084AbfIRGVY (ORCPT ); Wed, 18 Sep 2019 02:21:24 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.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 F05172053B; Wed, 18 Sep 2019 06:21:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1568787683; bh=qEC3OPBq2O/Yt0wWToHvduRL+baM8br/3x3yc5kO8KA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e5AjyEpDn3JtBmizig6+NLpB0Ea5IkQW3q52fW2YAUyncQ9Ksf7XH/CakxIOKrJi9 RJS5rTQM5pJU/ofI3DsqqFW8SvAer1iBjCZkuDu6zbHIPuqnaQPnoCoIeEVZ7ar20r c039uUhl4IqYWZqXOQxaOuod+JKgYpGUpyyPM1ks= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Willem de Bruijn , Daniel Borkmann , Eric Dumazet , Alexander Duyck , Shmulik Ladkani , Willem de Bruijn , Alexander Duyck , "David S. Miller" Subject: [PATCH 4.14 06/45] net: gso: Fix skb_segment splat when splitting gso_size mangled skb having linear-headed frag_list Date: Wed, 18 Sep 2019 08:18:44 +0200 Message-Id: <20190918061223.498721351@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190918061222.854132812@linuxfoundation.org> References: <20190918061222.854132812@linuxfoundation.org> User-Agent: quilt/0.66 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 From: Shmulik Ladkani [ Upstream commit 3dcbdb134f329842a38f0e6797191b885ab00a00 ] Historically, support for frag_list packets entering skb_segment() was limited to frag_list members terminating on exact same gso_size boundaries. This is verified with a BUG_ON since commit 89319d3801d1 ("net: Add frag_list support to skb_segment"), quote: As such we require all frag_list members terminate on exact MSS boundaries. This is checked using BUG_ON. As there should only be one producer in the kernel of such packets, namely GRO, this requirement should not be difficult to maintain. However, since commit 6578171a7ff0 ("bpf: add bpf_skb_change_proto helper"), the "exact MSS boundaries" assumption no longer holds: An eBPF program using bpf_skb_change_proto() DOES modify 'gso_size', but leaves the frag_list members as originally merged by GRO with the original 'gso_size'. Example of such programs are bpf-based NAT46 or NAT64. This lead to a kernel BUG_ON for flows involving: - GRO generating a frag_list skb - bpf program performing bpf_skb_change_proto() or bpf_skb_adjust_room() - skb_segment() of the skb See example BUG_ON reports in [0]. In commit 13acc94eff12 ("net: permit skb_segment on head_frag frag_list skb"), skb_segment() was modified to support the "gso_size mangling" case of a frag_list GRO'ed skb, but *only* for frag_list members having head_frag==true (having a page-fragment head). Alas, GRO packets having frag_list members with a linear kmalloced head (head_frag==false) still hit the BUG_ON. This commit adds support to skb_segment() for a 'head_skb' packet having a frag_list whose members are *non* head_frag, with gso_size mangled, by disabling SG and thus falling-back to copying the data from the given 'head_skb' into the generated segmented skbs - as suggested by Willem de Bruijn [1]. Since this approach involves the penalty of skb_copy_and_csum_bits() when building the segments, care was taken in order to enable this solution only when required: - untrusted gso_size, by testing SKB_GSO_DODGY is set (SKB_GSO_DODGY is set by any gso_size mangling functions in net/core/filter.c) - the frag_list is non empty, its item is a non head_frag, *and* the headlen of the given 'head_skb' does not match the gso_size. [0] https://lore.kernel.org/netdev/20190826170724.25ff616f@pixies/ https://lore.kernel.org/netdev/9265b93f-253d-6b8c-f2b8-4b54eff1835c@fb.com/ [1] https://lore.kernel.org/netdev/CA+FuTSfVsgNDi7c=GUU8nMg2hWxF2SjCNLXetHeVPdnxAW5K-w@mail.gmail.com/ Fixes: 6578171a7ff0 ("bpf: add bpf_skb_change_proto helper") Suggested-by: Willem de Bruijn Cc: Daniel Borkmann Cc: Eric Dumazet Cc: Alexander Duyck Signed-off-by: Shmulik Ladkani Reviewed-by: Willem de Bruijn Reviewed-by: Alexander Duyck Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/skbuff.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3514,6 +3514,25 @@ struct sk_buff *skb_segment(struct sk_bu int pos; int dummy; + if (list_skb && !list_skb->head_frag && skb_headlen(list_skb) && + (skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY)) { + /* gso_size is untrusted, and we have a frag_list with a linear + * non head_frag head. + * + * (we assume checking the first list_skb member suffices; + * i.e if either of the list_skb members have non head_frag + * head, then the first one has too). + * + * If head_skb's headlen does not fit requested gso_size, it + * means that the frag_list members do NOT terminate on exact + * gso_size boundaries. Hence we cannot perform skb_frag_t page + * sharing. Therefore we must fallback to copying the frag_list + * skbs; we do so by disabling SG. + */ + if (mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb)) + features &= ~NETIF_F_SG; + } + __skb_push(head_skb, doffset); proto = skb_network_protocol(head_skb, &dummy); if (unlikely(!proto))