Spectre mitigation on heap access overflow checks.
This PR adds a conditional move following a heap bounds check through which the address to be accessed flows. This conditional move ensures that even if the branch is mispredicted (access is actually out of bounds, but speculation goes down in-bounds path), the acually accessed address is zero (a NULL pointer) rather than the out-of-bounds address. The mitigation is controlled by a flag that is off by default, but can be set by the embedding. Note that in order to turn it on by default, we would need to add conditional-move support to the current x86 backend; this does not appear to be present. Once the deprecated backend is removed in favor of the new backend, IMHO we should turn this flag on by default. Note that the mitigation is unneccessary when we use the "huge heap" technique on 64-bit systems, in which we allocate a range of virtual address space such that no 32-bit offset can reach other data. Hence, this only affects small-heap configurations.
This commit is contained in:
@@ -1748,6 +1748,34 @@ pub(crate) fn define(
|
||||
.operands_out(vec![a]),
|
||||
);
|
||||
|
||||
ig.push(
|
||||
Inst::new(
|
||||
"selectif_spectre_guard",
|
||||
r#"
|
||||
Conditional select intended for Spectre guards.
|
||||
|
||||
This operation is semantically equivalent to a selectif instruction.
|
||||
However, it is guaranteed to not be removed or otherwise altered by any
|
||||
optimization pass, and is guaranteed to result in a conditional-move
|
||||
instruction, not a branch-based lowering. As such, it is suitable
|
||||
for use when producing Spectre guards. For example, a bounds-check
|
||||
may guard against unsafe speculation past a bounds-check conditional
|
||||
branch by passing the address or index to be accessed through a
|
||||
conditional move, also gated on the same condition. Because no
|
||||
Spectre-vulnerable processors are known to perform speculation on
|
||||
conditional move instructions, this is guaranteed to pick the
|
||||
correct input. If the selected input in case of overflow is a "safe"
|
||||
value, for example a null pointer that causes an exception in the
|
||||
speculative path, this ensures that no Spectre vulnerability will
|
||||
exist.
|
||||
"#,
|
||||
&formats.int_select,
|
||||
)
|
||||
.operands_in(vec![cc, flags, x, y])
|
||||
.operands_out(vec![a])
|
||||
.other_side_effects(true),
|
||||
);
|
||||
|
||||
let c = &Operand::new("c", Any).with_doc("Controlling value to test");
|
||||
ig.push(
|
||||
Inst::new(
|
||||
|
||||
Reference in New Issue
Block a user