# DF-4230 — cyapa: cyapa_poll_thread reads uninitialized `regs.stat` when the device stops responding — garbage byte drives the re-init state machine

## Where
`sys/dev/smbus/cyapa/cyapa.c`

- cyapa.c:1164 — `struct cyapa_regs regs;` — **local, never initialized**.
- cyapa.c:1178-1184 — `smbus_trans(..., (void *)&regs, sizeof(regs), NULL)`
  only writes `regs` **on success**; on bus error/NAK `regs` keeps its
  previous contents (uninitialized on the first failing iteration).
- cyapa.c:1191-1193 — the reset decision is evaluated regardless of the
  smbus error:
  ```c
  if (cyapa_reset ||
      ((regs.stat & CYAPA_STAT_RUNNING) == 0 &&
       (unsigned)(ticks - last_reset) > TIME_TO_RESET)) {
  ```
  → reads the uninitialized `regs.stat`.
- cyapa.c:1196 — consequence: `init_device(sc->dev, NULL, sc->addr, 2)` is
  invoked (bootloader handshake hammering on the SMBus) based on garbage.

## Impact
Purely a logic/robustness defect: an uninitialized stack byte decides
whether the driver spams the bus with bootloader commands every 3 seconds
while the device is dead. No info leak (the byte is never printed), no
memory unsafety. Info severity, hardening class.

## PoC — `model_uninit_regs.c`
Exact branch model with an smbus-failure stub and stack poisoning
(observed on the audit guest, run.log):
- poison byte 0x2d (RUNNING clear) → re-init triggered from garbage;
- poison byte 0xcd (RUNNING set)   → re-init suppressed by garbage.
Both decisions flip solely on the uninitialized byte — 2/2 each.

## Fix
Zero `regs` once before the loop (fix.diff): `bzero(&regs, sizeof(regs));`
(or `memset`) at declaration, giving `regs.stat = 0` → RUNNING bit clear →
deterministic re-init behavior.

## Build / run
```
cc -O0 -Wall -o model_uninit_regs model_uninit_regs.c
./model_uninit_regs 0x2d
./model_uninit_regs 0xcd
```
