# VERDICT — DF-3209

**status: untested** (boot-path-only code; not runtime-testable on the audit guest — same ceiling as DF-3203/3204/3205)
**impact: leak (limited: 0–3 uninitialized kernel-heap bytes per boot RPC, boot-time window)**
**confidence: certain** (pure source/arithmetic proof, no execution required)

## Proof chain (path:line)

1. `sys/vfs/nfs/nfs_mountrpc.c:143` — `m = xdr_string_encode(path, strlen(path));` (v3 mountd MOUNT request);
   `:160` (v2 fallback request); `:245` (NFSPROC_LOOKUP swap path). These are the **only** callers in the tree
   (`rg -l xdr_string_encode sys/` → krpc.h declaration + krpc_subr.c definition + this file).
2. `sys/vfs/nfs/krpc_subr.c:466-467`:
   `dlen = (len + 3) & ~3; mlen = dlen + 4;` — XDR string = 4-byte length + padded data.
3. `sys/vfs/nfs/krpc_subr.c:472` — `m = m_getl(mlen, M_WAITOK, MT_DATA, 0, NULL);` — **flags=0, no M_ZERO**.
   `sys/sys/mbuf.h:584-602` — `m_getl(..., flags=0, ...)` → `m_get(how, type)` (plain MT_DATA mbuf from the
   freelist, data area untouched). Cluster path (`m_getcl`) also does not zero.
4. `sys/vfs/nfs/krpc_subr.c:475-476` — only `len` bytes are written (`xs->len = txdr_unsigned(len);
   bcopy(str, xs->data, len);`). Bytes `xs->data[len .. dlen)` (0–3 bytes) are **uninitialized**.
5. `sys/vfs/nfs/krpc_subr.c:474` — `m->m_len = mlen;` — the datagram includes the uninitialized tail.
6. `sys/vfs/nfs/krpc_subr.c:276` (`mhead->m_next = *data`), `:300-306` (pkthdr.len includes it),
   `:317-323` (`m_copym` + `sosend(so, sa, ..., m, ...)`) — the request, including the stale pad bytes, is
   transmitted as one UDP datagram to the mountd/NFS server (and observable by any on-path LAN device).

## Why untested rather than reproduced
The execute path requires `nfs_mountroot()` at boot with an NFS root. Audit guest (DragonFly 6.5-DEVELOPMENT
#0, X86_64_GENERIC, `vbd0s1d on / (hammer2, local)`) boots from disk; `NFS_ROOT` is compiled in
(sys/config/X86_64_GENERIC:29) but `md_mount`/`md_lookup_swap` are unreachable at runtime (static callers only:
nfs_vfsops.c:724 `nfs_mountdiskless` ← nfs_vfsops.c:557 `nfs_mountroot` ← kernel mount-root machinery).
No unprivileged (or any) runtime user can reach the builder.

## Impact assessment
* Unauthenticated LAN observer or the configured server receives 0–3 bytes of stale kernel heap per request,
  up to ~3 requests per boot (v3 mount, maybe v2 fallback mount, swap LOOKUP). Boot-time window only.
* Contents: whatever the recycled mbuf last held (early-boot network traffic / loader data) — low sensitivity,
  but a textbook CWE-908 (uninitialized resource) disclosure and trivially fixable.

## Recommended fix
Zero the pad tail (or allocate with M_ZERO):
```diff
--- a/sys/vfs/nfs/krpc_subr.c
+++ b/sys/vfs/nfs/krpc_subr.c
@@ -473,6 +473,7 @@ xdr_string_encode(char *str, int len)
 	m = m_getl(mlen, M_WAITOK, MT_DATA, 0, NULL);
 	xs = mtod(m, struct xdr_string *);
 	m->m_len = mlen;
 	xs->len = txdr_unsigned(len);
 	bcopy(str, xs->data, len);
+	bzero(xs->data + len, dlen - len);	/* do not leak stale pad bytes */
 	return (m);
 }
```

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
