diff options
author | Florian Westphal <fw@strlen.de> | 2024-05-08 14:52:47 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2024-05-10 11:13:45 +0200 |
commit | fa23e0d4b756d25829e124d6b670a4c6bbd4bf7e (patch) | |
tree | efefff28ec56690cc72b08c7812d383b6a538ede /net/netfilter/nft_quota.c | |
parent | a8a388c2aae490c08d59a6c15d15a968fea5089a (diff) | |
download | linux-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.c | 4 |
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; |