hptv2 metadata writeback: 2048-byte write from a 512-byte heap buffer persists ~1.5KB of kernel heap to disk (OOB read -> durable info leak)
Summary
ata_raid_hptv2_write_meta kmallocs sizeof(struct hptv2_raid_conf)=512B but writes sizeof(struct promise_raid_conf)=2048B to every member disk - ata_raid_rw DMAs bcount bytes from the buffer, persisting 1536 bytes of adjacent kernel heap into fixed sectors (LBA 9..12) on every writeback. write_metadata routes BOTH HPTv2 and HPTv3 formats here; writeback fires on every status change (boot 0->READY, mirror loss, subdisk detach, spare ops). Vendor-gated to HighPoint controllers so not runnable on this Intel-only guest: inconclusive, source certain (compile-time-constant size mismatch proven by compiling the packed struct from the real header).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3693 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.4 KB | β raw | |
| VERDICT.md | β | 2.1 KB | β raw | |
| analysis.txt | β | 1.9 KB | view raw | |
| fix.diff | β | 3.6 KB | view raw | |
| verdict.json | β | 2.0 KB | view raw | |
| manifest.json | β | 2.4 KB | view raw |
DF-3693 β hptv2 metadata writeback reads 2048 bytes out of a 512-byte heap buffer and persists them to disk (kernel heap disclosure)
Root cause (source)
ata_raid_hptv2_write_meta (sys/dev/disk/nata/ata-raid.c:1897-1983)
allocates sizeof(struct hptv2_raid_conf) = 512 bytes
(:1903-1904) but issues the write with sizeof(struct promise_raid_conf)
= 2048 bytes:
1903: meta = (struct hptv2_raid_conf *)kmalloc(sizeof(struct hptv2_raid_conf), M_AR, M_WAITOK | M_ZERO);
...
1972: if (ata_raid_rw(rdp->disks[disk].dev,
1973: HPTV2_LBA(rdp->disks[disk].dev), meta,
1974: sizeof(struct promise_raid_conf), /* 2048 != 512 */
1975: ATA_R_WRITE | ATA_R_DIRECT)) {
ata_raid_rw DMAs bcount bytes from meta to the disk
(request->data = data; request->bytecount = bcount;), so 1536 bytes of
kernel heap past the allocation are written into the member disks' metadata
sectors (LBA 9..12). Sizes verified by compiling the packed structs from
the real header on the guest (sizeof hptv2=512, sizeof promise=2048).
write_metadata routes both AR_F_HPTV2_RAID and AR_F_HPTV3_RAID arrays
here (:1492-1498). The writeback fires on every array-state change
(ata_raid_config_changed:977-998 forces writeback when status changes β
e.g. 0βREADY at boot, mirror loss, disk detach :4179, spare insertion).
Impact
Kernel heap contents (adjacent allocation data β potentially pointers, file fragments, keys) are persisted to fixed disk sectors readable by anyone with raw access to the member disk (root/operator/physical/cloud-image inspection). CWE-125/CWE-200 (OOB read β information exposure), plus corruption of the (unwritten-by-us) HPTv2 image area semantics.
Guest testability
The HPTv2/HPTv3 read parsers are only reached when
pci_get_vendor(GRANDPARENT(...)) == ATA_HIGHPOINT_ID
(ata_raid_read_metadata:1416-1420), i.e. on HighPoint controllers. This
QEMU guest has only an Intel PIIX3 IDE controller, so the format can never
be instantiated here β verdict inconclusive (not testable on this
hardware), confidence in the source analysis remains certain
(buffer-size mismatch is compile-time constant; sizes confirmed on the
guest toolchain).
Fix
fix.diff hunk: use sizeof(struct hptv2_raid_conf) for the write length.
Files
analysis.txt (struct size transcript from the guest), fix.diff,
verdict.json
DF-3693 VERDICT
Status: inconclusive (runtime) / certain (source). impact: leak (not demonstrated at runtime on this hardware).
Why inconclusive at runtime
The HPTv2/HPTv3 parsers are vendor-gated on ATA_HIGHPOINT_ID
(ata-raid.c:1416-1420). The audit guest exposes only an Intel PIIX3 IDE
controller (QEMU default), so AR_F_HPTV2_RAID/AR_F_HPTV3_RAID can never
be instantiated and ata_raid_hptv2_write_meta cannot be reached. No other
reachable route exists (write_metadata dispatches purely on rdp->format).
Why the source claim is certain
kmalloc(sizeof(struct hptv2_raid_conf))= 512 bytes (verified by compiling the packed struct from the real header with the guest's cc β see analysis.txt).- The write passes
sizeof(struct promise_raid_conf)= 2048 bytes toata_raid_rw, which setsrequest->data = data; request->bytecount = bcountand DMAs that many bytes from the buffer to disk (ata-raid.c:4087-4131, 1972-1975). - 1536 bytes beyond the allocation are therefore persisted into LBA 9..12 of every member disk, on every forced writeback (status change at boot, subdisk detach :4179, spare add, generation bumps).
- The overflow is compile-time-constant; there is no path-sensitive condition to dispute.
Impact ceiling
Kernel-heap-content disclosure to persistent storage. The metadata sectors are world-position-stable (HPTV2_LBA = 9) and re-readable by whoever controls the disk later (operator/physical/cloud-image). Adjacent M_AR / kmem allocations can contain pointers and file data. No write primitive, no direct kernel-execution path β Medium.
Fix
One-line: use sizeof(struct hptv2_raid_conf) as the write length
(included in fix.diff; not behaviorally validated on this guest for the
hardware reason above β fix_status = not_testable with this stated reason).
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
not_testableone-line constant change included in fix.diff; cannot be behaviorally validated on this guest (no HighPoint controller)
fix.diff hunk '@@ -1971,7 +1998,7 @@'
Confirmed kernel references
Detail
Evidence (decisive lines)
analysis.txt (guest-compiled sizeof transcript: hptv2=512, promise=2048; vendor gating trace; writeback trigger trace)
PoC changes
no PoC possible on this hardware; layout verification tooling only
Verified recommended fix
write sizeof(struct hptv2_raid_conf) instead of sizeof(struct promise_raid_conf) (fix.diff hunk 7)
Verdict
ata_raid_hptv2_write_meta kmallocs 512 bytes (sizeof hptv2_raid_conf, verified by compiling the packed struct from the real header on the guest) but writes sizeof(promise_raid_conf)=2048 bytes to each member disk, persisting 1536 bytes of adjacent kernel heap into fixed metadata sectors (LBA 9..12) on every writeback (boot status change, subdisk detach, spare ops). Runtime test impossible on this guest: HPTv2/HPTv3 formats are PCI-vendor-gated to HighPoint controllers and the guest has only Intel PIIX3 IDE. Buffer-size mismatch is compile-time constant - source analysis certain.
No comments yet.