Received: by 2002:ac0:bc90:0:0:0:0:0 with SMTP id a16csp5656289img; Wed, 27 Mar 2019 12:34:01 -0700 (PDT) X-Google-Smtp-Source: APXvYqxj3xh/IBSl3OhE/ZCE2zpYDzcdef3enho4ckbmR8CEz2tQ9BZGa9ufqtfkAIJBTqdObzPZ X-Received: by 2002:a17:902:2848:: with SMTP id e66mr39538683plb.181.1553715241446; Wed, 27 Mar 2019 12:34:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1553715241; cv=none; d=google.com; s=arc-20160816; b=fTRihBUaSXpMVhyj3UbMCqCPe772snRusjlLvPhLTSsG3luAvA+F0iLeQY7axzsk87 UhVdU8KfTYACF1BCZx38DnsIVAjLmIIMeZVZk/beAJTXyonrSxW38nt8f8kqARgPMOG6 Mbisegl4tkHQ3Ry6Pd79XKVXC6hZ8TurVs8jMdBHJyflkgLI5FcS9h0xZIwtRAqONqoJ Otba3FFr5QXz1kw5ioolnoLgYthj4wIdA2mw6DwBMb36nzFL+JDYi+W49K95pSPG6H+8 z/JDffPqQiUoHQYTkoLW7Ad/I8LtZY3Dg8TzRY7/HrMaHVvf/aIQvej4wo8OVyx4uIPk Welw== 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 :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=KstF12x5TZQtIJA4x0J1efX1QH0amRSXh3964Ua1mVg=; b=oiFrE4cNVYDgY822uLC9q/IT3TDPfuFomX3wZgjjvMkEE8/P+r/Osf4y9ipLLkmTyr bXJ9xzqnm9/mPK85v1hU5g6W6QzqsZSW02qhyBDdiW+Hw9TrVNtpODu6uH99AijlmBCo 48ieGXyxerG5yj+KrR7fz3gkgnJd384qhQC45uIPIwBGkyfjPrEb3rzmTTRZkE8ku+Qs qbXnY1ujKGC44quycd95VsKDqmi/q1eW86Oz6wbbJ5udA/uI+WKG22gILlZfZmcHlMtA XDKR4GuhF3T5M+kH4PnyivY6kHVGpflnYG23zuj5sDOvTFH7fJfj6IOZZPxm92ixB1Hk c7WQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=qlmzwNQU; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f3si19098409pfn.122.2019.03.27.12.33.45; Wed, 27 Mar 2019 12:34:01 -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=qlmzwNQU; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387656AbfC0TdJ (ORCPT + 99 others); Wed, 27 Mar 2019 15:33:09 -0400 Received: from mail.kernel.org ([198.145.29.99]:42498 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730874AbfC0SCe (ORCPT ); Wed, 27 Mar 2019 14:02:34 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 7784F217D7; Wed, 27 Mar 2019 18:02:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1553709753; bh=Pnka2KWCFbN+CL3GfPF+gtjWz7b5RKVBpofK6u/R8E8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qlmzwNQUvj+sQ8OwTMIoNF7VOenjAZPXYXJFscCDeTe9BylS00ZWUxQZWAKAjm7Wq ALcGsfk3DwbT5Q0bvGGtYbXNpe8uCRSu8IjmlMHua5wqIo+3lrA3j86VivwBuBT21Q rovPoVt0GUKd05HglLtsUi8JsHigZfKJdWbzSZHE= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Pablo Neira Ayuso , Sasha Levin , netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org Subject: [PATCH AUTOSEL 5.0 020/262] netfilter: nf_tables: fix set double-free in abort path Date: Wed, 27 Mar 2019 13:57:55 -0400 Message-Id: <20190327180158.10245-20-sashal@kernel.org> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20190327180158.10245-1-sashal@kernel.org> References: <20190327180158.10245-1-sashal@kernel.org> MIME-Version: 1.0 X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Pablo Neira Ayuso [ Upstream commit 40ba1d9b4d19796afc9b7ece872f5f3e8f5e2c13 ] The abort path can cause a double-free of an anonymous set. Added-and-to-be-aborted rule looks like this: udp dport { 137, 138 } drop The to-be-aborted transaction list looks like this: newset newsetelem newsetelem rule This gets walked in reverse order, so first pass disables the rule, the set elements, then the set. After synchronize_rcu(), we then destroy those in same order: rule, set element, set element, newset. Problem is that the anonymous set has already been bound to the rule, so the rule (lookup expression destructor) already frees the set, when then cause use-after-free when trying to delete the elements from this set, then try to free the set again when handling the newset expression. Rule releases the bound set in first place from the abort path, this causes the use-after-free on set element removal when undoing the new element transactions. To handle this, skip new element transaction if set is bound from the abort path. This is still causes the use-after-free on set element removal. To handle this, remove transaction from the list when the set is already bound. Joint work with Florian Westphal. Fixes: f6ac85858976 ("netfilter: nf_tables: unbind set in rule from commit path") Bugzilla: https://bugzilla.netfilter.org/show_bug.cgi?id=1325 Acked-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Sasha Levin --- include/net/netfilter/nf_tables.h | 6 ++---- net/netfilter/nf_tables_api.c | 17 +++++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index b4984bbbe157..3d58acf94dd2 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -416,7 +416,8 @@ struct nft_set { unsigned char *udata; /* runtime data below here */ const struct nft_set_ops *ops ____cacheline_aligned; - u16 flags:14, + u16 flags:13, + bound:1, genmask:2; u8 klen; u8 dlen; @@ -1329,15 +1330,12 @@ struct nft_trans_rule { struct nft_trans_set { struct nft_set *set; u32 set_id; - bool bound; }; #define nft_trans_set(trans) \ (((struct nft_trans_set *)trans->data)->set) #define nft_trans_set_id(trans) \ (((struct nft_trans_set *)trans->data)->set_id) -#define nft_trans_set_bound(trans) \ - (((struct nft_trans_set *)trans->data)->bound) struct nft_trans_chain { bool update; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 4893f248dfdc..e1724f9d8b9d 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -127,7 +127,7 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set) list_for_each_entry_reverse(trans, &net->nft.commit_list, list) { if (trans->msg_type == NFT_MSG_NEWSET && nft_trans_set(trans) == set) { - nft_trans_set_bound(trans) = true; + set->bound = true; break; } } @@ -6617,8 +6617,7 @@ static void nf_tables_abort_release(struct nft_trans *trans) nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans)); break; case NFT_MSG_NEWSET: - if (!nft_trans_set_bound(trans)) - nft_set_destroy(nft_trans_set(trans)); + nft_set_destroy(nft_trans_set(trans)); break; case NFT_MSG_NEWSETELEM: nft_set_elem_destroy(nft_trans_elem_set(trans), @@ -6691,8 +6690,11 @@ static int __nf_tables_abort(struct net *net) break; case NFT_MSG_NEWSET: trans->ctx.table->use--; - if (!nft_trans_set_bound(trans)) - list_del_rcu(&nft_trans_set(trans)->list); + if (nft_trans_set(trans)->bound) { + nft_trans_destroy(trans); + break; + } + list_del_rcu(&nft_trans_set(trans)->list); break; case NFT_MSG_DELSET: trans->ctx.table->use++; @@ -6700,8 +6702,11 @@ static int __nf_tables_abort(struct net *net) nft_trans_destroy(trans); break; case NFT_MSG_NEWSETELEM: + if (nft_trans_elem_set(trans)->bound) { + nft_trans_destroy(trans); + break; + } te = (struct nft_trans_elem *)trans->data; - te->set->ops->remove(net, te->set, &te->elem); atomic_dec(&te->set->nelems); break; -- 2.19.1