]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: nf_tables: deactivate anonymous set from preparation phase
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 11 May 2023 15:41:43 +0000 (17:41 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 May 2023 09:11:48 +0000 (11:11 +0200)
[ backport for 4.14 of c1592a89942e9678f7d9c8030efa777c0d57edab ]

Toggle deleted anonymous sets as inactive in the next generation, so
users cannot perform any update on it. Clear the generation bitmask
in case the transaction is aborted.

The following KASAN splat shows a set element deletion for a bound
anonymous set that has been already removed in the same transaction.

[   64.921510] ==================================================================
[   64.923123] BUG: KASAN: wild-memory-access in nf_tables_commit+0xa24/0x1490 [nf_tables]
[   64.924745] Write of size 8 at addr dead000000000122 by task test/890
[   64.927903] CPU: 3 PID: 890 Comm: test Not tainted 6.3.0+ #253
[   64.931120] Call Trace:
[   64.932699]  <TASK>
[   64.934292]  dump_stack_lvl+0x33/0x50
[   64.935908]  ? nf_tables_commit+0xa24/0x1490 [nf_tables]
[   64.937551]  kasan_report+0xda/0x120
[   64.939186]  ? nf_tables_commit+0xa24/0x1490 [nf_tables]
[   64.940814]  nf_tables_commit+0xa24/0x1490 [nf_tables]
[   64.942452]  ? __kasan_slab_alloc+0x2d/0x60
[   64.944070]  ? nf_tables_setelem_notify+0x190/0x190 [nf_tables]
[   64.945710]  ? kasan_set_track+0x21/0x30
[   64.947323]  nfnetlink_rcv_batch+0x709/0xd90 [nfnetlink]
[   64.948898]  ? nfnetlink_rcv_msg+0x480/0x480 [nfnetlink]

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/netfilter/nf_tables.h
net/netfilter/nf_tables_api.c
net/netfilter/nft_dynset.c
net/netfilter/nft_lookup.c
net/netfilter/nft_objref.c

index fe56b2f825b4e04d0945017d2bdd17995c6bd125..2db486e9724c616e451408c649e734f37702bd1f 100644 (file)
@@ -462,6 +462,7 @@ struct nft_set_binding {
 };
 
 enum nft_trans_phase;
+void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set);
 void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
                              struct nft_set_binding *binding,
                              enum nft_trans_phase phase);
index 2f5b5d563e4d170d02c443b94564b429ffee7236..c683a45b8ae53079001284ebb5bcec1b10c0a801 100644 (file)
@@ -3420,12 +3420,24 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
 }
 EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
 
+void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
+{
+       if (set->flags & NFT_SET_ANONYMOUS)
+               nft_clear(ctx->net, set);
+
+       set->use++;
+}
+EXPORT_SYMBOL_GPL(nf_tables_activate_set);
+
 void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
                              struct nft_set_binding *binding,
                              enum nft_trans_phase phase)
 {
        switch (phase) {
        case NFT_TRANS_PREPARE:
+               if (set->flags & NFT_SET_ANONYMOUS)
+                       nft_deactivate_next(ctx->net, set);
+
                set->use--;
                return;
        case NFT_TRANS_ABORT:
index a20f1668328dc7c3d93d486e6111b36dcaa48c75..74e8fdaa34321383ab357380345db9bdc92223cb 100644 (file)
@@ -237,7 +237,7 @@ static void nft_dynset_activate(const struct nft_ctx *ctx,
 {
        struct nft_dynset *priv = nft_expr_priv(expr);
 
-       priv->set->use++;
+       nf_tables_activate_set(ctx, priv->set);
 }
 
 static void nft_dynset_destroy(const struct nft_ctx *ctx,
index 453f84c571662f4dfa23cfe51483088a04571cba..4fcbe51e88c762cfdbff0006407ce4a05c660600 100644 (file)
@@ -132,7 +132,7 @@ static void nft_lookup_activate(const struct nft_ctx *ctx,
 {
        struct nft_lookup *priv = nft_expr_priv(expr);
 
-       priv->set->use++;
+       nf_tables_activate_set(ctx, priv->set);
 }
 
 static void nft_lookup_destroy(const struct nft_ctx *ctx,
index 7e628f4f02b93c4534696c27ee0a525ce2c1769a..49a067a67e7231bc28649aa6fa2edd54185013ba 100644 (file)
@@ -168,7 +168,7 @@ static void nft_objref_map_activate(const struct nft_ctx *ctx,
 {
        struct nft_objref_map *priv = nft_expr_priv(expr);
 
-       priv->set->use++;
+       nf_tables_activate_set(ctx, priv->set);
 }
 
 static void nft_objref_map_destroy(const struct nft_ctx *ctx,