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@kernel.org, andrew+netdev@lunn.ch, horms@kernel.org,
razor@blackwall.org, roopa@nvidia.com, kuniyu@google.com,
petrm@nvidia.com, aroulin@nvidia.com, shuah@kernel.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org,
Ali Firas <alishmery18@gmail.com>
Subject: [PATCH net-next v5 1/8] vxlan: vnifilter: reject VNIs outside the 24-bit space
Date: Sun, 15 Nov 2026 01:14:05 +0300 [thread overview]
Message-ID: <20261114221412.255825-2-alishmery18@gmail.com> (raw)
In-Reply-To: <20261114221412.255825-1-alishmery18@gmail.com>
VXLAN_VNIFILTER_ENTRY_START and VXLAN_VNIFILTER_ENTRY_END are bare
NLA_U32, so neither is bounded before vxlan_process_vni_filter() hands
them to vxlan_vni_add_del():
int v, err = 0;
...
for (v = start_vni; v <= end_vni; v++)
v is int and end_vni is __u32, so the comparison is done unsigned. A
request carrying only START=0xffffffff has vni_start == vni_end ==
0xffffffff and looks like a single VNI; v is then -1, the comparison
promotes it to 0xffffffff and passes, v++ makes v 0, and the loop walks
the space upwards from there, creating a VNI node and a per-CPU stats
block per iteration under rtnl_lock. Any range ending at 0xffffffff
behaves the same way.
Separately, a VNI at or above VXLAN_N_VID is accepted and stored even
though the VXLAN header carries only 24 bits: vxlan_vni_field() shifts
without masking, so such an entry keeps its own rhashtable slot while
being truncated on the wire.
Range-validate both attributes against the 24-bit space, as vxlan_mdb.c
already does for its own VNI attributes. Since commit 599d0e97610f
("vxlan: vnifilter: validate the VXLAN_VNIFILTER_ENTRY nest") linked the
nest to this policy, an out-of-range endpoint is rejected during netlink
policy validation, before vxlan_process_vni_filter() runs and before
anything is allocated. Without that commit the range would be checked
one entry at a time, by the nla_parse_nested() in
vxlan_process_vni_filter(), after the earlier entries of the message had
been applied. How many VNIs a single in-range request may span is a
separate question, bounded later in this series by "vxlan: vnifilter:
bound the number of VNIs one request may touch"; that limit is not a
policy check and runs in the handler.
Make the loop counter u32 as well. With the range bounded it is no
longer what keeps the loop finite, but it drops the undefined signed
overflow past INT_MAX and matches the u32 vni that vxlan_vni_add() and
vxlan_vni_del() already take.
Found by code review: vxlan_mdb.c range-checks its VNI attributes
against VXLAN_N_VID, and the vnifilter policy did not. In QEMU on
net-next (production build, 2 vCPU), VNI 16777216 is accepted and
stored, and a lone START=0xffffffff wraps the loop counter and keeps
allocating VNI nodes under rtnl_lock.
This targets net-next without a Fixes tag and is not a backport
candidate. Reviewing the earlier posting of this range check alone,
Jakub said it was either a security fix needing a stronger check or
something making things slightly better that did not deserve Fixes or
stable.
Link: https://lore.kernel.org/netdev/20260905123900.23984eda@kernel.org/
Signed-off-by: Ali Firas <alishmery18@gmail.com>
---
v5: state the dependency on the applied nest patch, named by commit id
(Paolo and review of v3); name the cap patch by subject instead of "the
next patch"; the changelog no longer calls this "not a fix" and says how
the gap was found and what it did in QEMU (review of v4, sinfo bot);
policy lines wrapped to 80 columns; rebased. v4: no functional change;
rebased onto net-next.
drivers/net/vxlan/vxlan_vnifilter.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/vxlan/vxlan_vnifilter.c b/drivers/net/vxlan/vxlan_vnifilter.c
index 124ba47758e9..2b02f448c3e9 100644
--- a/drivers/net/vxlan/vxlan_vnifilter.c
+++ b/drivers/net/vxlan/vxlan_vnifilter.c
@@ -491,9 +491,15 @@ static int vxlan_vnifilter_dump(struct sk_buff *skb, struct netlink_callback *cb
return err;
}
+static const struct netlink_range_validation vni_filter_vni_range = {
+ .max = VXLAN_N_VID - 1,
+};
+
static const struct nla_policy vni_filter_entry_policy[VXLAN_VNIFILTER_ENTRY_MAX + 1] = {
- [VXLAN_VNIFILTER_ENTRY_START] = { .type = NLA_U32 },
- [VXLAN_VNIFILTER_ENTRY_END] = { .type = NLA_U32 },
+ [VXLAN_VNIFILTER_ENTRY_START] =
+ NLA_POLICY_FULL_RANGE(NLA_U32, &vni_filter_vni_range),
+ [VXLAN_VNIFILTER_ENTRY_END] =
+ NLA_POLICY_FULL_RANGE(NLA_U32, &vni_filter_vni_range),
[VXLAN_VNIFILTER_ENTRY_GROUP] = NLA_POLICY_EXACT_LEN(sizeof_field(struct iphdr, daddr)),
[VXLAN_VNIFILTER_ENTRY_GROUP6] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
};
@@ -914,7 +920,8 @@ static int vxlan_vni_add_del(struct vxlan_dev *vxlan, __u32 start_vni,
int cmd, struct netlink_ext_ack *extack)
{
struct vxlan_vni_group *vg;
- int v, err = 0;
+ int err = 0;
+ u32 v;
vg = rtnl_dereference(vxlan->vnigrp);
--
2.53.0
next prev parent reply other threads:[~2026-11-14 22:15 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-14 22:14 [PATCH net-next v5 0/8] vxlan: vnifilter: bound a single request and account per-VNI memory Ali Firas
2026-11-14 22:14 ` Ali Firas [this message]
2026-11-14 22:14 ` [PATCH net-next v5 2/8] vxlan: vnifilter: clamp the dumped VNI range to the request limit Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 3/8] vxlan: vnifilter: bound the number of VNIs one request may touch Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 4/8] vxlan: vnifilter: account per-VNI memory to memcg Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 5/8] vxlan: leave FDB state and flags unchanged when an update fails Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 6/8] vxlan: vnifilter: roll back a VNI add that fails Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 7/8] vxlan: vnifilter: account the default FDB entry to memcg Ali Firas
2026-11-14 22:14 ` [PATCH net-next v5 8/8] selftests: net: test the vxlan vnifilter request limit and dump replay Ali Firas
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=20261114221412.255825-2-alishmery18@gmail.com \
--to=alishmery18@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=aroulin@nvidia.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=petrm@nvidia.com \
--cc=razor@blackwall.org \
--cc=roopa@nvidia.com \
--cc=shuah@kernel.org \
/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®