Hacker News new | past | comments | ask | show | jobs | submit login
Blink-dev – Intent to Ship: SharedArrayBuffer (groups.google.com)
113 points by okket on April 7, 2017 | hide | past | favorite | 49 comments



If Chrome is going to ship SharedArrayBuffer, then why will the resolution of performance.now() and other timer APIs continue to be neutered? I don't have any preference one way or the other for implementing SharedArrayBuffer, but I am fully against neutering timers with jitter if a vendor does choose to implement SharedArrayBuffer. Random additional timer jitter becomes a false layer of security in this scenario, and https://bugs.chromium.org/p/chromium/issues/detail?id=506723 should be reverted.

With SharedArrayBuffer you can easily implement extremely high resolution sub-nanosecond timers and open the door to new timing attacks. For example, here is a high resolution SharedArrayBuffer timer: https://codepen.io/yossioren/pen/LVBNMR

For more discussion regarding the security implications of this change, see https://github.com/tc39/ecmascript_sharedmem/issues/1 . Some of the security problems may be mitigable with Intel CAT, although I am not aware of Chrome making use of that yet.


The research papers on the topic suggest the primary mode of attack to be a background tab attacking a sensitive tab also open.

Does the recent Chrome change to limit processor usage of a background tab also neuter this attack vector?


Is there any layman's introduction to this subject? I can't comprehend how having an accurate timer lets me steal information from other processes.


The papers "The Spy in the Sandbox -- Practical Cache Attacks in Javascript" at https://arxiv.org/pdf/1502.07373.pdf and "ASLR on the Line: Practical Cache Attacks on the MMU" at http://www.cs.vu.nl//~herbertb/download/papers/anc_ndss17.pd... are good starting points, though they are not very accessible to a layman.

There have even been timing attacks that let you recover AES keys from analyzing a device's power usage.

In layman's terms: computers are extremely complicated beasts of coordinated timing of software and hardware, and timing data leaks many things about what a piece of software is doing. This is the reason that many modern encryption libraries pad operations as a defense against timing attacks.


Thanks. I had actually started reading The Spy in the Sandbox but it was too hardcore for me.

So, how does this work? I set a timer, and then read the time a bit later, and somehow I recovered an AES key from a different process? I'm still missing a piece :-)

Notably, how can timing data leak things?

I mean, I can see how I can do

    1. Start hi-res timer
    2. Kick off something that involves out-of-sandbox data
    3. Stop hi-res timer
and do this often enough and with well-tuned input to read useful data out. Is that how it works?

But how can I use this to read stuff in entirely different processes? Moreover, how can I do that in a targeted manner? Eg I suspect my target is using internet banking but I don't know which other programs are running, how many cores the machine has, etc etc etc.


> Notably, how can timing data leak things?

That part's simple. Naive crypto code will often vary in speed based on the data. A 0 bit in the key causes some behavior, a 1 bit causes some slightly different behavior, and suddenly if you can measure the length of each step you can recover the secrets.

Getting the timing data is a little bit trickier from javascript, but it's also simple in concept. As sensitive code runs, it affects the CPU cache. Javascript can use memory locations that go in the same cache slots as sensitive code. This goes a few nanoseconds faster or slower based on what parts of the sensitive code have finished. Now you have timing data.

If you don't know what else is running or if you're on the same core, you just have to try repeatedly.


> Notably, how can timing data leak things?

A lot of crypto code, especially implementations of asymmetric crypto, is not constant time, meaning that by timing it's execution you can extract key or plaintext fragments. Of course, authors try to make them as constant time as possible, but it's very, very hard to mask a non-constant time operation (required by some algorithms). So a higher resolution timer for the attacker means that it's easier and faster to attack these applications.

(This was a major design motivation for Curve25519. Previous ECC algorithms all had special cases, which mean non-constant-time, even with masking. Curve25519 was specifically designed to avoid that. -- That doesn't mean you can't implement it badly, though ;)

Due to the memory hierarchy (i.e. the fact that a CPU has caches) key or plaintext-dependent memory accesses lead to time variations as well. There are attacks that can be used to amplify these, by poisoning or preparing the caches in a way that forces main-memory or L3 reads for certain addresses.

(Some badly written libraries also use completely naive implementations, e.g. BouncyCastle used a not-at-all constant time implementation of AES, which was trivial to attack.)


To be very simplistic, timing attacks are a bit like buffer overflows, if you do then just right you can use them to read information about other processes, such as processes you aren't meant to be able to see into.

Where they are different is that timing attacks usually serve as information extraction tools, which attackers can choose to further leverage by basing subsequent attacks on the information they obtained, where as buffer overflow attacks can do pretty much anything up to and including rooting a box or breaking out of a hypervisor.


The amount of time something takes is often related to the input. Measuring the time, gives you information on that input.

For example measuring the time of a=b with constant b tells you roughly how large a[:n] such that a[:n] = b[:n].


I am not sure I like some of the new changes. It seems to me like JS is expanding both towards an upper level language and a lower level language, which frankly makes it look more like a Frankenlanguage. I guess it's the limitations of having a single real language to be used in the browsers.

Edit: just check this tutorial. I'd venture to guess to 99% of JS developers it sounds totally bizarre: https://github.com/tc39/ecmascript_sharedmem/blob/master/TUT...


But that is exactly what is needed. JavaScript is essentially a becoming a ~native~ language (like C, C++, Java) which is used to implement all kinds of abstractions.

Think of C++ for example. It's used to implement frameworks like JUCE, used for high-level application logic and UIs, but underneath that there are a lot of optimised abstractions. Some of these abstractions can only be so good or so deep until the language they are implemented in can get closer to the "metal" (or in this instance, VM).

I for one welcome these new additions to the ECMAscript spec.


> ... ~native~ language (like C, C++, Java)

One of those is not like the others.


Surprisingly enough, Java is a native language in some parts of the embeded world (see smart cards for instance, but not only [1]).

[1]: https://en.m.wikipedia.org/wiki/Java_processor


Also Android.


C++ was OS-native on some older now extinct systems, like Symbian and BeOS.


I think he's talking about Java


There are coprocessors that run Java Bytecode directly. Is there actually an implementation of the machine outlined in the C standard? Clearly C is an abstraction while Java is a truly native language.


Well those processors just run bytecode compiled from Java source code. The same is true of more traditional processors they just run bytecode compiled from c source code. I thicnk they are both doing essentially the same thing.


So what are the properties of C bytecode? Other than undefined, implementation defined and format C:\\ ? Java specifies a high level language, the low level bytecode and a target machine while C has to abstract over the byte code and large parts of the machine, leaving it up to the developer to fight countless "implementations". Guaranteeing that the same code is simultaneously right, wrong and file not found while limiting access to features exposed by the underlying "bytecode" in ways that require software workarounds like fmadd that are used in place of hardware.

Clearly the Java language -> Java bytecode -> Java Hardware chain is inherently more native and consistent than C language -> C Virtual Machine -> x64 -> Intel Core 2, where each step in the C language chain looses access to features of the underlying layer.


But not really, Javascript has to be interpreted/JITed, so it will never be in the same level as C/C++. IMO it'd be way better to:

- Introduce real native types, not complex-named functions that are way more bothersome to work with than types.

- Use WASM or something similar to provide for a low level variant.


I believe the issue is in building high performance types that are both secure and that fit in with the rest of js.


JIT can be faster than static compilation.


Javascript is less than ideal for this, and was never designed with this sort of thing in mind, unlike C/C++.

Plus, web assembly is here.


How is web assembly going to help with multithreading?


It's one of the primary goals of the project

> Provide low-level buildings blocks for pthreads-style shared memory: shared memory between threads, atomics and futexes (or synchronic).

New atomic memory operators, including loads/stores annotated with their atomic ordering property, will follow the C++11 memory model, similarly to the PNaCl atomic support and the SharedArrayBuffer proposal. Regular loads and stores will be bound by a happens-before relationship to atomic operators in the same thread of execution, which themselves synchronize-with atomics in other threads. Following these rules, regular load/store operators can still be elided, duplicated, and split up. This guarantees that data-race free code executes as if it were sequentially consistent. Even when there are data races, WebAssembly will ensure that the nondeterminism remains limited and local.


I think the idea is for these things (much like TypedArray and the like) to be used by "compile-to-JS" languages, rather than to be used directly too often.


Making them accessible from WASM is also likely to happen in the future, as they're perfect for running truly multithreaded C/C++, Rust, etc. code.


We certainly don't seem to know when to stop extending software.


You mean like Python? I agree.


Added a tutorial on SharedArrayBuffer with a lot of other low level JS stuff that looks like a total different language.


Has python gotten much more low level recently?


  import ctypes
  from multiprocessing import Array
  mysharedarray = Array(ctypes.<type>, 100)
That's essentially the same as this proposal.


I would say async is a little bit lower level, but not at the atomic array level.


This is great. It opens up a lot of possibilities for our online 3D editor - background worker threads that each work on a segment of an array.

Now if only Node.JS could support worker threads at all.


In NW.js you can use Node.js in Web Worker: https://nwjs.io/blog/v0.18.4/ . HTH.


why is it available in NW.js but not Node?


I think Node community is working on it. In NW the implementation of webworker from browser can be leveraged.


The main benefit here will be realized in Shared Workers. Unfortunately Edge support is "not planned" and WebKit support is "removed" http://caniuse.com/#feat=sharedworkers

I guess it may come in handy for Electron apps.


You don’t need Shared Workers to benefit from this. I haven’t ever actually used Shared Workers, but as I understand it the normal sort of case for them could be polyfilled without too much difficulty.

Using Web Workers instead of Shared Workers just means that any actual communication beyond the shared memory must be posted via the instantiator of the worker.


You're right about Shared Workers not being needed for this, but just to continue going off on a tangent...

I think a polyfill would be pretty difficult. First you have to make sure only one tab starts a Web Worker. Maybe that's not impossible, but it's tricky. And then the real difficulty... when the tab that spawned the Web Worker closes while another tab is open, you'd need to spawn another Web Worker in that tab and copy the state of the first Web Worker to the second Web Worker before the first one is destroyed by the browser. Not sure if that's possible.


You can use broadcastchannel to coordinate multiple tabs and workers. And I think once you receive a message from such a channel you get a proxy for the sender, which means you can establish a 1-1 channel, which in turn means you can can transfer objects like sharedarraybuffer.


I've just stumpled once again on atob/btoa not working with characters like or 𝒞 and here I read about SharedArrayBuffers, which is way a greater goal. Of course they're right to work on such projects, go for it, but I can't avoid to be baffled by the fact that (apparently) more mundane operations don't receive love.

Other examples would be MD5 removed from subtlecrypto, killing any way to speak with services that use it for non-cryptographic operations, or the missing functions to encode/decode hex strings, which maybe are not everyday use cases but are provided by most languages and would need an afternoon to write with tests.

I want a better standard library. Just my discouraged 5 cents.


atob/btoa is atrocious from an API design standpoint. Here we are, designing an API to convert things to Base64 and back and we use a string as a byte array substitute, nevermind the fact that strings are not limited to Latin-1. There's probably a bunch of libraries that solve this, but stumbling over this in a library that has no outside dependencies is a bit annoying since you have to solve it yourself ... again.


I'm just curious since I never used this feature, are you talking about this issue?

> The "Unicode Problem"

> Since DOMStrings are 16-bit-encoded strings, in most browsers calling window.btoa on a Unicode string will cause a Character Out Of Range exception if a character exceeds the range of a 8-bit ASCII-encoded character. There are two possible methods to solve this problem:

https://developer.mozilla.org/en/docs/Web/API/WindowBase64/B...


Yes, that one


> Gives JavaScript access to shared memory, atomics, and futex.

Holy fuck, this is going to be bad, introducing a whole continent of new bugs into JavaScript land. And also giving JS even more and even better options to spy and attack other applications on the same computer.


Yes, it introduces a whole new range of multithreading issues also to JS land.

However I think threading issues won't be as common as in C++/Java/C# land, since the only thing that will be shared between threads/workers is byte arrays -> There's no shared access to other Javascript objects. As most normal JS developers won't be dealing with plain byte arrays the potential for misuse is not too high.


SharedArrayBuffer and Atomics is already in Chrome, unluckily behind the flag.


This is GREAT! Transferable's didn't make sense in a few situations.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: