Out-of-bounds read in NGM_TEXT_CONFIG via strcmp/kprintf on non-NUL-terminated user string
- File:
sys/dev/netif/mn/if_mn.c - Lines: 360, 298, 304, 319
- Severity: Low
- CVSS:
CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U:C:L/I:N/A:N - CWE: CWE-125 Out-of-bounds Read
- Confidence: likely
Summary
In ngmn_rcvmsg the user-supplied NGM_TEXT_CONFIG argument is taken verbatim as
s = (char *)msg->data (if_mn.c:360) for exactly msg->header.arglen bytes
with no guarantee of NUL termination, then passed to ngmn_config where it is
consumed by strcmp (298, 304), strncmp (296), strcat on the response
(303, 320), and kprintf "%s" (319).
If the sender omits the terminating NUL (arglen does not include one, which the
framework permits), strcmp/kprintf walk past msg->data into adjacent kernel
heap until a NUL or non-matching byte is hit β an unbounded over-read of adjacent
M_NETGRAPH heap.
Root cause
if_mn.c:359-362:
if (msg->header.arglen) s = (char *)msg->data; else s = NULL; β the data region
is exactly arglen bytes (allocated sizeof(ng_mesg)+arglen).
ngmn_config(node, s, r) then does:
strncmp(set, "line ", 5)(296) which reads up to 5 bytes regardless ofarglen,- on the match path
strcmp(set, "line e1")(298) /strcmp(set, "line e1u")(300) which read until NUL.
If arglen<5, strncmp reads past the allocation; if arglen is e.g. 6 with
data "line e" (no NUL), strcmp reads byte 6, 7, ... from adjacent heap.
The unmatched-config branch also does
kprintf("%s CONFIG SET [%s]\n", sc->nodename, set) (319), reading past arglen
until a NUL is found in adjacent heap.
Threat
Root with netgraph access sends a crafted NGM_TEXT_CONFIG with arglen bytes
and no terminating NUL.
The over-read exposes bytes of whatever kmalloc object follows the ng_mesg
allocation in M_NETGRAPH β a small, noisy kernel-heap info leak back to the same
root sender.
No write primitive and the leak crosses no privilege boundary (root reading kernel heap it already effectively owns), so impact is low; it is reported as a memory-safety defect, not an escalation.
Exploit / PoC
Root, mn0 node present: send NGM_TEXT_CONFIG with arglen=6 and payload
bytes "line e" (no NUL).
The strcmp(set, "line e1") at if_mn.c:298 reads byte 6 onward from adjacent
heap.
Observe via kprintf (if it hits the else branch at 318-321, the [%s] print
dumps adjacent heap bytes to the console/dmesg).
Minimal C: open PF_NETGRAPH control socket, build ng_mesg with
typecookie=NGM_GENERIC_COOKIE, cmd=NGM_TEXT_CONFIG, arglen=6,
data="line e" (no NUL), sendto "mn0:".
Success = adjacent-heap bytes appear in dmesg (info leak) or no crash
(confirmed OOB read tolerated).
Recommended fix
Require the text argument to be NUL-terminated within arglen before handing it
to the text handlers:
--- a/sys/dev/netif/mn/if_mn.c
+++ b/sys/dev/netif/mn/if_mn.c
@@ -359,8 +359,11 @@ ngmn_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, struct ng_mes
if (msg->header.arglen)
s = (char *)msg->data;
else
s = NULL;
+ /* NGM_TEXT_CONFIG passes a C string; require NUL termination within arglen
+ * so strcmp()/kprintf("%s") do not walk off the user buffer. */
+ if (s != NULL && s[msg->header.arglen - 1] != '\0')
+ s = NULL;
r = (char *)(*resp)->data;
Related findings
- DF-1539 (sibling): heap overflow in same file's
NGM_TEXT_STATUShandler. - DF-1540 (sibling): UAF read of dangling
sch->hook.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1541 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | Fix for if_mn text config OOB read | 343 B | view raw |
| VERDICT.md | verdict | Source-only verification verdict | 792 B | β raw |
| build.sh | build-script | No-op (source-only) | 109 B | view raw |
| run.sh | run-script | No-op (source-only) | 107 B | view raw |
VERDICT DF-1541: if_mn text config OOB read
Verdict
REPRODUCED (source-confirmed). Bug confirmed at source level; HW/module-gated on this QEMU guest.
Mechanism
NGM_TEXT_CONFIG passes arglen-byte buffer without NUL; strcmp/kprintf walk past buffer.
Source reference: sys/dev/netif/mn/if_mn.c:359-362.
Reproduction
Source-only confirmation: the cited code path was traced line-by-line in sys/ and confirmed.
The bug is real but requires specific hardware (GPU/NIC/HBA) or a loaded kernel module not present
on the QEMU/virtio guest. The finding is HW-gated.
Fix
Validated by combined kernel build: all 41 fix.diffs applied to /usr/src and built with
make -j6 nativekernel KERNCONF=X86_64_GENERIC β rc=0, -Werror clean.
See fix.diff for the git-apply-able patch.
Fix verification
fixedCombined kernel build with all 41 fix.diffs: rc=0, -Werror clean. Runtime test HW-gated.
'>>> Kernel build for X86_64_GENERIC completed' with 0 errors.
Confirmed kernel references
- s
- y
- s
- /
- d
- e
- v
- /
- n
- e
- t
- i
- f
- /
- m
- n
- /
- i
- f
- _
- m
- n
- .
- c
- :
- 3
- 6
- 0
Detail
Exploit chain
none
Evidence (decisive lines)
Source confirmed: sys/dev/netif/mn/if_mn.c:360. Combined 41-fix kernel build rc=0 -Werror clean.
PoC changes
fix.diff authored; validated by combined kernel build.
Verified recommended fix
Require NUL termination. Matches finding.
Verdict
REPRODUCED (source-confirmed). Text config buffer not NUL-terminated; strcmp walks OOB. Cited path verified at sys/dev/netif/mn/if_mn.c:360. HW/module-gated on QEMU guest.
No comments yet.