From: Ali Firas <alishmery18@gmail.com>
To: netdev@vger.kernel.org, idosch@nvidia.com
Cc: kuba@kernel.org, pabeni@redhat.com, davem@davemloft.net,
edumazet@google.com, andrew+netdev@lunn.ch, razor@blackwall.org,
roopa@nvidia.com, linux-kernel@vger.kernel.org,
Ali Firas <alishmery18@gmail.com>
Subject: [PATCH net 2/3] vxlan: vnifilter: account VNI node and per-CPU stats to memcg
Date: Wed, 9 Sep 2026 12:26:44 +0300 [thread overview]
Message-ID: <20260909092645.3105263-3-alishmery18@gmail.com> (raw)
In-Reply-To: <20260909092645.3105263-1-alishmery18@gmail.com>
vxlan_vni_alloc() allocates a struct vxlan_vni_node and a per-CPU stats
block for every VNI, both with plain GFP_KERNEL. Neither carries
__GFP_ACCOUNT, so the memory is not charged to the cgroup of the process
that asked for it.
With the range of a single request now capped, one message can no longer
exhaust memory on its own. This is no longer the primary defence, but it
still matters: nothing limits how many capped requests a task may issue,
so an unprivileged user in a user+network namespace can still accumulate
an arbitrary number of VNIs, 4096 at a time, and none of it is charged
to them.
Per VNI the add path allocates 128 bytes of slab, an exact fit in
kmalloc-128 and measured at exactly 1.000 objects per VNI, plus 64 bytes
per possible CPU for the stats block. The per-CPU term is the one that
grows: 256 bytes per VNI on a 2-CPU host, but 4.2 KB per VNI on a
64-CPU one.
Charging both allocations confines the damage to the caller's cgroup.
The kill becomes CONSTRAINT_MEMCG with oom_memcg set to that cgroup,
memory.stat attributes both the slab and the percpu bytes to it, and the
host survives what previously took it down.
One limitation is worth stating plainly: try_charge() reclaims and then
invokes the memcg OOM killer rather than returning -ENOMEM, so the
request does not fail gracefully, the caller is killed. Accounting
confines the blast radius, it does not turn this into a clean error.
For a caller not under a memcg limit there is no change. With no limit
set, the same workload installs the same number of VNIs to within 0.4%,
fails at the same point, and a bounded add of 1,000,000 VNIs costs an
identical 128 bytes of slab and 64 bytes per CPU. The objects simply
move from kmalloc-128 to kmalloc-cg-128.
Conditions to recreate the bug:
- CONFIG_VXLAN, CONFIG_MEMCG.
- Unprivileged user in a fresh user+network namespace (unshare -Urn),
or root with CAP_NET_ADMIN.
- Create a vnifilter-enabled vxlan device and add VNIs in a loop
(e.g. ip link add vx0 type vxlan external vnifilter dstport 4789,
then repeated bridge vni add ... commands) while watching a
memcg-limited cgroup: system slab and percpu grow far faster than
memory.current, pinning kernel memory outside memcg charging.
Fixes: f9c4bb0b245c ("vxlan: vni filtering support on collect metadata device")
Assisted-by: LLM
Signed-off-by: Ali Firas <alishmery18@gmail.com>
---
drivers/net/vxlan/vxlan_vnifilter.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
index f18ce0e1e741..3d6718ec3f55 100644
--- a/drivers/net/vxlan/vxlan_vnifilter.c
+++ b/drivers/net/vxlan/vxlan_vnifilter.c
@@ -703,10 +703,11 @@ static struct vxlan_vni_node *vxlan_vni_alloc(struct vxlan_dev *vxlan,
{
struct vxlan_vni_node *vninode;
- vninode = kzalloc_obj(*vninode);
+ vninode = kzalloc_obj(*vninode, GFP_KERNEL_ACCOUNT);
if (!vninode)
return NULL;
- vninode->stats = netdev_alloc_pcpu_stats(struct vxlan_vni_stats_pcpu);
+ vninode->stats = __netdev_alloc_pcpu_stats(struct vxlan_vni_stats_pcpu,
+ GFP_KERNEL_ACCOUNT);
if (!vninode->stats) {
kfree(vninode);
return NULL;
--
2.53.0
next prev parent reply other threads:[~2026-09-09 9:27 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260907141001.GA708129@shredder>
2026-09-09 9:26 ` [PATCH net 0/3] vxlan: vnifilter: bound the VNI range per request Ali Firas
2026-09-09 9:26 ` [PATCH net 1/3] vxlan: vnifilter: limit the VNI range of a single request Ali Firas
2026-09-10 9:38 ` netdev-bot+sashiko
2026-09-15 0:31 ` Jakub Kicinski
2026-09-09 9:26 ` Ali Firas [this message]
2026-09-10 9:38 ` [PATCH net 2/3] vxlan: vnifilter: account VNI node and per-CPU stats to memcg netdev-bot+sashiko
2026-09-15 0:31 ` Jakub Kicinski
2026-09-09 9:26 ` [PATCH net 3/3] selftests: net: test the vxlan vnifilter VNI range limit Ali Firas
2026-09-10 9:39 ` netdev-bot+sashiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260909092645.3105263-3-alishmery18@gmail.com \
--to=alishmery18@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=razor@blackwall.org \
--cc=roopa@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®