Resource leak in ata_ali_sata_allocate error path: io released with wrong device and rid
| Field | Value |
|---|---|
| ID | DF-2094 |
| Status | new |
| Severity | Info |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:L |
| CWE | CWE-775 Missing Release of File Descriptor or Handle after Effective Lifetime |
| File | sys/dev/disk/nata/chipsets/ata-acerlabs.c |
| Lines | 152-161 |
| Area | disk/nata |
| Confidence | certain |
| Discovered | 2026-07-25 |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
In ata_ali_sata_allocate(), when the ctlio allocation fails, the
previously allocated io resource is freed with
bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io). But io
was allocated from parent with rid = PCIR_BAR(0)+offset (0x10 or
0x18), not from dev with rid = ATA_IOADDR_RID (0). Both the device
handle and the rid are wrong, so newbus cannot match the resource and io
is leaked for the lifetime of the controller.
Root cause
ata-acerlabs.c:152-153:
rid = PCIR_BAR(0) + (unit01 ? 8 : 0);
io = bus_alloc_resource_any(parent, SYS_RES_IOPORT, &rid, RF_ACTIVE);
ata-acerlabs.c:159-161:
if (!ctlio) {
bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
return ENXIO;
}
Two mismatches:
- The resource was allocated from
parent(the PCI controller device), but the release targetsdev(the ATA channel child) β the child never owned this resource. - The rid passed (
ATA_IOADDR_RID = 0,ata-all.h:300) does not match the actual allocation rid (PCIR_BAR(0) = 0x10, or0x18for the secondary channel).
Newbus looks up resources by (type, rid) in the specified device's
resource list; with neither matching, the release is a no-op and io is
leaked.
Compare the correct idiom in ata_pci_allocate() at ata-pci.c:417-423
where io is allocated from dev with rid ATA_IOADDR_RID and released
identically β a copy-paste that is correct in its source but wrong here.
Threat model & preconditions
- Attacker position: privileged local user (root or operator group on
/dev/ata*). - Privileges gained or impact: operational β repeated attach/detach cycles could in principle exhaust the parent's rman resource-accounting slots, causing future allocations on the controller to fail. No memory corruption, no info leak, no privilege escalation.
- Required config or capabilities: an ALi 5281/5287/5288/5289 SATA
controller where BAR(1) (or BAR(3) for
unit01) is unmappable. - Reachability:
ctlioallocation atata-acerlabs.c:158fails whileioatata-acerlabs.c:153succeeded.
Proof of concept
Not exploitable for memory corruption or privilege escalation.
Operational-impact only: on a system with a present ALi SATA controller,
force repeated channel re-probes (e.g. via devctl or by repeatedly
unloading/reloading the nata module) under a condition where BAR(1) cannot
be mapped. Each failed attach of ata_ali_sata_allocate leaks one rman
IOPORT resource on the parent. dmesg will not report the leak; it is
observable via vmstat -z / rman walk showing orphans, or by the parent
eventually failing allocate with ENXIO after enough cycles.
Impact
Local privileged DoS only (rman slot exhaustion on the parent controller). No security boundary violation.
Recommended fix
Release io from the same device and with the same rid used to allocate
it. The allocation rid must be saved in a variable because it was
overwritten by the ctlio allocation.
--- a/sys/dev/disk/nata/chipsets/ata-acerlabs.c
+++ b/sys/dev/disk/nata/chipsets/ata-acerlabs.c
@@ -142,11 +142,12 @@
ata_ali_sata_allocate(device_t dev)
{
device_t parent = device_get_parent(dev);
struct ata_pci_controller *ctlr = device_get_softc(parent);
struct ata_channel *ch = device_get_softc(dev);
struct resource *io = NULL, *ctlio = NULL;
int unit01 = (ch->unit & 1), unit10 = (ch->unit & 2);
- int i, rid;
+ int i, rid, iorid;
- rid = PCIR_BAR(0) + (unit01 ? 8 : 0);
+ iorid = rid = PCIR_BAR(0) + (unit01 ? 8 : 0);
io = bus_alloc_resource_any(parent, SYS_RES_IOPORT, &rid, RF_ACTIVE);
if (!io)
return ENXIO;
@@ -157,7 +158,7 @@
rid = PCIR_BAR(1) + (unit01 ? 8 : 0);
ctlio = bus_alloc_resource_any(parent, SYS_RES_IOPORT, &rid, RF_ACTIVE);
if (!ctlio) {
- bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
+ bus_release_resource(parent, SYS_RES_IOPORT, iorid, io);
return ENXIO;
}
References
sys/dev/disk/nata/ata-pci.c:417-423β correct idiom this was copied from.
Timeline
- 2026-07-25 Discovered during automated audit.
- 2026-07-25 Reported to DragonFlyBSD security contact.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2094 Β· 2 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | git-apply-able fix | 833 B | view raw |
| VERDICT.md | verdict | source-trace confirmation | 633 B | β raw |
DF-2094 β ata_ali_sata_allocate resource leak on error path
Verdict
REPRODUCED (source-only confirmation). Bug confirmed by source tracing.
Mechanism
ata_ali_sata_allocate (ata-acerlabs.c:152-161): io allocated from parent with rid=PCIR_BAR(0)+offset. On ctlio failure, release uses bus_release_resource(dev,...,ATA_IOADDR_RID,io) β wrong device (dev vs parent) and wrong rid. Resource leaked/mismatched.
Fix
Save io_rid separately; release with bus_release_resource(parent, SYS_RES_IOPORT, io_rid, io).
Batch-build status
Applied with all 24 other fixes; kernel + modules compiled rc=0, 0 errors, -Werror.
Fix verification
fixedSaved io_rid separately; batch build rc=0.
Saved io_rid separately; batch build rc=0.
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
ata_ali_sata ctlio error releases io with wrong dev+rid.
Verified recommended fix
ata_ali_sata ctlio error releases io with wrong dev+rid.
Verdict
ata_ali_sata ctlio error releases io with wrong dev+rid.
No comments yet.