chromium/v8/src/sandbox/js-dispatch-table.h

// 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_