]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: nft_dynset: honor stateful expressions in set definition
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 9 Jan 2025 15:45:38 +0000 (16:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 1 Feb 2025 17:22:18 +0000 (18:22 +0100)
commit fca05d4d61e65fa573a3768f9019a42143c03349 upstream.

If the set definition contains stateful expressions, allocate them for
the newly added entries from the packet path.

[ This backport includes nft_set_elem_expr_clone() which has been
  taken from 8cfd9b0f8515 ("netfilter: nftables: generalize set
  expressions support") and skip redundant expressions when set
  already provides it per ce5379963b28 ("netfilter: nft_dynset: dump
  expressions when set definition contains no expressions") ]

Fixes: 65038428b2c6 ("netfilter: nf_tables: allow to specify stateful expression in set definition")
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

index 31edeafeda77a35ff05682d0451ccdf9c2cfe11f..cb13e604dc347b0c6883a713f371e3150d0a9190 100644 (file)
@@ -734,6 +734,8 @@ void *nft_set_elem_init(const struct nft_set *set,
                        const struct nft_set_ext_tmpl *tmpl,
                        const u32 *key, const u32 *key_end, const u32 *data,
                        u64 timeout, u64 expiration, gfp_t gfp);
+int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
+                           struct nft_expr **pexpr);
 void nft_set_elem_destroy(const struct nft_set *set, void *elem,
                          bool destroy_expr);
 void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
index 2bd1c7e7edc3744ee990c0226bda8862d11f8eec..28ea2ed3f3375b8fdda154e927aab919a3d651f7 100644 (file)
@@ -5548,6 +5548,29 @@ static int nft_set_elem_expr_setup(struct nft_ctx *ctx,
        return 0;
 }
 
+int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
+                           struct nft_expr **pexpr)
+{
+       struct nft_expr *expr;
+       int err;
+
+       expr = kzalloc(set->expr->ops->size, GFP_KERNEL);
+       if (!expr)
+               goto err_expr;
+
+       err = nft_expr_clone(expr, set->expr, GFP_KERNEL);
+       if (err < 0) {
+               kfree(expr);
+               goto err_expr;
+       }
+       *pexpr = expr;
+
+       return 0;
+
+err_expr:
+       return -ENOMEM;
+}
+
 static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                            const struct nlattr *attr, u32 nlmsg_flags)
 {
index 9461293182e85e345a9c22211acc33335bddef3e..fc81bda6cc6b64e0a099ec8865845a7c10c3d9ac 100644 (file)
@@ -192,6 +192,10 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
                        err = -EOPNOTSUPP;
                        goto err_expr_free;
                }
+       } else if (set->expr) {
+               err = nft_set_elem_expr_clone(ctx, set, &priv->expr);
+               if (err < 0)
+                       return err;
        }
 
        nft_set_ext_prepare(&priv->tmpl);
@@ -272,7 +276,8 @@ static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr)
                         nf_jiffies64_to_msecs(priv->timeout),
                         NFTA_DYNSET_PAD))
                goto nla_put_failure;
-       if (priv->expr && nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr))
+       if (!priv->set->expr && priv->expr &&
+           nft_expr_dump(skb, NFTA_DYNSET_EXPR, priv->expr))
                goto nla_put_failure;
        if (nla_put_be32(skb, NFTA_DYNSET_FLAGS, htonl(flags)))
                goto nla_put_failure;