chromium/v8/src/sandbox/code-entrypoint-tag.h

// Copyright 2023 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_CODE_ENTRYPOINT_TAG_H_
#define V8_SANDBOX_CODE_ENTRYPOINT_TAG_H_

#include "src/common/globals.h"

namespace v8 {
namespace internal {

// A tag to distinguish code pointers with different calling conventions.
//
// When the sandbox is enabled, we assume that an attacker cannot modify memory
// outside of the sandbox and so the code pointer table achieves a form of
// coarse-grained control-flow integrity (CFI) for code running in the sandbox:
// indirect control flow transfers initiated by such code (for example,
// invoking a JavaScript or WebAssembly function or a compiled RegExp) will
// always land at a valid code entrypoint. However, this is not enough:
// different types of code may use different calling conventions or
// incompatible signatures. Further, some internal builtins may not expect to
// be called indirectly in this way at all. CodeEntrypointTags are therefore
// used to achieve fine-grained CFI: used appropriately, they guarantee that
// the callee and caller of such control-flow transfers are compatible. As
// such, two code objects should use the same tag iff they can safely be
// interchanged at all (indirect) callsites.
//
// Implementation-wise, the tags are simply XORed into the top bits of the
// entrypoint pointer in the CPT and hardcoded at the callsite, where the
// pointer is untagged (again via XOR) prior to invoking it. If the tags do not
// match, the resulting pointer will be invalid and cause a safe crash.
// TODO(saelo): on Arm64, we could probably use PAC instead of XORing the tag
// into the pointer. This may be more efficient.
constexpr int kCodeEntrypointTagShift =;
enum CodeEntrypointTag : uint64_t {};

}  // namespace internal
}  // namespace v8

#endif  // V8_SANDBOX_CODE_ENTRYPOINT_TAG_H_