From 65ccbcbd92dced7f57f398c21e5717bca1d64c5f Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Thu, 6 Aug 2026 09:31:37 -0700 Subject: [PATCH] Scan only the sectors the crack actually read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit read_sectors returns the number of bytes written and a source may return Ok with fewer than asked — a recovery read over a damaged region does exactly that. The crack loop discarded the count and inspected all n sectors of a buffer that is REUSED across batches, so the tail still held the previous batch sectors. Cracking a key from those means cracking from data belonging to a different extent, possibly a different VTS, while crack_span records the CURRENT one. A key that opens nothing in this region is then installed, and its wrong descrambles are only partly caught by the per-sector crib. --- src/css/mod.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/css/mod.rs b/src/css/mod.rs index 37548aa..64d55db 100644 --- a/src/css/mod.rs +++ b/src/css/mod.rs @@ -278,10 +278,21 @@ fn crack_key_scan( let n = (ext.sector_count - i).min(batch); let want = n as usize * 2048; match reader.read_sectors(ext.start_lba + i, n as u16, &mut buf[..want], true) { - Ok(_) => { + Ok(got) => { // A readable batch: the gate is open — reset the locked run. consecutive_locked = 0; - for s in 0..n as usize { + // Inspect only what was actually READ. The trait returns the + // byte count and a source may return Ok with fewer bytes + // than asked (a recovery read over a damaged region), while + // `buf` is reused across batches — so the tail still holds + // the PREVIOUS batch's sectors. Scanning those means + // cracking a key from data belonging to a different extent, + // and possibly a different VTS, while `crack_span` records + // the CURRENT one: a key that opens nothing here gets + // installed and its wrong descrambles are only partly caught + // by the per-sector crib. + let usable = (got / 2048).min(n as usize); + for s in 0..usable { tried += 1; let sect = &buf[s * 2048..(s + 1) * 2048]; // Use the HARDENED pack-gated check (Fix 3): a clear stub