ATA PASS-THROUGH 16 drops LBA high extension byte (copy-paste defect)
Summary
In ATA_PASS_16 (SCSI opcode 0x85) translation line 1219 is byte-for-byte duplicate of line 1217 (both write fis->lba_mid_exp = atp16->lba_mid_ext). As a result fis->lba_high_exp is never assigned. Because sili_ata_get_xfer zeroes the FIS before returning it lba_high_ext byte from caller CDB silently forced to 0 so upper byte of LBA48 address (bits [47:40]) dropped device targets wrong sector. Line 1219 was meant to be fis->lba_high_exp=atp16->lba_high_ext. ATA_PASS_12 correctly omits *_exp fields because 28-bit LBA command. [VERIFIED pass2: reproduced - copy-paste re-stores lba_mid_exp so FIS lba_high_exp stays 0 while CDB carries lba_high_ext 0xf5 - LBA48 bits 47-40 dropped wrong-sector IO; fix A/B 0xf5 delivered]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2519 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 939 B | β raw | |
| VERDICT.md | β | 1.8 KB | β raw | |
| build.sh | β | 99 B | view raw | |
| run.log | β | 338 B | view raw | |
| env.txt | β | 963 B | view raw | |
| fix.diff | β | 471 B | view raw | |
| manifest.json | β | 617 B | view raw | |
| verdict.json | β | 2.0 KB | view raw |
DF-2519 -- ATA PASS-THROUGH(16) drops LBA high extension byte (copy-paste)
Verification used the shared rig tree at /root/rigs on the audit guest (see manifest). The rig for this finding: dfv_sili (rig.c = harness, gen.sh = verbatim extractor, dfv_*_extract.h = generated production text). The decisive outputs below were captured live on the guest during the 2026-10-24 verification session; full session logs are summarized per run.
Build
sh build.sh # extracts verbatim driver text + builds the KLD
Run (guest, root)
kldload ./dfv_rig.ko
kldload dfv_sili.ko; sysctl kern.dfv_sili_run=1; sysctl -n kern.dfv_sili_status
Expected
run.log: CDB high ext 0xf5 -> FIS high exp 0x00 (BYTE-DROPPED); fixed 0xf5.
Fix validation
fix.diff corrects the duplicated line to fis->lba_high_exp = atp16->lba_high_ext; A/B delivers the byte.
Verdict: reproduced / impact=corruption (see verdict.json, VERDICT.md)
DF-2519 verdict -- ATA PASS-THROUGH(16) drops LBA high extension byte (copy-paste)
status: reproduced reproduced: 1 impact: corruption confidence: certain attempts: 2 runtime_sec: 400
The verbatim sili_xpt_scsi_disk_io ATA_PASS_16 case contains the duplicated line fis->lba_mid_exp = atp16->lba_mid_ext at sili_cam.c:1219 (byte-identical to :1217); fis->lba_high_exp is never assigned. sili_ata_get_xfer zeroes the FIS (modelled by the rig exactly), so with a CDB carrying distinct extension bytes (lba_high_ext=0xF5) the resulting FIS had lba_mid_exp=0xF4 (correct) but lba_high_exp=0x00 - LBA48 bits 47:40 silently forced to zero and the device targets the wrong sector (data corruption at the disk). Fixed source (assign fis->lba_high_exp = atp16->lba_high_ext) A/B: FIS exp bytes feat=0xf1 cnt=0xf2 low=0xf3 mid=0xf4 high=0xf5 - all five extension bytes delivered.
Evidence (decisive lines)
DF2519: CDB ext bytes: feat=0xf1 cnt=0xf2 low=0xf3 mid=0xf4 high=0xf5 DF2519: FIS exp bytes: feat=0xf1 cnt=0xf2 low=0xf3 mid=0xf4 high=0x00 DF2519: RESULT=BYTE-DROPPED (fis->lba_high_exp must equal CDB lba_high_ext=0xf5; copy-paste at sili_cam.c:1219) --- fixed source A/B --- DF2519: FIS exp bytes: ... mid=0xf4 high=0xf5 ... RESULT=OK
Exploit chain / privesc assessment
correctness bug reachable by any ATA pass-through user (CAM path); wrong-sector I/O = silent data corruption.
Fix + A/B
fix.diff corrects the duplicated line to fis->lba_high_exp = atp16->lba_high_ext; A/B delivers the byte.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
fixedConfirmed kernel references
Detail
Exploit chain
correctness bug reachable by any ATA pass-through user (CAM path); wrong-sector I/O = silent data corruption.
Evidence (decisive lines)
run.log: CDB high ext 0xf5 -> FIS high exp 0x00 (BYTE-DROPPED); fixed 0xf5.
PoC changes
none - first rig run after the ap_sc NULL fix.
Verified recommended fix
fix the duplicated line to fis->lba_high_exp = atp16->lba_high_ext
Verdict
The verbatim sili_xpt_scsi_disk_io ATA_PASS_16 case contains the duplicated line fis->lba_mid_exp = atp16->lba_mid_ext at sili_cam.c:1219 (byte-identical to :1217); fis->lba_high_exp is never assigned. sili_ata_get_xfer zeroes the FIS (modelled by the rig exactly), so with a CDB carrying distinct extension bytes (lba_high_ext=0xF5) the resulting FIS had lba_mid_exp=0xF4 (correct) but lba_high_exp=0x00 - LBA48 bits 47:40 silently forced to zero and the device targets the wrong sector (data corruption at the disk). Fixed source (assign fis->lba_high_exp = atp16->lba_high_ext) A/B: FIS exp bytes feat=0xf1 cnt=0xf2 low=0xf3 mid=0xf4 high=0xf5 - all five extension bytes delivered.
No comments yet.