From patchwork Thu Nov 30 10:50:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Dumazet X-Patchwork-Id: 10084571 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0982A6035E for ; Thu, 30 Nov 2017 10:50:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D3AE429F0B for ; Thu, 30 Nov 2017 10:50:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C7FF229F35; Thu, 30 Nov 2017 10:50:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F82C29F0B for ; Thu, 30 Nov 2017 10:50:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751911AbdK3Kut (ORCPT ); Thu, 30 Nov 2017 05:50:49 -0500 Received: from mail-io0-f195.google.com ([209.85.223.195]:37129 "EHLO mail-io0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751862AbdK3Kur (ORCPT ); Thu, 30 Nov 2017 05:50:47 -0500 Received: by mail-io0-f195.google.com with SMTP id d16so7076048iob.4; Thu, 30 Nov 2017 02:50:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:subject:from:to:cc:date:in-reply-to:references :mime-version:content-transfer-encoding; bh=KKhOryyoCCWrhLvd3opZI31ZS6AmsQqIzPODc/GLLP0=; b=smMGnWG2TS1OXcRGkvFgbiP2qDvZ/I/clFoax1747Hle6IkaU9tz3500z7XclJceZI 64E9KeLh7yxDFzJo96gwDSi8ltT9TK3S7q84nkKEvPd4hhukBgeoeE4Hv+xS6r20Clyz GvBvycS56p9ctb4SeQ028HNwufX3xidGE+w3NWePPEbbU1x3MY954syzuL5Q1TwWzsfN K48XHsEo3SKZ/tgUI+3zlVHuRWrAmLBmtZHU6cmMfoUmrR4jBQXmUZxp4lXP0vh+RvUU 2I4ZY/7+w/oJRdJSrWWdmp0bvoNd7m8CfoWbHAnM6sfH6vRFcT1qTyfsaAFmOfVuKPS9 K3Xw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:mime-version:content-transfer-encoding; bh=KKhOryyoCCWrhLvd3opZI31ZS6AmsQqIzPODc/GLLP0=; b=Po2WWBS5BCNkD2FfYp+yN0hJyER3409Ga6BPRAc3HU46xnAJW1k+VCusnUe3nwJONF aCXotP9G4cVgLjN3D1N+zQIUdcMp9h4G+6vG9SYly2Qx89lMI5ACpjALQT9SHd53/ppM SocdblTwjnyc+WtrNHc3rypTcDWI/zY2SG4HEmkZtF1T/XJZFX6vMv/XRnE6i4QznLdn 31Ca+qCMW5SWmgnu6D5VEbIlrs54MSI1ISPk40x2CctAKwtZ+7bhrS9uaLSuFDm7W6y/ f+nPo/0AgbTmaROjY27WzqclchldcFNwDceFqjfSN3J4wMVWGRGKSVx+EMu9KQlK+YF/ 6CFw== X-Gm-Message-State: AJaThX5E4TCLQabdEU2yZR5D8LaGY3X/IJ4SKMtchkuVRuxR/79rU8C1 sSvNqukTe9RTnyYSLF3MIhs= X-Google-Smtp-Source: AGs4zMYPO1HCFDu61q14cwwlxC4l6xWtwAURBXv5gvgx7XiCUsd/zSaB+SW6dk35xjfGY0rC8985JQ== X-Received: by 10.107.201.78 with SMTP id z75mr7429705iof.123.1512039047216; Thu, 30 Nov 2017 02:50:47 -0800 (PST) Received: from edumazet-glaptop3.lan (c-67-180-167-114.hsd1.ca.comcast.net. [67.180.167.114]) by smtp.googlemail.com with ESMTPSA id h21sm1892316iod.59.2017.11.30.02.50.45 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 30 Nov 2017 02:50:46 -0800 (PST) Message-ID: <1512039044.19682.12.camel@gmail.com> Subject: Re: [BUG] kernel stack corruption during/after Netlabel error From: Eric Dumazet To: Casey Schaufler , James Morris Cc: Paul Moore , netdev@vger.kernel.org, Stephen Smalley , selinux@tycho.nsa.gov, LSM Date: Thu, 30 Nov 2017 02:50:44 -0800 In-Reply-To: References: <4d73f839-7a86-6edc-b44b-e296bd5947c2@schaufler-ca.com> X-Mailer: Evolution 3.22.6-1+deb9u1 Mime-Version: 1.0 Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP On Wed, 2017-11-29 at 19:16 -0800, Casey Schaufler wrote: > On 11/29/2017 4:31 PM, James Morris wrote: > > On Wed, 29 Nov 2017, Casey Schaufler wrote: > > > > > I see that there is a proposed fix later in the thread, but I > > > don't see > > > the patch. Could you send it to me, so I can try it on my > > > problem? > > > > Forwarded off-list. > > The patch does fix the problem I was seeing in Smack. Can you guys test the following more complete patch ? It should cover IPv4 and IPv6, and also the corner cases. ( Note that I squashed ipv6 fix in https://patchwork.ozlabs.org/patch/8 42844/ that I spotted while cooking this patch ) Tested-by: Casey Schaufler Tested-by: Paul Moore Tested-by: James Morris --- To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c6bc0c4d19c624888b0d0b5a4246c7183edf63f5..77ea45da0fe9c746907a312989658af3ad3b198d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1591,6 +1591,34 @@ int tcp_filter(struct sock *sk, struct sk_buff *skb) } EXPORT_SYMBOL(tcp_filter); +static void tcp_v4_restore_cb(struct sk_buff *skb) +{ + memmove(IPCB(skb), &TCP_SKB_CB(skb)->header.h4, + sizeof(struct inet_skb_parm)); +} + +static void tcp_v4_fill_cb(struct sk_buff *skb, const struct iphdr *iph, + const struct tcphdr *th) +{ + /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB() + * barrier() makes sure compiler wont play fool^Waliasing games. + */ + memmove(&TCP_SKB_CB(skb)->header.h4, IPCB(skb), + sizeof(struct inet_skb_parm)); + barrier(); + + TCP_SKB_CB(skb)->seq = ntohl(th->seq); + TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + + skb->len - th->doff * 4); + TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); + TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); + TCP_SKB_CB(skb)->tcp_tw_isn = 0; + TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph); + TCP_SKB_CB(skb)->sacked = 0; + TCP_SKB_CB(skb)->has_rxtstamp = + skb->tstamp || skb_hwtstamps(skb)->hwtstamp; +} + /* * From tcp_input.c */ @@ -1631,24 +1659,6 @@ int tcp_v4_rcv(struct sk_buff *skb) th = (const struct tcphdr *)skb->data; iph = ip_hdr(skb); - /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB() - * barrier() makes sure compiler wont play fool^Waliasing games. - */ - memmove(&TCP_SKB_CB(skb)->header.h4, IPCB(skb), - sizeof(struct inet_skb_parm)); - barrier(); - - TCP_SKB_CB(skb)->seq = ntohl(th->seq); - TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + - skb->len - th->doff * 4); - TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); - TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); - TCP_SKB_CB(skb)->tcp_tw_isn = 0; - TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph); - TCP_SKB_CB(skb)->sacked = 0; - TCP_SKB_CB(skb)->has_rxtstamp = - skb->tstamp || skb_hwtstamps(skb)->hwtstamp; - lookup: sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source, th->dest, sdif, &refcounted); @@ -1679,14 +1689,19 @@ int tcp_v4_rcv(struct sk_buff *skb) sock_hold(sk); refcounted = true; nsk = NULL; - if (!tcp_filter(sk, skb)) + if (!tcp_filter(sk, skb)) { + th = (const struct tcphdr *)skb->data; + iph = ip_hdr(skb); + tcp_v4_fill_cb(skb, iph, th); nsk = tcp_check_req(sk, skb, req, false); + } if (!nsk) { reqsk_put(req); goto discard_and_relse; } if (nsk == sk) { reqsk_put(req); + tcp_v4_restore_cb(skb); } else if (tcp_child_process(sk, nsk, skb)) { tcp_v4_send_reset(nsk, skb); goto discard_and_relse; @@ -1712,6 +1727,7 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_and_relse; th = (const struct tcphdr *)skb->data; iph = ip_hdr(skb); + tcp_v4_fill_cb(skb, iph, th); skb->dev = NULL; @@ -1742,6 +1758,8 @@ int tcp_v4_rcv(struct sk_buff *skb) if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) goto discard_it; + tcp_v4_fill_cb(skb, iph, th); + if (tcp_checksum_complete(skb)) { csum_error: __TCP_INC_STATS(net, TCP_MIB_CSUMERRORS); @@ -1768,6 +1786,8 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_it; } + tcp_v4_fill_cb(skb, iph, th); + if (tcp_checksum_complete(skb)) { inet_twsk_put(inet_twsk(sk)); goto csum_error; @@ -1784,6 +1804,7 @@ int tcp_v4_rcv(struct sk_buff *skb) if (sk2) { inet_twsk_deschedule_put(inet_twsk(sk)); sk = sk2; + tcp_v4_restore_cb(skb); refcounted = false; goto process; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6bb98c93edfe2ed2f16fe5229605f8108cfc7f9a..1f04ec0e4a7aa2c11b8ee27cbdd4067b5bcf32e5 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1454,7 +1454,6 @@ static int tcp_v6_rcv(struct sk_buff *skb) struct sock *nsk; sk = req->rsk_listener; - tcp_v6_fill_cb(skb, hdr, th); if (tcp_v6_inbound_md5_hash(sk, skb)) { sk_drops_add(sk, skb); reqsk_put(req); @@ -1467,8 +1466,12 @@ static int tcp_v6_rcv(struct sk_buff *skb) sock_hold(sk); refcounted = true; nsk = NULL; - if (!tcp_filter(sk, skb)) + if (!tcp_filter(sk, skb)) { + th = (const struct tcphdr *)skb->data; + hdr = ipv6_hdr(skb); + tcp_v6_fill_cb(skb, hdr, th); nsk = tcp_check_req(sk, skb, req, false); + } if (!nsk) { reqsk_put(req); goto discard_and_relse; @@ -1492,8 +1495,6 @@ static int tcp_v6_rcv(struct sk_buff *skb) if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; - tcp_v6_fill_cb(skb, hdr, th); - if (tcp_v6_inbound_md5_hash(sk, skb)) goto discard_and_relse; @@ -1501,6 +1502,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) goto discard_and_relse; th = (const struct tcphdr *)skb->data; hdr = ipv6_hdr(skb); + tcp_v6_fill_cb(skb, hdr, th); skb->dev = NULL; @@ -1590,7 +1592,6 @@ static int tcp_v6_rcv(struct sk_buff *skb) tcp_v6_timewait_ack(sk, skb); break; case TCP_TW_RST: - tcp_v6_restore_cb(skb); tcp_v6_send_reset(sk, skb); inet_twsk_deschedule_put(inet_twsk(sk)); goto discard_it;