Unsigned underflow in agp_i915_get_stolen_size: sc->stolen wraps to ~0x3FFFFFFF entries when BIOS stolen size < GTT size, permanently breaking all GTT binds
Summary
sc->stolen = (stolen - gtt_size)*1024/4096 computed unsigned with no guard. Pineview with a G4X-encoded GMS yields stolen=0 against gtt_size=4KB; a 965 with GMS=1M against a 2MB PGTBL. Both wrap to 0x3FFFFFFF entries, making bind/unbind reject every GTT index with EINVAL - graphics permanently dead from attach (availability only; the value only widens the refused prefix). Guard-the-subtraction fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4256 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| trigger.sh | β | 538 B | view raw | |
| env.txt | β | 1007 B | view raw | |
| VERDICT.md | β | 2.2 KB | β raw | |
| fix.diff | β | 530 B | view raw | |
| manifest.json | β | 748 B | view raw | |
| verdict.json | β | 2.0 KB | view raw |
DF-4256 VERDICT β sc->stolen unsigned underflow in agp_i915_get_stolen_size
Status: inconclusive (hardware-gated; no Intel GTT device on the audit guest). Arithmetic certain at source level.
Reproduction attempt
Checked the audit guest for any device handled by this driver:
pciconf -l | grep 8086.*(2582|258a|2592|2772|27a2|27ae|...) β none; agp
module not loaded (env.txt). The underflow executes only during
agp_i810_attach β get_stolen_size (intel-gtt.c:867) on real 915-class
hardware with firmware that programs GMS smaller than the page-table size.
The DragonFly kernel has no other caller.
Analysis (why it is a real bug)
(stolen - gtt_size) is computed in unsigned int (both are unsigned int,
intel-gtt.c:566) with no guard at intel-gtt.c:698:
- Pineview path: for CHIP_IGD the G4X stolen encodings (0xa0/0xb0/0xc0/0xd0)
set
stolen = 0(intel-gtt.c:682-688) whilegtt_sizeis 0+4 KB (intel-gtt.c:622-625, 696) β(0u - 4u) * 1024 / 4096 == 0x3FFFFFFF. - 965 path: GMS=1M + PGTBL=2MB β
(1024u - 2052u)wraps the same way.
sc->stolen is then only consumed as a lower bound to refuse:
- intel-gtt.c:1065-1067
if (sc->stolen != 0 && index < sc->stolen) return (EINVAL); - intel-gtt.c:1083-1085 same in unbind.
So the corrupted value cannot widen writes; it locks out the GTT entirely
(graphics permanently broken β availability only), and the wrong
stolen_size propagates to i915 via agp_intel_gtt_get (intel-gtt.c:1445)
for stolen-range accounting.
Severity Low (needs specific/faulty firmware; impact is loss of graphics function, not memory unsafety). Confidence: certain for the arithmetic, speculative for the trigger precondition (well-formed BIOS avoids it).
Fix
Validate stolen >= gtt_size before the subtraction and fail attach (or
clamp sc->stolen to 0) β see fix.diff.
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_testablefix.diff adds the guard; hardware-gated, cannot be exercised on this guest
findings/poc/DF-4256/fix.diff
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (wrap cases + consumer analysis); env.txt (hardware absent)
PoC changes
no runnable PoC exists without affected firmware; trigger.sh only observes the accounting
Verified recommended fix
Validate stolen >= gtt_size before the subtraction (fail attach or clamp sc->stolen to 0)
Verdict
agp_i915_get_stolen_size computes sc->stolen = (stolen - gtt_size) * 1024 / 4096 in unsigned int with no guard (sys/dev/agp/intel-gtt.c:698). For Pineview with a G4X-encoded GMS value (0xa0-0xd0, where the chiptype check at 661-688 sets stolen=0) or a 965 with GMS=1M and a 2MB PGTBL, the subtraction wraps and sc->stolen becomes 0x3fffffff entries; agp_i810_bind_page/unbind_page (1065-1067/1083-1085) then reject every index ('bind into stolen memory') β permanent graphics denial of service from attach on, plus a wrong stolen_size exported to i915. Not memory-unsafe (the wrapped value only widens the refused prefix). Not executable on the audit guest (no Intel GTT hardware, env.txt); arithmetic verified at source level; trigger precondition requires mis-programmed firmware.
No comments yet.