A Report from V8

Spectre Badness, Torque Goodness

April 2018

Michael Stanton

  • Google V8: Compiler Team/Manager
  • V8: Feedback Vectors, TurboFan
  • Cats, climbing and old typewriters :p

V8 Team, based in Munich

  • ~25 people
  • A few in San Francisco and London

We work on Chromium

  • Open source
  • Branded also as "Chrome"
  • Chromium is huge - we only know a part!

V8 has many features

  • "Hidden Classes"
  • ICs (Inline caches) - how we learn
  • Generational Garbage Collector
  • Pipelined Architecture

Compilation pipeline with learning

Source
Code

Ignition

Byte
Code

Run for a while

Gather feedback

Google proprietary

Compilation pipeline with learning

Source
Code

Ignition

Turbofan

Byte
Code

Optimized
Code

Google proprietary

Compilation pipeline with learning

Source
Code

Ignition

Turbofan

Byte
Code

Optimized
Code

Deoptimization

Google proprietary

TurboFan

  • The "Last Step" in the Pipeline
  • Inlining
  • Allocation Folding
  • Escape Analysis
  • Load Elimination
  • Write Barrier Elimination
  • etc!

Spectre

  • Speculative Execution exposes secrets
  • Chromium architecture is vulnerable ("rogue ads")
  • Optimizing JavaScript compilers are vulnerable

function lookup(i) {
  let data = 0;
  if (i < secret_size) {
    data = memory[ secret[i] ];
  }
  return data;
}

IFRAME boundary

// pass "nice" values to lookup to train
// the branch predictor
train();

// flush the memory array from the cache
fill_cache_with_junk();

// Pass a "bad" (out of bounds) i value
attack(bi);

// Which region of memory array load
// quickly? 
region = sense();  // timers!

secret_at_bi = compute(memory, region, bi);

Fencing


function lookup(i) {
  let data = 0;
  if (i < secret_size) {
    LFENCE();
    data = memory[ secret[i] ];
  }
  return data;
}

Costs a lot

Masking

 


function lookup(i) {
  let data = 0;
  let MASK = 0xffffffff;
  {MASK, O} = i < secret_size;
  if (O) {
    data = memory[ MASK & secret[i] ];
  }
  return data;
}

Not really JavaScript anymore...

Masking

 


MASK = 0xffffffff;  // CPU register

function lookup(i) {
  let data = 0;
  {MASK, O} = i < secret_size;
  if (O) {
    data = memory[ MASK & secret[i] ];
  }
  return data;
}

Not really JavaScript anymore...

Problems

  • New speculative attacks appear
  • How to test our mitigations?
  • Complexity
    • Does violence to our abstractions

What to do?

  • Move to full site isolation
  • Costs memory, some platforms need the mitigations
  • Longer term: Control Flow Integrity (CFI)

Torque

All the ways to implement a builtin

JavaScript Builtins

  • Array forEach, filter, map, splice, etc.
  • Need to be predictably fast
  • Tension: JavaScript is complex!

JavaScript Builtins

  • Array forEach, filter, map, splice, etc.
  • Need to be predictably fast
  • Tension: JavaScript is complex!
  • Spec compliant
  • Simple
  • Slow/cliffy :(
  • Cliffs/bailouts
  • Complex
  • Fast! :)

JavaScript

Assembly? C++?
Some unholy combination?

Some history

  • Some builtins were in hand-coded assembly
  • Others in JavaScript
  • Others had a C++ "fast path," and would bail out to JavaScript
  • Others had an assembly fast path, would fall back to C++, which would then fall back to JavaScript

Questions?

Google proprietary

Shameless plug

Made with Slides.com