netfilter: nf_tables: deactivate anonymous set from preparation phase
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 2 May 2023 08:25:24 +0000 (10:25 +0200)
committerSalvatore Bonaccorso <carnil@debian.org>
Fri, 14 Jul 2023 20:24:08 +0000 (21:24 +0100)
Origin: https://git.kernel.org/linus/c1592a89942e9678f7d9c8030efa777c0d57edab
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2023-32233

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>
Gbp-Pq: Topic bugfix/all
Gbp-Pq: Name netfilter-nf_tables-deactivate-anonymous-set-from-pr.patch

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 e66fee99ed3ea114c7d42c43298b1ccfcd0aa57d..564fbe0c865fdc59d994578314143d687154e919 100644 (file)
@@ -507,6 +507,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 2143edafba772aeeb23f47265b0653bdfab7dab1..695b7ea55f183311fcb7df582fe7de240454771f 100644 (file)
@@ -4479,12 +4479,24 @@ static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
        }
 }
 
+void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
+{
+       if (nft_set_is_anonymous(set))
+               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 (nft_set_is_anonymous(set))
+                       nft_deactivate_next(ctx->net, set);
+
                set->use--;
                return;
        case NFT_TRANS_ABORT:
index 8c45e01fecdd82e7929beaef01e626b887f15deb..038588d4d80e112f01df1513c38b91f4a852c582 100644 (file)
@@ -233,7 +233,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 b0f558b4fea5410184d639501c8cea9578bcc862..8bc008ff00cb742ee026b7179f90e1068be96510 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 bc104d36d3bb28588f401d2f3a74f8c324abc296..25157d8cc2504885ec6aaccfbfbc2a496fd6ba15 100644 (file)
@@ -180,7 +180,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,