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>
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,
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)
{
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);
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;