ReviewOS

zig-utils/zig-js

Threads: securely seed the ThreadLocal value index

#873
Closed chris opened this 9 days ago ·
9 days ago

Parent: #493 Related: #478, #482, #480

Problem

ThreadLocal stores its per-thread values in std.AutoHashMapUnmanaged(u64, Value), keyed by the current OS thread ID. The default integer hash has fixed, public bucket placement while JavaScript controls thread creation and ThreadLocal.value insert/read/remove schedules. Collision-amplified probes therefore execute while holding map_lock, turning predictable placement into an avoidable shared-realm latency and denial-of-service surface.

Required implementation

  • Replace the fixed-hash table with an exact-u64 map whose bucket placement is seeded from the engine secure RNG.
  • Install entropy lazily on the first non-undefined store so constructing or reading an empty ThreadLocal remains allocation- and entropy-free.
  • Publish the hash context only after the first backing allocation succeeds; entropy or allocation failure must follow the existing OOM path with no clock/address/constant fallback and no half-published value.
  • Preserve exact thread-ID equality, owner-thread cleanup, wrapper ownership/barriers, root tracing, moving relocation, and the existing map_lock synchronization ruling.
  • Do not weaken locking, retain exited-thread values, add unbounded reserves, or recognize test/benchmark inputs.

Acceptance

  • A deterministic collision witness shows legacy integer-bucket collisions disperse under a nonzero installed seed.
  • Empty get/remove paths consume no entropy; first-store entropy/allocation failures publish neither a context nor a value.
  • Repeated stores reuse the installed context and exact thread IDs remain the equality authority.
  • Thread exit removes its exact value and does not disturb peer values.
  • Focused ThreadLocal lifecycle/GC tests pass in Debug, ReleaseSafe, and suppression-free TSan.
  • Relevant threadfuzz profiles and the full unit suite pass with zero failures/leaks.
  • The change is documented in the public concurrency contract and changes 0 Test262 cases because ThreadLocal is a zig-js extension.
9 days ago

Implemented and pushed to main in 3cf4429e.

The ThreadLocal index now installs an independently CSPRNG-seeded exact-u64 hash context on the first store. Empty reads/removals remain entropy- and allocation-free; entropy/allocation failures publish neither the context nor a value; later stores reuse the installed context. The existing per-instance lock, exact thread-ID equality, thread-exit cleanup, write barriers, tracing, and moving relocation remain unchanged.

Validation:

  • deterministic legacy collision witness: 32 fixed-placement IDs dispersed across more than half of the keyed buckets
  • secure-index test: 1/1
  • focused ThreadLocal tests: 3/3 in Debug, ReleaseSafe, and suppression-free TSan
  • nursery native-side-record GC test: 1/1 in Debug, ReleaseSafe, and suppression-free TSan
  • threadfuzz default: 400/400, 0 failures
  • threadfuzz lifecycle: 22,400/22,400, 0 failures
  • full unit inventory: 2,296 passed, 1 skipped, 0 failed, 0 leaked (2,297 total)
  • docs: 50 pages built; 328 links resolve

Test262 was not run: ThreadLocal is a zig-js extension, so this changes 0 Test262 cases.

Sign in to comment on this issue.