Heap buffer overflow via unchecked slot->len in VALE bridge forwarding: pkt_copy up to 65536 bytes into 2048-byte buffer
| Field | Value |
|---|---|
| ID | DF-0401 |
| Status | new |
| Severity | High |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H |
| CWE | CWE-122 Heap-based Buffer Overflow |
| File | sys/net/netmap/netmap_vale.c |
| Lines | 988, 1330-1346 |
| Area | net (netmap VALE switch) |
| Confidence | certain |
| Discovered | 2026-07-01 |
| Reported | pending |
Summary
The VALE software switch forwarding path copies packet data using a
user-supplied length field (slot->len) without validating it against the
netmap buffer size (~2048 bytes). An attacker who has mapped a VALE TX ring
via /dev/netmap can set slot->len to any value up to 65535, causing
pkt_copy/copyin to write up to 65536 bytes into a ~2048-byte kernel
heap buffer — a controlled heap overflow with attacker-chosen data and
length. The sibling code in netmap.c validates slot->len against
NETMAP_BDG_BUF_SIZE in three separate places, but this check was omitted
in the VALE forwarding fast path.
Root cause
nm_bdg_preflush() at sys/net/netmap/netmap_vale.c:988:
ft[ft_i].ft_len = slot->len; /* no bounds check */
slot->len is a uint16_t from the user-mapped shared ring (writable via
mmap of /dev/netmap). It can be any value 0–65535.
nm_bdg_flush() at sys/net/netmap/netmap_vale.c:1330-1346:
size_t len = (ft_p->ft_len + 63) & ~63; /* round up; up to 65536 */
...
dst = BDG_NMB(&dst_na->up, slot); /* ~2048-byte kernel buffer */
...
if (ft_p->ft_flags & NS_INDIRECT) {
if (copyin(src, dst, len)) { ... } /* line 1339: writes len bytes */
} else {
pkt_copy(src, dst, (int)len); /* line 1345: writes len bytes */
}
The destination dst is a netmap buffer of NETMAP_BDG_BUF_SIZE (default
2048 bytes). With slot->len = 65535, len rounds to 65536, writing 32×
the buffer capacity.
The validation that exists in sibling code:
- netmap.c:748: if (slot->len < 14 || slot->len > NETMAP_BDG_BUF_SIZE(...))
- netmap.c:1124: same check
- netmap.c:2017: if (kring->nr_hwavail >= lim) (different but related)
None of these checks exist in the VALE forwarding path.
Threat model & preconditions
- Attacker position: local user with access to
/dev/netmap(mode 0660 root:wheel, or root in a jail where netmap is exposed). - Privileges gained or impact: kernel heap corruption with full attacker-controlled data and length. Enables kernel code execution, KASLR bypass, and jail escape.
- Required config: netmap loaded (
kldload netmap), a VALE bridge created. - Reachability:
mmapthe VALE TX ring, setslot->lento a large value, and trigger forwarding by sending packets through the bridge.
Proof of concept
PoC source: findings/poc/DF-0401/poc.c
Build & run
cc -o poc poc.c -lnetmap ./poc vale1:0 # requires /dev/netmap access
Expected output
Fatal trap 12: page fault while in kernel mode KDB: stack backtrace: #1 pkt_copy at netmap.c:... #2 nm_bdg_flush at netmap_vale.c:1345 #3 netmap_bwrap_intr_notify at netmap_vale.c:...
Impact
- Kernel heap overflow with 100% attacker-controlled data and length.
- Heap grooming of the netmap buffer slab enables controlled overwrite of adjacent kernel objects, leading to arbitrary kernel code execution.
- In a jail with exposed
/dev/netmap, this is a reliable jail escape to host root. - The overflow also over-reads the source buffer (
srcviaBDG_NMB), leaking adjacent netmap buffer contents.
Recommended fix
Validate slot->len in nm_bdg_preflush() before storing it:
--- a/sys/net/netmap/netmap_vale.c
+++ b/sys/net/netmap/netmap_vale.c
@@ -985,6 +985,9 @@
struct netmap_slot *slot = &ring->slot[j];
char *buf;
+ if (slot->len > NETMAP_BDG_BUF_SIZE(na->up.nm_mem)) {
+ D("dropping oversize slot len %d", slot->len);
+ continue;
+ }
ft[ft_i].ft_len = slot->len;
This mirrors the existing check at netmap.c:748.
References
NETMAP_BDG_BUF_SIZEis defined innetmap_kern.hand defaults to 2048.- The sibling validation in
netmap.cat lines 748, 1124, 2017 proves the intended contract: slot lengths must be bounded by the buffer size.
Timeline
- 2026-07-01 Discovered during automated audit.
- 2026-07-01 Reported to DragonFlyBSD security contact (pending).