Issue metadata
Sign in to add a comment
|
Security: efficient Spectre bounds check mitigation
Reported by
dtc...@scieneer.com,
Jan 9 2018
|
||||||||||||||||||||||
Issue descriptionThe 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!
,
Jan 9 2018
,
Jan 10 2018
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.
,
Jan 10 2018
,
Jan 10 2018
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).
,
Jan 10 2018
,
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.
,
Jan 12 2018
If you get chip vendors to answer you all these questions, let us know :)
,
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.
,
Jan 12 2018
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 :)
,
Jan 12 2018
Thank you for the confirmation, and for the hints.
,
Jan 25 2018
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 |
|||||||||||||||||||||||
Comment 1 by dtc...@scieneer.com
, Jan 9 2018