From: Taylor Bates <tmbates12@gmail.com>
To: Donald Hunter <donald.hunter@gmail.com>,
Jakub Kicinski <kuba@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Jiri Pirko <jiri@resnulli.us>,
Stanislav Fomichev <sdf@fomichev.me>
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
Taylor Bates <tmbates12@gmail.com>
Subject: [PATCH net-next 2/4] tools: ynl: reject zero-length attributes instead of looping forever
Date: Tue, 08 Sep 2026 19:45:08 -0400 [thread overview]
Message-ID: <20260908-ynl-robustness-v1-2-f255214c0f30@gmail.com> (raw)
In-Reply-To: <20260908-ynl-robustness-v1-0-f255214c0f30@gmail.com>
The following bug was found in the ynl tooling while parsing
MDBA_ROUTER_PORT entries on a real bridge device with IGMP snooping
enabled, not through fuzzing.
This occurs if the parser walks into a nested attribute containing a
headerless entry (such as MDBA_ROUTER_PORT) and reads the ifindex
parameter as a length, rather than data.
If the parser reads this now misaligned data and parses a field
containing a zero byte, it will run in an infinite loop. It will
continuously append empty attribute objects and consume 100% CPU until
it exhausts the system's memory.
The most straightforward way to trigger this systematically is as
follows:
1. Create a bridge device with multicast_vlan_snooping enabled.
2. Add a permanent multicast router port to the bridge that lands
on ifindex 8. (The mcast_router 2 state ensures that its timer
is zero.)
3. Feed NlAttrs() from pyynl the MDBA_ROUTER_PORT netlink payload.
This example creates a bytes object that reproduces the same shape
as the payload:
msg = struct.pack('HH', 8, 1) + struct.pack('I', 0xdeadbeef)
msg += struct.pack('HH', 0, 2)
NlAttrs(msg)
Fixes: e4b48ed460d3 ("tools: ynl: add a completely generic client")
Signed-off-by: Taylor Bates <tmbates12@gmail.com>
---
Full reproducer, run under "unshare -Urn" so the namespace starts with
only lo and ifindex allocation restarts from 1:
ip link add br0 type bridge vlan_filtering 1 mcast_snooping 1 \
mcast_vlan_snooping 1
ip link set br0 up
n=0
while :; do
n=$((n + 1))
ip link add d$n type dummy
idx=$(ip -o link show d$n | cut -d: -f1 | tr -d ' ')
[ $((idx & 0xffff)) = 8 ] && break
[ $n -gt 200 ] && { echo "gave up"; exit 1; }
done
ip link set d$n master br0
ip link set d$n up
bridge vlan add dev d$n vid 10
bridge vlan set dev d$n vid 10 mcast_router 2
bridge vlan global set dev br0 vid 10 mcast_snooping 1
The BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS payload the kernel then sends:
34 00 02 00 MDBA_ROUTER, len 52
30 00 01 00 MDBA_ROUTER_PORT, len 48
08 00 00 00 bare ifindex 8, written by nla_put_nohdr()
08 00 01 00 MDBA_ROUTER_PATTR_TIMER, len 8
00 00 00 00 timer value, 0 for a permanent router
Read as a header, the ifindex claims eight bytes and consumes the
MDBA_ROUTER_PATTR_TIMER header along with itself. The walk then lands on
the timer value, four zero bytes, and nla_len is 0. full_len is 0 too,
so the offset never advances.
---
tools/net/ynl/pyynl/lib/ynl.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/net/ynl/pyynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py
index 8682bf588e1f..375a15d83a34 100644
--- a/tools/net/ynl/pyynl/lib/ynl.py
+++ b/tools/net/ynl/pyynl/lib/ynl.py
@@ -317,6 +317,10 @@ class NlAttrs:
while offset < len(msg):
attr = NlAttr(msg, offset)
+ if attr.full_len < 4:
+ raise YnlException(
+ f'Malformed attribute at offset {offset}: '
+ f'length {attr.payload_len} is shorter than the header')
offset += attr.full_len
self.attrs.append(attr)
--
2.55.0
next prev parent reply other threads:[~2026-09-08 23:45 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 23:45 [PATCH net-next 0/4] netlink: fix ynl spec tooling robustness bugs Taylor Bates
2026-09-08 23:45 ` [PATCH net-next 1/4] netlink: specs: fix duplicate if/then keys in netlink-raw schema Taylor Bates
2026-09-08 23:45 ` Taylor Bates [this message]
2026-09-11 2:25 ` [PATCH net-next 2/4] tools: ynl: reject zero-length attributes instead of looping forever Jakub Kicinski
2026-09-08 23:45 ` [PATCH net-next 3/4] tools: ynl: stop find_kernel_root() spinning at the filesystem root Taylor Bates
2026-09-11 2:26 ` Jakub Kicinski
2026-09-08 23:45 ` [PATCH net-next 4/4] tools: ynl: fix uapi generation for anonymous enums with documented entries Taylor Bates
2026-09-11 2:27 ` Jakub Kicinski
2026-09-11 2:23 ` [PATCH net-next 0/4] netlink: fix ynl spec tooling robustness bugs Jakub Kicinski
2026-09-12 17:35 ` tmbates12
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=20260908-ynl-robustness-v1-2-f255214c0f30@gmail.com \
--to=tmbates12@gmail.com \
--cc=davem@davemloft.net \
--cc=donald.hunter@gmail.com \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jiri@resnulli.us \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@fomichev.me \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.