https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=297437
Bug ID: 297437
Summary: netmap: unchecked NR_REG_NULL slot count overflows
ring allocation size
Product: Base System
Version: 14.4-STABLE
Hardware: amd64
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: [email protected]
Reporter: [email protected]
Created attachment 273624
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=273624&action=edit
Deterministic two-call RX slot-count overflow reproducer
Overview
========
The NETMAP_REQ_REGISTER path for an NR_REG_NULL adapter accepts
user-controlled TX/RX ring and slot counts without applying the geometry
bounds used by other netmap adapter types.
A slot count of 0xfffffffe reaches netmap_mem2_rings_create(), where the ring
allocation length is calculated in a 32-bit u_int. The multiplication and
addition wrap to a small allocation size. The kernel then initializes or
traverses the allocation using the original slot count, causing an
out-of-bounds kernel memory access and panic.
Both the RX-slot and TX-slot variants reproduced deterministically.
Tested environment
==================
Operating system: FreeBSD 14.4-STABLE
Architecture: amd64
Kernel ident: SYZKALLER
Base image source revision: cc921088d9ee
Base image date: 2026-05-14
Virtualization: QEMU/KVM
The kernel is based on the FreeBSD 14.4-STABLE amd64 image identified by
revision cc921088d9ee, with the SYZKALLER kernel
configuration/instrumentation.
The reported reproductions were performed as root in clean snapshot VMs.
Unprivileged-user and jail reachability have not been tested.
Reproducer
==========
The attached RX .syz reproducer executes two calls:
r0 = openat$netmap(...)
ioctl$NIOCCTRL(r0, NIOCCTRL, {
nr_reqtype = NETMAP_REQ_REGISTER,
nr_name = "null-overflow-rx",
nr_mode = NR_REG_NULL,
nr_mem_id = 1,
nr_tx_slots = 0x10,
nr_rx_slots = 0xfffffffe
})
The attached TX variant exchanges the slot counts:
nr_tx_slots = 0xfffffffe
nr_rx_slots = 0x10
The RX program panicked on its first execution in two independent cold boots.
The TX program panicked on its first execution in a third independent cold
boot.
Observed result
===============
All three deterministic runs produced:
panic: vm_fault_lookup: fault on nofault entry,
addr: 0xfffffe007bc00000
Relevant stack:
panic
vm_fault
vm_fault_trap
trap_pfault
netmap_mem_rings_create+0x84
netmap_do_regif+0x5b3
netmap_ioctl+0x1cf0
freebsd_netmap_ioctl+0xa5
devfs_ioctl
vn_ioctl
kern_ioctl
sys_ioctl
The same fault address was observed in both RX cold-boot runs and in the
independent TX cold-boot run.
Expected result
===============
The kernel should reject or safely bound invalid ring geometry. A
user-controlled slot count must not overflow the kernel allocation length or
cause an out-of-bounds kernel memory access.
Root cause
==========
netmap_get_null_na() copies all four geometry values from the
nmreq_register request without applying the nm_bound_var() checks used by
VALE, pipe, and monitor adapters:
nna->up.num_tx_rings = req->nr_tx_rings;
nna->up.num_rx_rings = req->nr_rx_rings;
nna->up.num_tx_desc = req->nr_tx_slots;
nna->up.num_rx_desc = req->nr_rx_slots;
The minimal reproducer selects the existing default allocator with
nr_mem_id = 1.
The unchecked slot count is copied to kring->nkr_num_slots. In
netmap_mem2_rings_create(), the allocation length is calculated using
32-bit u_int variables:
u_int len, ndesc;
ndesc = kring->nkr_num_slots;
len = sizeof(struct netmap_ring) +
ndesc * sizeof(struct netmap_slot);
For ndesc = 0xfffffffe, this expression wraps in 32 bits. A small allocation
can consequently be returned and later accessed as if it contained almost
UINT32_MAX slots.
This is an arithmetic and validation bug, rather than a normal allocation
failure.
Suggested fix
=============
Two layers of validation are suggested:
1. Apply explicit ring-count and slot-count limits in netmap_get_null_na(),
consistent with the bounds applied to other software adapter types.
2. Add a common integer-overflow check in netmap_mem2_rings_create() before
calculating:
sizeof(struct netmap_ring) +
ndesc * sizeof(struct netmap_slot)
A proposed stable/14 patch is attached. It has not yet been tested against
FreeBSD main and is provided for discussion rather than as a final reviewed
fix.
Impact
======
The demonstrated impact is a deterministic local kernel panic and an
out-of-bounds kernel memory access caused by an integer-overflowed allocation
size.
Because the issue involves kernel memory corruption, a stronger security
impact may be possible, but exploitability has not been assessed.
Triggering the issue requires access to /dev/netmap. The reproductions
reported here were performed as root. Default unprivileged and jail
reachability have not been tested.
Affected branches
=================
The issue was reproduced on stable/14. Source review found the same relevant
unchecked NULL-adapter geometry and 32-bit allocation calculation in the
corresponding current netmap code, but the panic has not yet been reproduced
on FreeBSD main.
Reproduction evidence
=====================
Three independent clean cold-boot runs are attached:
1. RX slot overflow, first run:
SHA-256:
ca04e711334b9d78d4ee501eae130678b9e7e5b89a193b2077569b0f1b7dedae
2. RX slot overflow, second run:
SHA-256:
b4b51888a18eb6c37d0b4b2b48abbfa08283f8e8c7f61ffe2eebaf8fcb13bb2
3. TX slot overflow:
SHA-256:
f7cff58b82631f92dc2850b0c9e827b4118084431b5367980ecbefd2ddb484eb
Tools used
==========
The issue was discovered and reproduced using syzkaller with locally
developed FreeBSD netmap syscall descriptions and structured seed programs.
AI-assisted tools were used to organize experiment artifacts, inspect crash
logs, group related crash signatures, and help draft this report. The
reproduction results, fault locations, arithmetic analysis, and source-level
claims were manually checked against the saved kernel image and source tree.
--
You are receiving this mail because:
You are the assignee for the bug.