[HN Gopher] The Life of an Optimization Barrier
___________________________________________________________________
The Life of an Optimization Barrier
Author : ingve
Score : 41 points
Date : 2022-01-26 12:20 UTC (1 days ago)
(HTM) web link (blog.trailofbits.com)
(TXT) w3m dump (blog.trailofbits.com)
| staticassertion wrote:
| > What is missing is a way forward for getting secret types and
| the corresponding semantics into LLVM.
|
| Seems crazy that this hasn't happened already given how prevalent
| and old this issue is.
| tigersforhire wrote:
| I think one reason is that it actually entails a pretty big
| lift from LLVMs side since it would introduce a new invariant
| that needs to be upheld by optimization passes and code
| generators.
|
| I've heard rumours that Google have done some work internally
| in this area, but it was never open sourced or upstreamed.
| staticassertion wrote:
| The thing is that this issue predates LLVM. It just feels
| like the sort of thing that would have been brought up really
| really early in the process, like as soon as anyone used it
| for any real world project.
|
| I imagine it's not straightforward, just seems like the
| effort would have started earlier.
| vlovich123 wrote:
| Most projects targeting binaries provide coarse escape
| hatches that work well enough (in the form of asm
| volatile). This is a new space where we now need to persist
| the optimization to work correctly through one AOT pass and
| then a totally separate JIT which is a new thing and I'm
| not surprised there's work to be done.
| staticassertion wrote:
| That's true - we're definitely working with much more
| complex compilation pipelines now.
| adrian17 wrote:
| > packaging a library as an npm module using wasm-pack (...) the
| code would be optimized twice before being executed, first by
| LLVM and then by the Turbofan JIT compiler
|
| Actually, that's not entirely true; if running wasm-pack, there's
| another optimizer `wasm-opt`, running on output of llvm and wasm-
| bindgen.
|
| I've found it able to produce measurable improvements in speed
| and size of the produced .wasm - which is quite surprising to me,
| given it's basically a set of simple (compared to llvm)
| optimization passes running on top of whatever llvm already
| produced, with none of the metadata. However, this also means it
| can easily do unexpected things like inlining a
| `#[inline(never)]` function (because again, it only sees the
| .wasm file, with none of rust or llvm metadata) - I stumbled upon
| this several times when trying to profile wasm code in browsers.
|
| This also means that if llvm ever supported constant-time
| semantics, wasm-opt would happily ignore these too.
| codeflo wrote:
| You really do need to look at the whole chain. Of course, if
| Wasm had constant-time annotations as suggested by the article
| author, you'd expect wasm-opt to respect those.
|
| Then there are steps below that layer to consider as well.
| Maybe not so relevant when targeting Wasm, but x86 code is
| increasingly executed inside emulators on ARM chips. Do those
| respect the constant-timeness?
|
| And what about processor microcode and fused instructions, can
| a future CPU include an optimization that will un-constant-time
| your code? (In other words: I really don't know, are there
| constant-time guarantees made by the ISA?)
| woodruffw wrote:
| > (In other words: I really don't know, are there constant-
| time guarantees made by the ISA?)
|
| Not on AMD64, at least: neither Intel nor AMD will guarantee
| the timing behavior or timing complexity of an instruction
| between processors. REP prefixes with string/data operations
| exemplify this -- they historically had data-dependent
| timings, but have become increasingly decoupled as both Intel
| and AMD have shoved "fast string" modes into ucode.
| rwilson4 wrote:
| Am I the only one who clicked on this expecting to read about the
| barrier method for interior point algorithms?
| akireu wrote:
| codeflo wrote:
| We pay a very heavy price for the complexity of modern compilers:
| slow compilation times even on crazy fast hardware, real-world
| bugs from undefined behavior propagation, and now here, leaking
| cryptographic secrets unless heroic engineering efforts are made
| to prevent it.
|
| What we get in return for all that pain is slightly faster
| execution -- in theory. A recent post on HN actually showed that
| at least in some cases, modern LLVM compiles to code that
| actually runs 1-2% slower than an ancient LLVM version.
|
| Shouldn't we conclude from all this that what we need is a
| movement to go back to simple, deterministic and fast compilers?
| flerchin wrote:
| > What we get in return for all that pain is slightly faster
| execution
|
| We also get protections against whole classes of security bugs,
| ala Spectre and other vulns. Some of those protections make
| speed tradeoffs.
| codeflo wrote:
| I don't agree that exploit mitigation is where the bulk of
| the complexity in the compiler comes from. And if anything,
| with all the UB inference going on, modern compilers might be
| more likely to compile exploitable bugs into your code than
| old ones were. Several well-known examples of this happening
| exist.
|
| (To explain: A decade ago, if there was a code path where you
| dereference null, you would get a clean crash. Not pretty,
| and potentially a denial of service, but usually not further
| exploitable. Nowadays, the compiler will infer that this path
| is not taken, eliminate the if, potentially eliminate other
| checks as well because they are then reasoned to be
| redundant, and then randomly execute _something_. This is
| practically more dangerous in a lot more situations than
| Spectre ever was.)
| flerchin wrote:
| It's pretty easy to disable the spectre mitigations, and
| pretty easy to measure the performance impact (~10% in some
| workloads).
| bastawhiz wrote:
| It would seem to me that your comment only really applies to C
| or C++ or other similar languages. Modern JavaScript compilers
| can compile and run code orders of magnitude faster than what
| was possible fifteen years ago. Many languages have seen
| dramatic compiler improvements.
|
| Maybe the problem is that making big improvements to a compiler
| for a fifty year old language that sits pretty close to the
| metal is getting increasingly difficult because the people
| writing the compilers are running out of clever tricks.
| codeflo wrote:
| With all respect, we're discussing an article about the
| difficulty of balancing performance and security in modern
| compilers in the context of implementing cryptographic
| primitives. You might use those primitives from JavaScript
| (Node.js links OpenSSL, for example), not typically implement
| them in JavaScript.
| bastawhiz wrote:
| One of the two compilers discussed in the article is
| Turbofan because the code in question is being invoked from
| JavaScript, so I'm not sure how you think JavaScript isn't
| relevant. We live in an age where not everything, including
| cryptography, needs to traverse C or C++ to reach machine
| code (see: Java, Go, etc).
|
| Plenty of JavaScript and WASM exists for cryptography
| purposes, for what it's worth, because Node isn't the only
| runtime and "native" code isn't easily portable.
| SkyMarshal wrote:
| If it's not clear from the title, this article is about
| maintaining the constant-time property of Rust cryptographic
| libraries when compiler optimizations tend to compromise that
| property.
|
| There should probably be some kind ----constant-time compiler
| flag to prevent the compiler from compromising that property when
| it's a higher priority than raw performance.
| vlovich123 wrote:
| There's so many optimization passes that happen in a compiler
| that I doubt such a flag is feasible. The CT types work is
| probably a better avenue.
___________________________________________________________________
(page generated 2022-01-27 23:02 UTC)