β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2519

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2519 Β· 8 files
FileTypeDescriptionSize
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)

VERDICT.md
↓ download raw

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

fixed
↓ fix.diffper-fix-DF-2519

Confirmed 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.