Merge pull request #1930 from cfallin/spectre-heap
Spectre mitigation on heap access overflow checks.
This commit is contained in:
@@ -1395,6 +1395,7 @@ fn define_alu(
|
||||
let rotr = shared.by_name("rotr");
|
||||
let rotr_imm = shared.by_name("rotr_imm");
|
||||
let selectif = shared.by_name("selectif");
|
||||
let selectif_spectre_guard = shared.by_name("selectif_spectre_guard");
|
||||
let sshr = shared.by_name("sshr");
|
||||
let sshr_imm = shared.by_name("sshr_imm");
|
||||
let trueff = shared.by_name("trueff");
|
||||
@@ -1608,6 +1609,11 @@ fn define_alu(
|
||||
|
||||
// Conditional move (a.k.a integer select).
|
||||
e.enc_i32_i64(selectif, rec_cmov.opcodes(&CMOV_OVERFLOW));
|
||||
// A Spectre-guard integer select is exactly the same as a selectif, but
|
||||
// is not associated with any other legalization rules and is not
|
||||
// recognized by any optimizations, so it must arrive here unmodified
|
||||
// and in its original place.
|
||||
e.enc_i32_i64(selectif_spectre_guard, rec_cmov.opcodes(&CMOV_OVERFLOW));
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -264,5 +264,23 @@ pub(crate) fn define() -> SettingGroup {
|
||||
true,
|
||||
);
|
||||
|
||||
// Spectre options.
|
||||
|
||||
settings.add_bool(
|
||||
"enable_heap_access_spectre_mitigation",
|
||||
r#"
|
||||
Enable Spectre mitigation on heap bounds checks.
|
||||
|
||||
This is a no-op for any heap that needs no bounds checks; e.g.,
|
||||
if the limit is static and the guard region is large enough that
|
||||
the index cannot reach past it.
|
||||
|
||||
This option is enabled by default because it is highly
|
||||
recommended for secure sandboxing. The embedder should consider
|
||||
the security implications carefully before disabling this option.
|
||||
"#,
|
||||
true,
|
||||
);
|
||||
|
||||
settings.build()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user