Earlier quoted context omitted.
Hi, TLM of the WebAssembly runtime in V8 here. TLDR: it's asm.js's fault. And yes, complexity. The reason that WebAssembly JIT code memory is still RMW (for now) is actually really unfortunate. As you might know, V8's JIT code memory for JS is only writable when the application is quiesced (i.e. JS is not running) and the JIT is either finishing a function or the garbage collector is moving JITted code. It's read-exe…
> TLDR: it's asm.js's fault. > In order to meet our performance goals for fast asm.js validation and startup, the WebAssembly engine does not do up-front compilation of Wasm code coming from asm.js. It sounds like the fault is how you reached your performance goals rather than asm.js itself.
Exploiting the Math.expm1 typing bug in V8
11–20 of 47 posts
Re: Exploiting the Math.expm1 typing bug in V8
#12The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. But if x is -0, it can. That, in turn, means it believes Object.is(Math.expm(x), -0) must always be false. But if x is -0, it's true, not false. That, in turn, means that the JIT believes array[Object.is(Math.expm(x), -0) * INDEX] must be array[0], no matter what INDEX is. But if x is -0, it'll…
I can't get past this part.
When a Googler "believes" Union(PlainNumber, NaN) represents the set of possible return values for a math function and commits that in the code, how is there not an automated set of tests that use one out of every other IEEE754-associated type as input to then check whether it generates output which falls outside the assumed set of types?
I mean in this case you've even got NegativeZero as its own type. What's even the point of having a type with a single value if you don't hurl it at every manually-entered optimization that it could conceivably invalidate?
Re: Exploiting the Math.expm1 typing bug in V8
#13Earlier quoted context omitted.
Hi, TLM of the WebAssembly runtime in V8 here. TLDR: it's asm.js's fault. And yes, complexity. The reason that WebAssembly JIT code memory is still RMW (for now) is actually really unfortunate. As you might know, V8's JIT code memory for JS is only writable when the application is quiesced (i.e. JS is not running) and the JIT is either finishing a function or the garbage collector is moving JITted code. It's read-exe…
> TLDR: it's asm.js's fault. > In order to meet our performance goals for fast asm.js validation and startup, the WebAssembly engine does not do up-front compilation of Wasm code coming from asm.js. It sounds like the fault is how you reached your performance goals rather than asm.js itself.
The properties of asm.js make it inherently less efficient than Wasm.
Re: Exploiting the Math.expm1 typing bug in V8
#14The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. But if x is -0, it can. That, in turn, means it believes Object.is(Math.expm(x), -0) must always be false. But if x is -0, it's true, not false. That, in turn, means that the JIT believes array[Object.is(Math.expm(x), -0) * INDEX] must be array[0], no matter what INDEX is. But if x is -0, it'll…
> The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. I can't get past this part. When a Googler "believes" Union(PlainNumber, NaN) represents the set of possible return values for a math function and commits that in the code , how is there not an automated set of tests that use one out of every other IEEE754-associated type as input to then che…
But if you believe that this is an example of wanton abuse at Google, you can trade on that belief, and in a sense put your money where your mouth is, because this is a whole class of potential bugs, not just one bug; the same pattern will recur for other places where the v8 typer is wrong about the possible results of functions. Go do a sweep! If you find one, the value of the resulting bug might be pretty decent.
Re: Exploiting the Math.expm1 typing bug in V8
#15The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. But if x is -0, it can. That, in turn, means it believes Object.is(Math.expm(x), -0) must always be false. But if x is -0, it's true, not false. That, in turn, means that the JIT believes array[Object.is(Math.expm(x), -0) * INDEX] must be array[0], no matter what INDEX is. But if x is -0, it'll…
> The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. I can't get past this part. When a Googler "believes" Union(PlainNumber, NaN) represents the set of possible return values for a math function and commits that in the code , how is there not an automated set of tests that use one out of every other IEEE754-associated type as input to then che…
Re: Exploiting the Math.expm1 typing bug in V8
#16Interesting how at the end, after acquiring out-of-bounds write access, that it was easiest to leverage the WebAssembly infrastructure to execute code than to build a ROP chain. Apparently WebAssembly heap memory storing generated code is not write protected at all . I guess whatever architecture they have for managing typed memory chunks doesn't make it sufficiently easy to manipulate protection bits dynamically, an…
Hi, TLM of the WebAssembly runtime in V8 here. TLDR: it's asm.js's fault. And yes, complexity. The reason that WebAssembly JIT code memory is still RMW (for now) is actually really unfortunate. As you might know, V8's JIT code memory for JS is only writable when the application is quiesced (i.e. JS is not running) and the JIT is either finishing a function or the garbage collector is moving JITted code. It's read-exe…
It seems to me that the solution is the same for both wasm and asm.js: make the unit of compilation larger than the function, so as to amortize the cost of mprotect.
Re: Exploiting the Math.expm1 typing bug in V8
#17The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. But if x is -0, it can. That, in turn, means it believes Object.is(Math.expm(x), -0) must always be false. But if x is -0, it's true, not false. That, in turn, means that the JIT believes array[Object.is(Math.expm(x), -0) * INDEX] must be array[0], no matter what INDEX is. But if x is -0, it'll…
> The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. I can't get past this part. When a Googler "believes" Union(PlainNumber, NaN) represents the set of possible return values for a math function and commits that in the code , how is there not an automated set of tests that use one out of every other IEEE754-associated type as input to then che…
Re: Exploiting the Math.expm1 typing bug in V8
#18Earlier quoted context omitted.
Hi, TLM of the WebAssembly runtime in V8 here. TLDR: it's asm.js's fault. And yes, complexity. The reason that WebAssembly JIT code memory is still RMW (for now) is actually really unfortunate. As you might know, V8's JIT code memory for JS is only writable when the application is quiesced (i.e. JS is not running) and the JIT is either finishing a function or the garbage collector is moving JITted code. It's read-exe…
I'm not sure how asm.js is relevant here. The issue is that function-level lazy compilation makes compilation too hot to allow for an mprotect call, no? Wouldn't a function-level lazy Web Assembly implementation have the same problem? It seems to me that the solution is the same for both wasm and asm.js: make the unit of compilation larger than the function, so as to amortize the cost of mprotect.
Re: Exploiting the Math.expm1 typing bug in V8
#19Earlier quoted context omitted.
Hi, TLM of the WebAssembly runtime in V8 here. TLDR: it's asm.js's fault. And yes, complexity. The reason that WebAssembly JIT code memory is still RMW (for now) is actually really unfortunate. As you might know, V8's JIT code memory for JS is only writable when the application is quiesced (i.e. JS is not running) and the JIT is either finishing a function or the garbage collector is moving JITted code. It's read-exe…
I'm not sure how asm.js is relevant here. The issue is that function-level lazy compilation makes compilation too hot to allow for an mprotect call, no? Wouldn't a function-level lazy Web Assembly implementation have the same problem? It seems to me that the solution is the same for both wasm and asm.js: make the unit of compilation larger than the function, so as to amortize the cost of mprotect.
Re: Exploiting the Math.expm1 typing bug in V8
#20The fundamental bug here is really slick. The static analyzer in the JIT incorrectly believes Math.expm1(x) can't return -0. But if x is -0, it can. That, in turn, means it believes Object.is(Math.expm(x), -0) must always be false. But if x is -0, it's true, not false. That, in turn, means that the JIT believes array[Object.is(Math.expm(x), -0) * INDEX] must be array[0], no matter what INDEX is. But if x is -0, it'll…
Math.expm1 = (x) => Math.pow(Math.E, (x)) - 1;
With this monkey patched version, Math.expm1(-0) now returns 0. I've been writing JavaScript for a long time and I didn't even know Math.expm1 was a thing. Was it really necessary to implement this inside V8?