Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp526650yba; Mon, 1 Apr 2019 11:05:25 -0700 (PDT) X-Google-Smtp-Source: APXvYqzMLED1v9qCIHhZs+gQA7IUYXg14bi93TU9sFnIwYDaDW2Lz2GKDmayxYDqwkIx2l7X8Myx X-Received: by 2002:a63:4e57:: with SMTP id o23mr58597478pgl.368.1554141925533; Mon, 01 Apr 2019 11:05:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554141925; cv=none; d=google.com; s=arc-20160816; b=IoGapsqU3zBFZFJn+gb9ADC8FgPG5pmyz5XeJCYp4x/Eh1Ip/EEvVAxL4BeYyJMSKg 9MHQlTBfjRDSSYh4HvZ/vIHQ5j/vrP7CgqS02FDq9TJCwITUHNv7Zi5KeWUV1jTDicpX BD1j9J82P6e3KKkSr70AxaJaigwhf5yuVND+A1p9Xf3cdRCCqRzUZqyy6N3LfqmT0FSX Dxn1QvCc5RpSCVOASXEpRpp5TgpCYR0Vco3onqS6fU1J7N9gMMOQpVRic2OBkqXtg7IV ufqr3lpqjxAZg3Po8KLUXJdWfxvToOTB9x9JxN7aUevC93NfACbV+TMaNlxsgqM8YokM 3QTQ== 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=5iJAkNTK8OIeW+9L6tsmpNipXOvhuNC0a6INhrfpEuY=; b=NfawiqHLrt2tMIm65ZMVpNOP72YCnSLcQcMHsDNp20GYUhC41pQLVwWXBf6IJPdm5K Rnxzh3zAGFC48Wry9q0+4DaHLSydWKsn9VN/J7vhEbYMZDSr/pK1sJ5Xs+gKT4Qlg5r8 2AFSH2DKJVmBnxEo69AVfYXj2Rw7A3AumkBDYZct8QpTaw7eTzOFStPwnO6Z/DRR6/A/ C31GvPH3A9lm0VeHtrNDkjUQ439bw8VdtSiUA08uC70tHk+jnLBBVzs9Jj4w2TvHebCH klqpGsy5FCM3+lGPR+DKT6hq1ibBYNtp3aOQZ4eBiAewyY5zeVPueLjD5+pvWnaWdoNK Kl6g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=iTF3Z4gB; 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 g123si7204593pfc.58.2019.04.01.11.05.09; Mon, 01 Apr 2019 11:05:25 -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=iTF3Z4gB; 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 S1730120AbfDAROI (ORCPT + 99 others); Mon, 1 Apr 2019 13:14:08 -0400 Received: from mail.kernel.org ([198.145.29.99]:36972 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730653AbfDAROB (ORCPT ); Mon, 1 Apr 2019 13:14:01 -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 D999E2171F; Mon, 1 Apr 2019 17:04:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1554138247; bh=ofLYgo2g1HPJlw4IigGPZi62VPq4brPNNhSZbPjqlBU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iTF3Z4gBqvFsptPnjWbJwL9zRwCQhqdyAEFefle+z3eXqJKLElun00qbnPw8jwRYk 1DOp6y/rsNxGm1gqA2m3OsTrq7bTGPhVblCTgvPxywHZ54LI+CnkEGtTrOhGzN5JGo 2xLj4s7/Ij38K8nQiyapkRVRkXtSDLh6H0EVWmkI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Florian Westphal , Pablo Neira Ayuso , Sasha Levin Subject: [PATCH 5.0 003/146] netfilter: nf_tables: fix set double-free in abort path Date: Mon, 1 Apr 2019 19:00:15 +0200 Message-Id: <20190401170048.726418947@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401170048.449559024@linuxfoundation.org> References: <20190401170048.449559024@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore 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 5.0-stable review patch. If anyone has any objections, please let me know. ------------------ [ 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 Signed-off-by: Greg Kroah-Hartman --- include/net/netfilter/nf_tables.h | 6 ++---- net/netfilter/nf_tables_api.c | 17 +++++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) --- 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; --- 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 str 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(stru 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 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 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;