netfilter: nf_tables: fix set double-free in abort path

[ 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 <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
(cherry picked from commit 25ddad73070c8fd15528fe804db90f0bda0dc6ad)
[Vegard: fix conflicts due to commit 59c38c80769a5528a617ea8857049b94a4b67041
 ("netfilter: nf_tables: use-after-free in failing rule with bound set")
 which included extra code for the NFT_MSG_NEWSETELEM case that was
 added upstream in commit 40ba1d9b4d19796afc9b7ece872f5f3e8f5e2c13
 ("netfilter: nf_tables: fix set double-free in abort path") and
 conflicts due to commit 63d921c3e52a14125f293efea5f78508c36668c1
 ("netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound
 set/chain") for the bind/true differences.]
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
2 files changed