Fix 3 Opus-audit findings: patch transport-abort, patch AACS align, reset IOCTL

- patch (Pass N) now aborts immediately on transport failure (status=0xFF),
  symmetric with the sweep and single-pass mux. Previously a USB-bridge crash
  was treated as an ordinary bad sector and the pass hammered the crashed
  device sector-by-sector until the per-range watchdog expired. (medium)
- patch AACS recovery reads are now unit-aligned: a mid-unit single-sector
  read on an AACS disc was rejected by the decrypting reader (DecryptFailed)
  and the sector abandoned without asking the drive. The read is now widened
  to the enclosing whole 3-sector unit and the requested window copied out,
  leaving all recovery accounting (pos/block_bytes/cursor) untouched so it
  cannot desync. Only affected CLI decrypt-to-ISO --multipass re-runs. (low)
- IOCTL_STORAGE_RESET_DEVICE corrected 0x002D1004 -> 0x002DD000 (the old value
  decoded to function 0x401 with the access bits cleared, so DeviceIoControl
  would fail ERROR_INVALID_FUNCTION instead of resetting). Windows-only. (low)

Adds a transport-failure classification regression test.
This commit is contained in:
Matthew Jackson
2026-06-22 15:50:22 -07:00
parent f863e9a4be
commit fa8913800c
2 changed files with 116 additions and 3 deletions
+7 -1
View File
@@ -214,7 +214,13 @@ impl SptiTransport {
/// Opens the device, sends IOCTL_STORAGE_RESET_DEVICE to reset
/// the USB/SCSI bus, then closes. Same concept as SG_SCSI_RESET on Linux.
pub fn reset(device: &Path) -> Result<()> {
const IOCTL_STORAGE_RESET_DEVICE: u32 = 0x002D1004;
// CTL_CODE(IOCTL_STORAGE_BASE=0x2D, 0x0400, METHOD_BUFFERED=0,
// FILE_READ_ACCESS|FILE_WRITE_ACCESS=3)
// = (0x2D<<16) | (3<<14) | (0x0400<<2) | 0 = 0x002DD000.
// The earlier literal 0x002D1004 decoded to function 0x401 with the
// access bits cleared — not IOCTL_STORAGE_RESET_DEVICE, so
// DeviceIoControl would fail ERROR_INVALID_FUNCTION instead of resetting.
const IOCTL_STORAGE_RESET_DEVICE: u32 = 0x002D_D000;
let dev_str = device.to_str().ok_or_else(|| Error::DeviceNotFound {
path: device.display().to_string(),