Merge pull request #1930 from cfallin/spectre-heap

Spectre mitigation on heap access overflow checks.
This commit is contained in:
Chris Fallin
2020-07-01 09:23:04 -07:00
committed by GitHub
9 changed files with 148 additions and 47 deletions

View File

@@ -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)]

View File

@@ -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(

View File

@@ -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()
}