New issue
Advanced search Search tips

Issue 800503 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Jan 2018
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: ----
Type: Bug-Security



Sign in to add a comment

Security: efficient Spectre bounds check mitigation

Reported by dtc...@scieneer.com, Jan 9 2018

Issue description

The current V8 Spectre bounds check mitigations use index masking when necessary (among other strategies). The current approach simply masks off some high bits, but that still leaves a potentially large area beyond the end of the array that might be vulnerable.

For example the current approach seems to have landed with https://chromium-review.googlesource.com/c/v8/v8/+/830394 and there is now a follow up to add padding to address this https://chromium-review.googlesource.com/c/v8/v8/+/856980

Other approaches, for JS array indexing, also use a form of masking but masks out the index precisely, see https://chromium-review.googlesource.com/c/v8/v8/+/831517 however that appears rather slow particularly compared with the potential mitigation proposed here.

I would like to suggest one alternative strategy that does not appear to have been explored, might need feedback from Intel etc who have not responded to me personally. The idea is to create a data dependency on the array length so that the protected memory access can not execute until the same time that the speculative bounds check branch can execute. Tests suggests this is faster than the current index masking approaches. Please see https://weblll.org/index.php/spectre-bounds-check-data-flow-mitigation/

If the masking strategy is to be followed then as people know I was pushing that for many years and demonstrated very competitive performance and obviously have many ideas for that too!

 
This is not really security sensitive now, the exploit is well known now, and v8 appears to be addressing the wip problem with padding, but this is more about performance and wider feedback would be welcomed so please remove the restriction.
Components: Blink>JavaScript
I'm pretty sure that the suggested approach won't work. The CPU will just speculate past the branch, and will still access the memory before speculation aborts.
Cc: clemensh@chromium.org titzer@chromium.org verwa...@chromium.org

Comment 5 by titzer@chromium.org, Jan 10 2018

Status: WontFix (was: Unconfirmed)
Agree with verwaest@, this is not an effective mitigation.

Closing this issue as "WontFix"--not because we won't fix this bug, but because the suggested approach unfortunately does not work in all cases (as confirmed in internal testing).

Comment 6 by titzer@chromium.org, Jan 10 2018

Labels: -Restrict-View-SecurityTeam

Comment 7 by dtc...@scieneer.com, Jan 12 2018

Thank you for the feedback. Would you be able to share a case in which it does not work? I know of many issues that would break it, for example if the result of the subtraction spilled to the stack and need to be reloaded, but it would be good to understand the constraints and if they are really hopeless to workaround.

My own limited testing showed that it did address the issue. verwaest@ the proposal does not depend on the processor not speculating past the branch, that can still occur, it is just that the memory access also depends on that input, so when the memory access can proceed the branch that proceeded it also has all its inputs on hand.

Is there any published information about when speculation aborts? Is there any practical limit.

It's very useful to know that speculation occurs and this information can be leaked, but can compiler developers expect any guarantees about when and how speculation ends?

It's getting off topic, but knowing more about how speculation aborts, and any ordering guarantees if any, would be very helpful. Without some confidence it might become impossible to hoist bounds check out of loops etc and compilers might be reduced to unrolling and only hoisting a bounds check above that.

This is not an objection to using masking, rather trying to settle if masking is the only practical solution. 
If you get chip vendors to answer you all these questions, let us know :)

Comment 9 by dtc...@scieneer.com, Jan 12 2018

> If you get chip vendors to answer you all these questions, let us know :)

You did claim to have a refutation, and that might be enough to cast this proposal as hopeless?

This proposal does offer some hope, and the alternative might be a huge burden.

I presume you are correct, but still I would like that to be verified and to see that it is hopeless and not something that could be worked around for a potentially better outcome.

Unfortunately we are not able to share PoC due to legal reasons, but roughly, AFAWK the order in which the pending branches are verified is not specified, which can lead to an earlier, much slower, condition allowing the CPU to continue to speculate past the branch in your example.

At this point we are using measures that introduce an explicit data dependency (e.g. poisoning) or remove some of the user-controlled information (e.g. masking).

verwaest's comment was spot on. Vendors are very tight-lipped with their trade secrets :)
Thank you for the confirmation, and for the hints.
Here is another suggestion that avoids any race between the branch and the load and appears to have some potential and might be worth exploring https://weblll.org/index.php/spectre-bounds-check-mitigation-using-a-subtraction-with-borrow/ It uses instructions listed in the Intel publication https://software.intel.com/sites/default/files/managed/c5/63/336996-Speculative-Execution-Side-Channel-Mitigations.pdf A key pattern came from the Linux kernel discussions and the uses a subtraction with borrow from zero to generate the mask from the comparison and for the JS sandbox this can be usefully fused with the bounds check branch. Is this something your team has considered for use cases in which arrays not guarded (where the fast strategy used for wasm is not applicable)?

Sign in to add a comment