Re: RFC: Re: shader IR vs. application IR

> On Aug 16, 2017, at 6:48 PM, Kai Ninomiya <kainino@google.com> wrote:
> 
>> On Wed, Aug 16, 2017 at 6:40 PM Filip Pizlo <fpizlo@apple.com> wrote:
>>> On Aug 16, 2017, at 6:27 PM, Kai Ninomiya <kainino@google.com> wrote:
>>> 
>>> WebAssembly's IR doesn't (and can't possibly) guarantee memory safety on its own. It relies on the execution environment (WebAssembly VM in this case) to provide these guarantees - but a WebAssembly VM could exist which omits memory safety checks.
>> 
>> This is not accurate. WebAssembly’s semantics for memory accesses were deliberately designed to allow scalable bounds checking. This includes peculiarities in the spec of how offsets are computed, that are there because they make safety checks cheaper.
> I don't mean to say that WebAssembly is not _designed_ to be executed in a memory safe way - it is. Just that its IR isn't intrinsically memory safe - the spec defines behavior for the VM to ensure safety.

Memory safety is a property of wasm. You get to allocate an array called “linear memory”. You are allowed to attempt to grow this array. You can’t access outside it’s bounds. If you do, you are deterministically aborted. 

This is unlike having pointers that can be targeted at arbitrary memory via bitcast, with nasal daemons as the semantics of dereference (like in C). 

> I agree that there are design decisions in WebAssembly which optimize these bounds checks.

This is an important point, maybe even more important than the question of whether WebAssembly is secure by spec or by impl. You can give programmers more expressiveness and more performance if you design the language’s semantics to optimize the bounds checks. This observation is part of the genius of WebAssembly. I think that would be hard to do in SPIR-V since a lot of choices have already been made. 

>  
>> Also, safety checks in WebAssembly are mandatory. An implementation that does not do them would not be conformant. 
> Of course a non-safe WebAssembly implementation wouldn't be conformant, but it could exist - a security-insensitive environment could hypothetically just omit bounds checks to squeeze out a little bit of performance.

Technically such a system would not really be running WebAssembly. The behavior of bounds check failure is detectable and could even be triggered deliberately. So, removing bounds checks is a change to the language. It’s not WebAssembly anymore if you do that. 

> 
> -Kai
> 
>> -Filip
>> 
>>> Based on my non-expert understanding of WebAssembly, this is how it handles some of the example issues you gave:
>>> 
>>> > Any exposure of pointer values
>>> > Pointer arithmetic
>>> > Read or write to any location without bounds checks
>>> > Ability to read or write another process's main or video memory
>>> > Ability to read or write another shader's main or video memory
>>> > Ability to read or write video memory that holds the contents of a webpage, even one that is same-origin with the shader
>>> 
>>> Prevented by either (a) bounds checks (against the size of global memory) in the AOT/JIT generated native code, or (b) by CPU MMU control.
>>> (In a shader, of course, each resource would have its own bounds check sizes. So bounds constants probably can't be baked into the AOT/JIT generated code.)
>>> 
>>> > Ability to hold a pointer or reference to an object after it may have been freed, and still perform access through it
>>> > Potential for race conditions which may lead to access to out-of-bounds, freed, reallocated or not-yet-freed memory
>>> 
>>> Heap allocations do not exist at the IR level (except for "request global memory expansion"). malloc and free are implemented inside the wasm program.
>>> Shaders do not allow "heap"/"global memory" allocations (and I don't think SPIR-V provides a way to do them).
>>> 
>>> > Function call or jump to an arbitrary addresses (jumping to known functions or labels is ok)
>>> > Mixing dynamically indexed data structures, and function pointers or executable code in the same memory space
>>> 
>>> WebAssembly instructions are not stored in program-accessible memory. Jumps are only possible to known functions and labels. Both seem to be true of SPIR-V as well.
>>> 
>>> > Ability to execute an infinite loop without ever being interrupted by a watchdog or the like
>>> 
>>> Just like a JS infinite loop, the process can be killed or the VM can generate cooperatively-terminable code. For WebGL, a watchdog is typically used.
>>> 
>>> -Kai
>>> 
>>>> On Wed, Aug 16, 2017 at 5:24 PM Maciej Stachowiak <mjs@apple.com> wrote:
>>>> 
>>>>>> On Aug 16, 2017, at 4:39 PM, Dean Jackson <dino@apple.com> wrote:
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> On 17 Aug 2017, at 05:08, Maciej Stachowiak <mjs@apple.com> wrote:
>>>>>> 
>>>>>> But bolting on security is not impossible; as you point out, it's been done for GLSL.
>>>>> 
>>>>> Restricting GLSL for security wasn't particularly difficult. It doesn't have pointers, for example. This is another argument for a language that is slightly higher than an IR: It probably will be easier to secure.
>>>> 
>>>> I'm not totally sure that's true. WebAssembly is an example of an IR that has memory safety designed in. A colleague pointed out to me that WebAssembly also takes a very hard stance on limiting nondeterminism: <https://github.com/WebAssembly/design/blob/master/Nondeterminism.md>. This is in contrast with SPIR-V where many things are undefined.
>>>> 
>>>> To be clear, I am *not* saying WebAssembly should be the shader format. I think it's probably not appropriate, because its memory safety depends in part on limiting the whole WebAssembly program to a single contiguous memory region. To the best of my understanding, that would not really work for shaders. I'm just citing it as an example of a binary IR language that meets web safety requirements, because it was designed with them in mind.
>>>> 
>>>> Java bytecode is arguably another IR designed for memory safety, though the complexity of their strategy for achieving it made Java not actually very web safe in practice.
>>>> 
>>>>  - Maciej
>>>> 
>>>>> For the SPIR-V folks, has any implementation actually used Logical Addressing Mode? I'd also like to understand what these proposed restrictions to SPIR-V mean for compute shaders. How are they impacted by Logical Addressing Mode?
>>>> 

Received on Thursday, 17 August 2017 02:04:20 UTC