Many of us are dealing with data that should remain secret on a daily
basis. In my case, that's key material in cryptographic implementations.
To protect against side-channel attacks. We write our code in such a way
that the execution of the program is not dependent on the key and other
secret values. However compiler optimizations often makes this very hard
for us, and often our only resort is to fall back to writing in plain
assembly.
Let me give you an example: https://godbolt.org/z/b1-0_J
In this code, the programmer instructs the program to select a value
from the lookup table using a scanning approach, in an attempt to hide
the secret lookup index in `secret_lookup_idx`.
However, LLVM is smart and skips the memory lookups whenever i !=
secret_lookup_idx, exposing the function to cache side-channel attacks.
Now how to prevent this? Most tricks, for example using empty inline
assembly directives[1], are just ugly hacks.
So I am wondering: Is there any support for preventing these kinds of
optimizations? Or is there otherwise a "mostly recommended" way to
prevent these optimizations?
Thanks for your advice.
All the best,
Daan Sprenkels
PS. Perhaps, would there be interest to add such a feature to LLVM?
I found this repository on GitHub[2], adding a `__builtin_ct_choose`
intrinsic to clang. But as far as I know, this has never been upstreamed.
[1]: Chandler Carruth described this trick at CppCon15:
<https://youtu.be/nXaxk27zwlk?t=2472>. See it in practice:
<https://godbolt.org/z/UMPeku>
[2]: <https://github.com/lmrs2/ct_choose>,
<https://github.com/lmrs2/llvm/commit/8f9a4d952100ae03d06f10aee237bf8b3331da89>.
Later published at S&P18.
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
I think adding a builtin to force CMOV or similar instructions on other architectures is long overdue. It’s generally useful, even if one isn’t mitigating speculative execution.
I believe that you can currently get this effect using __builtin_unpredictable in Clang. __builtin_unpredictable wasn't added for this purpose, and it's a hint not a forced behavior, but I believe that it causes the backend to prefer cmov to branches during lowering.
-Hal
On Sep 12, 2019, at 12:30 PM, Daan Sprenkels via llvm-dev <llvm...@lists.llvm.org> wrote:
PS. Perhaps, would there be interest to add such a feature to LLVM?
I found this repository on GitHub[2], adding a `__builtin_ct_choose`
intrinsic to clang. But as far as I know, this has never been upstreamed.
[1]: Chandler Carruth described this trick at CppCon15:
<https://youtu.be/nXaxk27zwlk?t=2472>. See it in practice:
<https://godbolt.org/z/UMPeku>
[2]: <https://github.com/lmrs2/ct_choose>,
<https://github.com/lmrs2/llvm/commit/8f9a4d952100ae03d06f10aee237bf8b3331da89>.
Later published at S&P18.
_______________________________________________ LLVM Developers mailing list llvm...@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
-- Hal Finkel Lead, Compiler Technology and Programming Languages Leadership Computing Facility Argonne National Laboratory
On 9/12/19 5:06 AM, David Zarzycki via llvm-dev wrote:
I think adding a builtin to force CMOV or similar instructions on other architectures is long overdue. It’s generally useful, even if one isn’t mitigating speculative execution.
I believe that you can currently get this effect using __builtin_unpredictable in Clang. __builtin_unpredictable wasn't added for this purpose, and it's a hint not a forced behavior, but I believe that it causes the backend to prefer cmov to branches during lowering.
Hi Chandler,The data-invariant feature sounds great but what about the general case? When performance tuning code, people sometimes need the ability to reliably generate CMOV, and right now the best advice is either “use inline assembly” or “keep refactoring until CMOV is emited” (and hope that future compilers continue to generate CMOV).Given that a patch already exists to reliably generate CMOV, are there any good arguments against adding the feature?
On Sep 13, 2019, at 10:45 AM, Chandler Carruth <chan...@gmail.com> wrote:On Fri, Sep 13, 2019 at 1:33 AM David Zarzycki via llvm-dev <llvm...@lists.llvm.org> wrote:Hi Chandler,The data-invariant feature sounds great but what about the general case? When performance tuning code, people sometimes need the ability to reliably generate CMOV, and right now the best advice is either “use inline assembly” or “keep refactoring until CMOV is emited” (and hope that future compilers continue to generate CMOV).Given that a patch already exists to reliably generate CMOV, are there any good arguments against adding the feature?For *performance* tuning, the builtin that Hal mentioned is IMO the correct design.Is there some reason why it doesn't work?
I don't think the X86 cmov converter pass knows about unpredictable? Do we even preserve that metadata into Machine IR?
AFAIK, no. It doesn't make it past the SDAGBuilder (mostly, it is used in CGP in order to prevent the select -> branch conversion). It also, in both SDAGBuilder and CGP, prevents splitting of logical operations feeding conditional branches - splitting by
forming more branches).
-Hal
int test_cmov(int left, int right, int *alt) {
return __builtin_unpredictable(left < right) ? *alt : 999;
}
Should generate:
test_cmov:
movl $999, %eax
cmpl %esi, %edi
cmovll (%rdx), %eax
retq
But currently generates:
test_cmov:
movl $999, %eax
cmpl %esi, %edi
jge .LBB0_2
movl (%rdx), %eax
.LBB0_2:
retq
On Sep 14, 2019, at 8:35 AM, Chandler Carruth <chan...@gmail.com> wrote:
Hi Chandler,I feel like this conversation has come full circle. So to ask again: how does one force CMOV to be emitted? You suggested “__builtin_unpredictable()” but that gets lost in various optimization passes. Given other architectures have CMOV like instructions, and given the usefulness of the instruction for performance tuning, it seems like a direct intrinsic would be best. What am I missing?