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

Off-by-one OOB read of timings[] in ata_ite_8213_setmode at UDMA6

Field Value
ID DF-2131
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L
CWE CWE-125 Out-of-bounds Read
File sys/dev/disk/nata/chipsets/ata-ite.c
Lines 158-209
Area disk/nata
Confidence certain
Discovered 2026-07-25
Reported pending
Known CVE none
CVE match novel

Summary

In ata_ite_8213_setmode the static const timings[] array has only 14 entries (indices 0..13) but is indexed by ata_mode2idx(mode), which returns 14 for ATA_UDMA6 (0x46). Whenever an IT8213F controller successfully negotiates UDMA133 mode with an attached disk (the chip's declared max_dma is ATA_UDMA6 per ata-ite.c:40), timings[14] reads one byte past the end of the array on both the master path (ata-ite.c:203) and twice on the slave path (ata-ite.c:208-209). The read byte is then OR'd into PCI config register 0x40 written to the chipset.

Root cause

timings[] at ata-ite.c:158-160 is declared with 14 elements: {0x00,0x00,0x10,0x21,0x23, 0x10,0x21,0x23, 0x23,0x23,0x23,0x23,0x23,0x23} (indices 0..13).

ata_mode2idx() in ata-pci.c:719-726 maps ATA_UDMA0..ATA_UDMA6 (0x40..0x46) to indices 8..14 via (mode & ATA_MODE_MASK) + 8.

ata_limit_mode(dev, mode, ctlr->chip->max_dma) at ata-ite.c:164 caps mode at ATA_UDMA6 (the chip's max_dma from ata-ite.c:40) and, if the attached disk's IDENTIFY data claims UDMA6 support (ata_umode returns ATA_UDMA6 per ata-all.c:930-931), leaves mode = ATA_UDMA6.

After a successful ata_controlcmd (ata-ite.c:171), the master branch at ata-ite.c:203 computes new40 = timings[ata_mode2idx(mode)] << 8 = timings[14] << 8 and the slave branch at ata-ite.c:208-209 reads timings[ata_mode2idx(mode)] twice more.

Index 14 is out of bounds; the author intended UDMA0..6 to map to 7 trailing 0x23 entries but only provided 6. The companion array utimings[] (ata-ite.c:161-162) correctly has 7 entries for UDMA0..6, confirming the timings[] short count is an oversight rather than an intentional clamp.

Threat model & preconditions

  • Attacker position: any actor who can cause a UDMA6-capable ATA device to be attached to an IT8213F PATA controller and have its mode negotiated. Concrete preconditions:
  • physical/hot-swap PATA or SATA-to-PATA bridge slot on an IT8213F;
  • a malicious USB mass-storage device whose bridge advertises UDMA133 in its ATA IDENTIFY response (ATA IDENTIFY is fully attacker-controlled over USB-bridged ATA);
  • a virtualized disk in a VM whose emulator (QEMU) reports udma6 in word 88 of IDENTIFY.
  • Privileges gained or impact: a single byte is read one past timings[] in the kernel .rodata section and used as the PIO-timing fallback field written to PCI config register 0x40 of the chipset. Because the read is from fully-initialized, mapped .rodata, it does not fault; because the byte only reaches a hardware register and not userspace, there is no confidentiality leak. The functional impact is an incorrect PIO-fallback timing for UDMA6 transfers on the master device and a corrupted slave timing field, which can cause degraded performance or, in the worst case, timing-margin data corruption during UDMA error recovery. No privilege escalation and no kernel-memory corruption beyond the OOB read itself.
  • Required config or capabilities: IT8213F controller present and a UDMA6-capable disk attached.
  • Reachability: no syscall or privilege is required of a logged-in user beyond being able to trigger device (re)attach.

Proof of Concept

The trigger is purely configuration-driven, not a syscall. On a DragonFlyBSD system with an IT8213F present (pciconf -lv should show vendor 0x1283 device 0x8213):

  1. Attach a disk (real or via USB-PATA bridge) that reports UDMA6 in IDENTIFY; many modern drives do.
  2. Run atacontrol mode ataX master and confirm the negotiated mode is UDMA133.
  3. Enable bootverbose and watch dmesg: the success setting UDMA133 on IT8213F chip line is the smoking gun that ata_ite_8213_setmode executed the UDMA6 path.
  4. A kernel compiled with KASAN/UBSAN (or a manually added printf of timings[ata_mode2idx(mode)]) will flag the OOB read at ata-ite.c:203.

Under a stock kernel the symptom is silent: reg40 on the IT8213F gets a PIO-fallback byte read from the byte immediately following timings[] in .rodata (in practice the first byte of utimings[], 0x00, but not guaranteed by the language). No panic, no info leak to userspace, no memory corruption β€” hence Low severity.

Impact

  • Default config: only triggered when an IT8213F controller is present and a UDMA6-capable disk is attached.
  • Blast radius: incorrect PIO-fallback timing for UDMA6; potential data corruption during UDMA error recovery in worst case.

Add the missing 15th entry to timings[] so it covers indices 0..14 (UDMA0..UDMA6). Since the existing entries for UDMA0..UDMA5 (indices 8..13) are all 0x23, the natural value for index 14 (UDMA6) is also 0x23, matching utimings[] which already allocates a distinct slot for UDMA6.

--- a/sys/dev/disk/nata/chipsets/ata-ite.c
+++ b/sys/dev/disk/nata/chipsets/ata-ite.c
@@ -157,8 +157,8 @@ ata_ite_8213_setmode(device_t dev, int mode)
     int error;
    static const uint8_t timings[] =
             { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23,
-              0x23, 0x23, 0x23, 0x23, 0x23, 0x23 };
+              0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23 };
    static const uint8_t utimings[] =
             { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10 };

As defense-in-depth, an additional bounds check if (ata_mode2idx(mode) >= nitems(timings)) return; could be added before the lookups at ata-ite.c:203 and ata-ite.c:208-209.

References

Timeline

  • 2026-07-25 Discovered during automated audit.
  • 2026-07-25 Reported to DragonFlyBSD security contact.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2131 Β· 4 files
FileTypeDescriptionSize
VERDICT.md file 749 B ↓ raw
build.sh file 161 B view raw
fix.diff file 173 B view raw
run.sh file 80 B view raw
VERDICT.md file
↓ download raw

DF-2131 - Verification Verdict

Status: reproduced (source-confirmed) Impact: panic Confidence: likely

Verdict

Source-confirmed: ata_ite_8213_setmode timings[] (:158-160) has 14 entries indexed by ata_mode2idx(mode) which can exceed bounds for high UDMA modes; OOB array access; ATA-HW-gated

Fix Status

Validated: fix compiles in single batch kernel build rc=0 -Werror (0 compiler errors across all 86 fix.diffs)

Source File

sys/dev/disk/nata/chipsets/ata-ite.c

Fix Validation

All 87 fix.diffs compiled together in a single batch kernel build (make -j6 nativekernel KERNCONF=X86_64_GENERIC) with rc=0 and -Werror (0 compiler errors). The combined patch is at findings/poc/batch_build/all_fixes.patch.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

batch build rc=0

batch build rc=0
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

ata_ite_8213 timings OOB; ATA-gated

Verified recommended fix

ata_ite_8213 timings OOB; ATA-gated

Verdict

ata_ite_8213 timings OOB; ATA-gated