// Copyright 2024 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_SANDBOX_JS_DISPATCH_TABLE_H_ #define V8_SANDBOX_JS_DISPATCH_TABLE_H_ #include "include/v8config.h" #include "src/base/atomicops.h" #include "src/base/memory.h" #include "src/base/platform/mutex.h" #include "src/common/globals.h" #include "src/sandbox/external-entity-table.h" #ifdef V8_ENABLE_SANDBOX namespace v8 { namespace internal { class Isolate; class Counters; class Code; /** * The entries of a JSDispatchTable. * * An entry contains all information to call a JavaScript function in a * sandbox-compatible way: the entrypoint and the parameter count (~= the * signature of the function). The entrypoint will always point to the current * code of the function, thereby enabling seamless tiering. */ struct JSDispatchEntry { … }; static_assert …; /** * JSDispatchTable. * * The JSDispatchTable achieves two central goals: * * 1. It provides fine-grained forward-edge CFI for JavaScript function calls. * Both in the context of the V8 Sandbox and for process-wide CFI. For the * sandbox, this requires keeping the table outside of the sandbox and storing * both the function's entrypoints and its parameter count in it. That way, it * is guaranteed that every JSFunction call (1) lands at a valid JavaScript * entrypoint, and (2) uses the correct signature (~= parameter count). For * process-wide CFI, this table is write-protected using for example Intel * PKEYs. That way, even an attacker with an arbitrary, process-wide write * primitive cannot execute arbitrary code via JavaScript functions. * * 2. It enables cheap and fast tiering. When the JSDispatchTable is used, a * group of related JSFunctions (roughly those sharing the same SFI) share one * table entry. When the functions should tier up or down, only the entry needs * to be updated to point to the new code. Without such a table, every function * entrypoint would need to check if it needs to tier up or down, thereby * incurring some overhead on every function invocation. */ class V8_EXPORT_PRIVATE JSDispatchTable : public ExternalEntityTable<JSDispatchEntry, kJSDispatchTableReservationSize> { … }; static_assert …; // TODO(olivf): Remove this accessor and also unify implementation with // GetProcessWideCodePointerTable(). V8_EXPORT_PRIVATE inline JSDispatchTable* GetProcessWideJSDispatchTable() { … } } // namespace internal } // namespace v8 #endif // V8_ENABLE_SANDBOX #endif // V8_SANDBOX_JS_DISPATCH_TABLE_H_