# DF-5523 VERDICT — REPRODUCED (uninitialized kernel stack byte drives the SMBus transfer length through the unvalidated bridge count; one-byte disclosure to the caller)

## The bug (two cooperating halves)

1. **Bridge (this file):** `iicsmb_bread()` uses `(int)*count` as the
   `iicbus_read()` length with no validation (`iicsmb.c:499-500`), and
   `iicsmb_bwrite()` sends `(int)count` bytes (`iicsmb.c:474`).  Neither
   enforces the SMBus block bounds that every other smbus driver enforces
   (`ichsmb_bwrite`/`ichsmb_bread`: `if (count < 1 || count > 32)
   return (SMB_EINVAL);`).
2. **Caller (`sys/dev/smbus/smb/smb.c`, routed):** `smbioctl`'s
   `u_char bcount;` (smb.c:217) is **never assigned** before
   `smbus_bread(bus, s->slave, s->cmd, &bcount, buf)` (smb.c:323).  The
   clamp lines above it touch `s->rcount`, which is *not* the value passed
   down.

Net effect on an iicsmb-backed bus: an uninitialized kernel stack byte
selects the on-wire transfer length (0..255), and — through
`s->rcount = min(s->rcount, bcount)` + the ioctl copy-back — that
uninitialized byte's value is disclosed to the caller.

## Observations (production chain, stock modules)

* parent process, fresh stack: `READ req_len=0` six times — zero-length
  "successful" block reads; `smbcmd.rcount` returned 0 (the byte's value).
* forked child (same binary, different stack history): `READ req_len=255`
  — the bridge transferred 255 bytes driven by stack junk.
* A 255-byte read stays inside smb.c's 1024-byte `buf` (SMB_MAXBLOCKSIZE,
  smb.h:62), so there is **no overflow on this in-tree path** — the
  candidates with 32-byte buffers (`ipmi_ssif`) pass an initialized 32.
  (This audit explicitly killed the "uninit bcount overflows a 32-byte
  stack buffer" hypothesis on that ground.)
* `groom` mode (pre-filling smbioctl's stack buf via a prior BWRITE
  copyin) did not reach the compiler's slot for `bcount` in this build;
  the 0-vs-255 cross-process variance is the demonstrated evidence that
  the value is uninitialized memory.

## Impact

Kernel uninitialized-memory disclosure (1 byte) to a root-only caller plus
nondeterministic bus behavior (arbitrary-length wire reads).  Not
exploitable beyond root on the in-tree paths (device node 0600, ipmi's
count initialized).  Severity Low.

## Fix (validated)

`fix.diff`: (a) validate `*count`/`count` in `[1,32]` at both bridge entry
points (mirrors ichsmb; rejects garbage deterministically — observed:
baseline garbage 0/255 both out of range → SMB_EINVAL, no wire traffic);
(b) `smb.c`: seed `bcount = s->rcount` after the clamp so the length comes
from initialized state.  Post-fix `proto`: deterministic
`req_len=1`/`req_len=8`, `rcount=8`, six consecutive identical ioctls.

## 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.
