# DF-2411 — advansys.c divide-by-zero in XPT_CALC_GEOMETRY

## Verdict: NOT REPRODUCED (hardware-gated) — source bug CONFIRMED real (partially mitigated upstream); fix.diff compiles.

**Classification:** `not_reproduced` / HW-gated / impact=none. No AdvanSys HBA on
this guest. The div-by-zero is **real in source**; the defense-in-depth `fix.diff`
**compiles cleanly** (`nativekernel rc=0`, `-Werror`, `-DINVARIANTS`).

### Why not reproduced (the gate)

The bug is in `adv_action()` `XPT_CALC_GEOMETRY` of the **advansys(4) SCSI HBA
driver** (`sys/dev/disk/advansys/advansys.c`). The guest has **no AdvanSys PCI HBA**
(`pciconf -l` shows only PIIX3 ISA/IDE, virtio-net, virtio-blk, VGA) and the
`advansys` module is **not loaded** (`kldstat` shows only `kernel`, `ehci.ko`,
`xhci.ko`). The XPT_CALC_GEOMETRY handler is therefore never invoked. The trigger
also requires a malicious SCSI device returning a crafted READ CAPACITY.

Gate proof (this guest):
```
$ kldstat              ->  kernel, ehci.ko, xhci.ko   (no advansys)
$ pciconf -l           ->  no AdvanSys (0x10cd/*) / no SCSI HBA at all
$ camcontrol devlist   ->  only QEMU DVD-ROM on PIIX3 ata-cam (no adv bus)
```

### The source bug (real, cited `path:line`)

`sys/dev/disk/advansys/advansys.c`, `adv_action()` `XPT_CALC_GEOMETRY` (`:433-457`):
- `size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size);` (`:441-442`).
- **Sink 1** (block_size==0): inner `1048576L / 0` → `#DE` → panic.
- **Sink 2** (block_size > 1 MiB, or any value that doesn't evenly divide 1 MiB
  yielding quotient 0): inner truncates to 0, outer `volume_size / 0` → `#DE` → panic.
- Data flow: READ CAPACITY → `scsi_da.c:1831` `block_size = scsi_4btoul(rdcap->length)`
  → `dasetgeom` → `ccg->block_size` → `xpt_action(XPT_CALC_GEOMETRY)` →
  `advansys.c:442`. No validation anywhere in the chain.

**Upstream mitigation observed during tracing (important):** the XPT core
`xpt_action()` `XPT_CALC_GEOMETRY` dispatcher at `sys/bus/cam/cam_xpt.c:3063` already
filters `block_size == 0` and `volume_size == 0` **before** dispatching to
`sim->sim_action`. So **Sink 1 (block_size==0) is NOT reachable** via the normal
da→`dasetgeom`→`xpt_action` path on this kernel — the core returns `CAM_REQ_CMP`
without calling the SIM. **Sink 2 (block_size > 1 MiB) is NOT filtered** by the core
and remains a real latent bug in this SIM. Both sinks are HW-gated here (no AdvanSys
HBA).

Attacker model: malicious SCSI device on an AdvanSys-attached bus; auto-probe issues
INQUIRY then READ CAPACITY. No authentication required (if the HBA were present).

### Exploit chain

Not developed — no AdvanSys HBA, no adv bus, no target. Valid hard blocker: the
driver code path is dead on this guest (no live SIM instance).

### Fix (defense-in-depth, validated to compile)

`fix.diff` guards `ccg->block_size` against `== 0`, `> 1 MiB`, and non-divisors of
1 MiB before the division (returning `CAM_REQ_CMP_ERR`). Validated in the combined
`nativekernel` build (`fix_build.log`).

### Reproduce

No runnable PoC on this guest (no AdvanSys HBA). Artifacts: `env.txt`, `fix.diff`,
`fix_build.log`.
