summaryrefslogtreecommitdiffstats
path: root/net/netfilter/nft_quota.c
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2024-05-08 14:52:47 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2024-05-10 11:13:45 +0200
commitfa23e0d4b756d25829e124d6b670a4c6bbd4bf7e (patch)
treeefefff28ec56690cc72b08c7812d383b6a538ede /net/netfilter/nft_quota.c
parenta8a388c2aae490c08d59a6c15d15a968fea5089a (diff)
downloadlinux-fa23e0d4b756d25829e124d6b670a4c6bbd4bf7e.tar.gz
linux-fa23e0d4b756d25829e124d6b670a4c6bbd4bf7e.tar.bz2
linux-fa23e0d4b756d25829e124d6b670a4c6bbd4bf7e.zip
netfilter: nf_tables: allow clone callbacks to sleep
Sven Auhagen reports transaction failures with following error: ./main.nft:13:1-26: Error: Could not process rule: Cannot allocate memory percpu: allocation failed, size=16 align=8 atomic=1, atomic alloc failed, no space left This points to failing pcpu allocation with GFP_ATOMIC flag. However, transactions happen from user context and are allowed to sleep. One case where we can call into percpu allocator with GFP_ATOMIC is nft_counter expression. Normally this happens from control plane, so this could use GFP_KERNEL instead. But one use case, element insertion from packet path, needs to use GFP_ATOMIC allocations (nft_dynset expression). At this time, .clone callbacks always use GFP_ATOMIC for this reason. Add gfp_t argument to the .clone function and pass GFP_KERNEL or GFP_ATOMIC flag depending on context, this allows all clone memory allocations to sleep for the normal (transaction) case. Cc: Sven Auhagen <sven.auhagen@voleatech.de> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nft_quota.c')
-rw-r--r--net/netfilter/nft_quota.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c
index 3ba12a7471b0..9b2d7463d3d3 100644
--- a/net/netfilter/nft_quota.c
+++ b/net/netfilter/nft_quota.c
@@ -233,7 +233,7 @@ static void nft_quota_destroy(const struct nft_ctx *ctx,
return nft_quota_do_destroy(ctx, priv);
}
-static int nft_quota_clone(struct nft_expr *dst, const struct nft_expr *src)
+static int nft_quota_clone(struct nft_expr *dst, const struct nft_expr *src, gfp_t gfp)
{
struct nft_quota *priv_dst = nft_expr_priv(dst);
struct nft_quota *priv_src = nft_expr_priv(src);
@@ -241,7 +241,7 @@ static int nft_quota_clone(struct nft_expr *dst, const struct nft_expr *src)
priv_dst->quota = priv_src->quota;
priv_dst->flags = priv_src->flags;
- priv_dst->consumed = kmalloc(sizeof(*priv_dst->consumed), GFP_ATOMIC);
+ priv_dst->consumed = kmalloc(sizeof(*priv_dst->consumed), gfp);
if (!priv_dst->consumed)
return -ENOMEM;