/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/objects/trusted-object.h
192 строки
9 KB
Michaël Zasso
deps: update V8 to 14.6.202.33
24 апр 2026, 19:01
Не верифицирован
24 апр 2026, 19:01
f1e0b83
Код
Авторство
О чём код?
// 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_OBJECTS_TRUSTED_OBJECT_H_ #define V8_OBJECTS_TRUSTED_OBJECT_H_ #include "src/objects/heap-object.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" namespace v8 { namespace internal { #include "torque-generated/src/objects/trusted-object-tq.inc" // An object that is trusted to not have been modified in a malicious way. // // Typical examples of trusted objects are containers for bytecode or code // metadata, which often allow an attacker to corrupt (for example) stack // memory when manipulated. When the sandbox is enabled, trusted objects are // located outside of the sandbox (in one of the trusted heap spaces) so that // attackers cannot corrupt these objects and use them to escape from the // sandbox. When the sandbox is disabled, trusted objects are treated like any // other objects since in that case, many other types of objects (for example // ArrayBuffers) can be used to corrupt memory outside of V8's heaps as well. // // Trusted objects cannot directly be referenced from untrusted objects as this // would be unsafe: an attacker could corrupt any (direct) pointer to these // objects stored inside the sandbox. However, ExposedTrustedObject can be // referenced via indirect pointers, which guarantee memory-safe access. class TrustedObject : public HeapObject { public: DECL_VERIFIER(TrustedObject) // Protected pointers. // // These are pointers for which it is guaranteed that neither the pointer-to // object nor the pointer itself can be modified by an attacker. In practice, // this means that they must be pointers between objects in trusted space, // outside of the sandbox, where they are protected from an attacker. As // such, the slot accessors for these slots only exist on TrustedObjects but // not on other HeapObjects. template <typename T = TrustedObject> inline Tagged<T> ReadProtectedPointerField(int offset) const; template <typename T = TrustedObject> inline Tagged<T> ReadProtectedPointerField(int offset, AcquireLoadTag) const; inline void WriteProtectedPointerField(int offset, Tagged<TrustedObject> value); inline void WriteProtectedPointerField(int offset, Tagged<TrustedObject> value, ReleaseStoreTag); inline bool IsProtectedPointerFieldEmpty(int offset) const; inline bool IsProtectedPointerFieldEmpty(int offset, AcquireLoadTag) const; inline void ClearProtectedPointerField(int offset); inline void ClearProtectedPointerField(int offset, ReleaseStoreTag); inline ProtectedPointerSlot RawProtectedPointerField(int byte_offset) const; inline ProtectedMaybeObjectSlot RawProtectedMaybeObjectField( int byte_offset) const; #ifdef VERIFY_HEAP inline void VerifyProtectedPointerField(Isolate* isolate, int offset); #endif static constexpr int kHeaderSize = HeapObject::kHeaderSize; OBJECT_CONSTRUCTORS(TrustedObject, HeapObject); }; V8_OBJECT class TrustedObjectLayout : public HeapObjectLayout { public: DECL_VERIFIER(TrustedObject) } V8_OBJECT_END; // A trusted object that can safely be referenced from untrusted objects. // // These objects live in trusted space but are "exposed" to untrusted objects // living inside the sandbox. They still cannot be referenced through "direct" // pointers (these can be corrupted by an attacker), but instead they must be // referenced through "indirect pointers": an index into a pointer table that // contains the actual pointer as well as a type tag. This mechanism then // guarantees memory-safe access. // // We want to have one pointer table entry per referenced object, *not* per // reference. As such, there must be a way to obtain an existing table entry // for a given (exposed) object. This base class provides that table entry in // the form of the 'self' indirect pointer. // // The need to inherit from this base class to make a trusted object accessible // means that it is not possible to expose existing utility objects such as // hash tables or fixed arrays. Instead, those would need to be "wrapped" by // another ExposedTrustedObject. This limitation is by design: if we were to // create such an exposed utility object, it would likely weaken the // type-safety mechanism of indirect pointers because indirect pointers are // (effectively) tagged with the target's instance type. As such, if the same // object type is used in different contexts, they would both use the same type // tag, allowing an attacker to perform a "substitution attack". As a concrete // example, consider the case of a trusted, exposed byte array. If such a byte // array is used (a) to hold some sort of bytecode for an interpreter and (b) // some sort of trusted metadata, then an attacker can take a trusted byte // array from context (a) and use it in context (b) or vice versa. This would // effectively result in a type confusion and likely lead to an escape from the // sandbox. This problem goes away if (a) and (b) each use a dedicated object // with a unique instance type. It is of course still possible to build new // utility objects on top of this class, but hopefully this comment serves to // document the potential pitfalls when doing so. class ExposedTrustedObject : public TrustedObject { public: // Initializes this object by allocating its pointer table entry. This // initializer function immediately makes the trusted object accessible from // within the sandbox ("publishes" it). If that is undesirable (e.g. because // the object may be in an inconsistent state or require addition // validation), use the InitDontPublish variant instead. inline void InitAndPublish(Isolate* isolate); inline void InitAndPublish(LocalIsolate* isolate); // Initializes this object by allocating its pointer table entry, but doesn't // yet make the object accessible from within the sandbox. This is achieved // by using a special "unpublished" tag for the table entry, which causes any // access to the object via the table (so from within the sandbox) to fail // the type check. The object will need to be published manually before it // can be used by calling the Publish method. inline void InitDontPublish(Isolate* isolate); inline void InitDontPublish(LocalIsolate* isolate); // Publishes this object so it becomes accessible from within the sandbox. // // This is only needed if the object was initialized without publishing it, // in which case its pointer table entry will not be usable (as it uses an // invalid type tag) until this method is called. inline void Publish(IsolateForSandbox isolate); // Returns true if this trusted object is "published", i.e. accessible from // within the sandbox via the trusted pointer table. inline bool IsPublished(IsolateForSandbox isolate) const; // Returns the 'self' indirect pointer of this object. // This indirect pointer references a pointer table entry (either in the // trusted pointer table or the code pointer table for Code objects) through // which this object can be referenced from inside the sandbox. inline IndirectPointerHandle self_indirect_pointer_handle() const; DECL_VERIFIER(ExposedTrustedObject) #ifdef V8_ENABLE_SANDBOX // The 'self' indirect pointer is only available when the sandbox is enabled. // Otherwise, these objects are referenced through direct pointers. #define FIELD_LIST(V) \ V(kSelfIndirectPointerOffset, kIndirectPointerSize) \ V(kUnalignedHeaderSize, OBJECT_POINTER_PADDING(kUnalignedHeaderSize)) \ V(kHeaderSize, 0) \ V(kSize, 0) DEFINE_FIELD_OFFSET_CONSTANTS(TrustedObject::kHeaderSize, FIELD_LIST) #undef FIELD_LIST #else // V8_ENABLE_SANDBOX static constexpr int kHeaderSize = TrustedObject::kHeaderSize; #endif // V8_ENABLE_SANDBOX OBJECT_CONSTRUCTORS(ExposedTrustedObject, TrustedObject); }; V8_OBJECT class ExposedTrustedObjectLayout : public TrustedObjectLayout { public: // Initializes this object by allocating its pointer table entry. // This initializer function immediately makes the trusted object accessible // from within the sandbox. If that is undesirable (e.g. because the object // may be in an inconsistent state or require addition validation), use the // InitDontPublish variant instead. inline void InitAndPublish(Isolate* isolate); inline void InitAndPublish(LocalIsolate* isolate); inline IndirectPointerHandle self_indirect_pointer_handle() const; DECL_VERIFIER(ExposedTrustedObject) private: #ifdef V8_ENABLE_SANDBOX // The 'self' indirect pointer is only available when the sandbox is enabled. // Otherwise, these objects are referenced through direct pointers. std::atomic<IndirectPointerHandle> self_indirect_pointer_; #endif // V8_ENABLE_SANDBOX } V8_OBJECT_END; } // namespace internal } // namespace v8 #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_TRUSTED_OBJECT_H_