tree: 37cd4b05f614edab207ff664ebf8644b7e543e35
  1. bounded-size-inl.h
  2. bounded-size.h
  3. code-entrypoint-tag.h
  4. code-pointer-inl.h
  5. code-pointer-table-inl.h
  6. code-pointer-table.cc
  7. code-pointer-table.h
  8. code-pointer.h
  9. external-entity-table-inl.h
  10. external-entity-table.h
  11. external-pointer-inl.h
  12. external-pointer-table-inl.h
  13. external-pointer-table.cc
  14. external-pointer-table.h
  15. external-pointer.h
  16. GLOSSARY.md
  17. indirect-pointer-inl.h
  18. indirect-pointer-tag.h
  19. indirect-pointer.h
  20. isolate-inl.h
  21. isolate.h
  22. OWNERS
  23. README.md
  24. sandbox.cc
  25. sandbox.h
  26. sandboxed-pointer-inl.h
  27. sandboxed-pointer.h
  28. testing.cc
  29. testing.h
  30. trusted-pointer-table-inl.h
  31. trusted-pointer-table.cc
  32. trusted-pointer-table.h
src/sandbox/README.md

V8 Sandbox - Readme

A low-overhead, in-process sandbox for V8.

The sandbox limits the impact of typical V8 vulnerabilities by restricting the code executed by V8 to a subset of the process' virtual address space (“the sandbox”), thereby isolating it from the rest of the process. This works purely in software (with options for hardware support to e.g. improve performance) by effectively converting raw pointers either into offsets from the base of the sandbox or into indices into out-of-sandbox pointer tables. In principle, these mechanisms are very similar to the userland/kernel separation used by modern operating systems (e.g. the unix file descriptor table).

The sandbox assumes that an attacker is able to arbitrarily and concurrently modify any memory inside the sandbox address space as this primitive can be constructed from typical V8 vulnerabilities. Further, it is assumed that an attacker will be able to read memory outside of the sandbox, for example through hardware side channels. The sandbox then aims to protect the rest of the process from such an attacker, and therefore any corruption of memory outside of the sandbox address space is considered a sandbox violation.

Usage

To enable the sandbox, simply use v8_enable_sandbox = true in the gn args. The sandbox is only available in 64-bit configurations as it requires large amounts of virtual address space. The sandbox is enabled by default on supported configurations.

Testing

The sandbox is designed to be testable, both manually and automatically.

To use a “sandbox testing” configurations, two steps are required:

  1. V8 needs to be build with v8_expose_memory_corruption_api = true. This will expose a JavaScript Sandbox object through which memory inside the sandbox can be arbitrarily modified. This API effectively emulates an exploit for a typical V8 vulnerability.
  2. The sandbox “crash filter” needs to be enabled. This signal handler will filter out harmless crashes such as access violations inside the sandbox or other, unexploitable crashes. As such, it effectively defines what constitutes a sandbox violation bug. The sandbox crash filter is currently only available on Linux and in d8, where it can be enabled with --enable-sandbox-crash-filter.

The following example demonstrates these two parts:

// Create a DataView that can read and write inside the sandbox.
let memory = new DataView(new Sandbox.MemoryView(0, 0x100000000));

// Create an object to corrupt and obtain its address in the sandbox.
let corruptMe = {};
let addr = Sandbox.getAddressOf(corruptMe);

// Corrupt the object.
memory.setUint32(addr, 0x41414141, true);
memory.setUint32(addr + 4, 0x41414141, true);
memory.setUint32(addr + 8, 0x41414141, true);

// Trigger a crash. The sandbox crash filter will catch it and determine that
// this is _not_ a sandbox violation as it crashes inside the sandbox.
corruptMe.crash();

// The process will now terminate cleanly with a message such as:
// "Caught harmless memory access violaton (inside sandbox address space). Exiting process..."

Resources

The following list contains further resources about the sandbox, in particular various design documents related to it.

  • High-Level Design Document: Discusses the attacker model, goal, and basic design of the sandbox, while linking to the more specific design documents below where appropriate.
  • Sandbox Address Space: Contains additional details about the address space reservation backing the sandbox and how it is allocated.
  • Sandboxed Pointers: Discusses the design of sandboxed pointers, which are pointers that are always guaranteed to point into the sandbox and are for example used to reference ArrayBuffer backing stores.
  • External Pointer Table: The external pointer table is used to securely reference non-V8 (“external”) objects, for example objects owned by the Embedder, from inside the sandbox. This document discusses its design in more detail.
  • Code Pointer Sandboxing: Similar to external objects, pointers to executable machine code also needs to be protected. This is done with the help of a dedicated code pointer table, which is discussed in this document.
  • Trusted Space: Certain V8 objects are considered trusted and must not be corrupted by an attacker. Examples of such objects include bytecode containers and metadata for JIT-generated code. These objects are protected by allocating them outside of the sandbox in the trusted heap space, then referencing them through another pointer table indirection to ensure memory safe access. This document discusses both of these mechanisms.