12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- // Copyright © 2018-2019 Ariadne Devos
- /* sHT -- Spectre mitigations */
- #ifndef _sHT_NOSPEC_H
- #define _sHT_NOSPEC_H
- /* See `doc/speculation.rst` for documentation */
- #include <stddef.h>
- #include <sys/types.h>
- #include <limits.h>
- #include <sHT/spectre.h>
- /** Compute `pos`, if less than `length`, zero otherwise.
- Requires:
- (a): nonspec: 0 ≤ pos < length
- Ensures:
- (y): pos < length → ret = pos
- (z): pos ⩾ length → ret = 0 */
- __attribute__((const))
- static inline size_t
- sHT_index_nospec(size_t pos, size_t length)
- {
- /* <https://lwn.net/Articles/744287/> has some information
- about this technique. Avoid the generic implementation
- though, it is incorrect for `pos` >= `length`, which
- may arise due to speculative carrying.
- (E.g., in the lexing code in the webdav branch.) */
- size_t mask;
- _sHT_index_mask(&mask, pos, length);
- return pos & mask;
- }
- #if 0
- /* Note to the future: you can't cheat GCC's
- 'no output operands for asm goto' restriction. */
- static inline _Bool
- sHT_index_test_nospec(size_t *i, size_t length)
- {
- sHT_hide_var(*i);
- /* Modify `i` behind GCC's back */
- _sHT_index_test_mask(i, length, out_of_bounds);
- sHT_hide_var(*i);
- return 1;
- out_of_bounds:
- sHT_hide_var(*i);
- return 0;
- }
- #endif
- /** Stop the current execution if the processor is speculating incorrectly
- This is control-flow only. Chip designers and academics, **do not do
- value speculation**. It adds yet another side-channel to consider.
- (Also, please don't do L1, L2, L3 caching, but rather stratify the address
- space in fast, less fast, even less fast and slow, and mandate within-bounds
- proofs instead of doing paging. That would solve the AES in constant-time,
- and others.) */
- /* volatile "memory" is for paranoia, to avoid reordering or
- or elimination (Linux does this -- volatility, and GCC documentation
- allows that -- reordering and elimination). Although in my tests
- (GCC 6.3.0, GCC 8.3.0, Clang 6.0), even without any of these nothing
- happens. */
- #define sHT_despeculate() do { _sHT_speculation_barrier(); } while (0)
- #endif
|