mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
367c12aaf8
Some processors may speculatively execute the instructions immediately following RET (returns) and BR (indirect jumps), even though control flow should change unconditionally at these instructions. To avoid a potential miss-speculatively executed gadget after these instructions leaking secrets through side channels, this pass places a speculation barrier immediately after every RET and BR instruction. Since these barriers are never on the correct, architectural execution path, performance overhead of this is expected to be low. On targets that implement that Armv8.0-SB Speculation Barrier extension, a single SB instruction is emitted that acts as a speculation barrier. On other targets, a DSB SYS followed by a ISB is emitted to act as a speculation barrier. These speculation barriers are implemented as pseudo instructions to avoid later passes to analyze them and potentially remove them. Even though currently LLVM does not produce BRAA/BRAB/BRAAZ/BRABZ instructions, these are also mitigated by the pass and tested through a MIR test. The mitigation is off by default and can be enabled by the harden-sls-retbr subtarget feature. Differential Revision: https://reviews.llvm.org/D81400
151 lines
4.3 KiB
YAML
151 lines
4.3 KiB
YAML
# RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu \
|
|
# RUN: -start-before aarch64-sls-hardening -o - %s \
|
|
# RUN: -mattr=harden-sls-retbr \
|
|
# RUN: | FileCheck %s --check-prefixes=CHECK,ISBDSB
|
|
# RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu \
|
|
# RUN: -start-before aarch64-sls-hardening -o - %s \
|
|
# RUN: -mattr=harden-sls-retbr -mattr=+sb \
|
|
# RUN: | FileCheck %s --check-prefixes=CHECK,SB
|
|
|
|
# Check that the SLS hardening pass also protects BRA* indirect branches that
|
|
# llvm currently does not generate.
|
|
--- |
|
|
@ptr_aa = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@br_aa, %return), i8* blockaddress(@br_aa, %l2)], align 8
|
|
@ptr_aaz = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@br_aaz, %return), i8* blockaddress(@br_aaz, %l2)], align 8
|
|
@ptr_ab = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@br_ab, %return), i8* blockaddress(@br_ab, %l2)], align 8
|
|
@ptr_abz = private unnamed_addr constant [2 x i8*] [i8* blockaddress(@br_abz, %return), i8* blockaddress(@br_abz, %l2)], align 8
|
|
|
|
define dso_local i32 @br_aa(i32 %a, i32 %b, i32 %i) {
|
|
entry:
|
|
br label %l2
|
|
l2:
|
|
br label %return
|
|
return:
|
|
ret i32 undef
|
|
}
|
|
define dso_local i32 @br_aaz(i32 %a, i32 %b, i32 %i) {
|
|
entry:
|
|
br label %l2
|
|
l2:
|
|
br label %return
|
|
return:
|
|
ret i32 undef
|
|
}
|
|
define dso_local i32 @br_ab(i32 %a, i32 %b, i32 %i) {
|
|
entry:
|
|
br label %l2
|
|
l2:
|
|
br label %return
|
|
return:
|
|
ret i32 undef
|
|
}
|
|
define dso_local i32 @br_abz(i32 %a, i32 %b, i32 %i) {
|
|
entry:
|
|
br label %l2
|
|
l2:
|
|
br label %return
|
|
return:
|
|
ret i32 undef
|
|
}
|
|
...
|
|
---
|
|
name: br_aa
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: br_aa:
|
|
bb.0.entry:
|
|
successors: %bb.2, %bb.1
|
|
liveins: $w2
|
|
$x8 = ADRP target-flags(aarch64-page) @ptr_aa
|
|
renamable $x8 = ADDXri $x8, target-flags(aarch64-pageoff, aarch64-nc) @ptr_aa, 0
|
|
renamable $x8 = LDRXroW killed renamable $x8, killed renamable $w2, 1, 1
|
|
BRAA killed renamable $x8, $sp
|
|
; CHECK: braa x8, sp
|
|
; ISBDSB-NEXT: dsb sy
|
|
; ISBDSB-NEXT: isb
|
|
; SB-NEXT: {{ sb$}}
|
|
|
|
bb.1.l2 (address-taken):
|
|
renamable $w0 = MOVZWi 1, 0
|
|
RET undef $lr, implicit $w0
|
|
|
|
bb.2.return (address-taken):
|
|
$w0 = ORRWrs $wzr, $wzr, 0
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: br_aaz
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: br_aaz:
|
|
bb.0.entry:
|
|
successors: %bb.2, %bb.1
|
|
liveins: $w2
|
|
$x8 = ADRP target-flags(aarch64-page) @ptr_aaz
|
|
renamable $x8 = ADDXri $x8, target-flags(aarch64-pageoff, aarch64-nc) @ptr_aaz, 0
|
|
renamable $x8 = LDRXroW killed renamable $x8, killed renamable $w2, 1, 1
|
|
BRAAZ killed renamable $x8
|
|
; CHECK: braaz x8
|
|
; ISBDSB-NEXT: dsb sy
|
|
; ISBDSB-NEXT: isb
|
|
; SB-NEXT: {{ sb$}}
|
|
|
|
bb.1.l2 (address-taken):
|
|
renamable $w0 = MOVZWi 1, 0
|
|
RET undef $lr, implicit $w0
|
|
|
|
bb.2.return (address-taken):
|
|
$w0 = ORRWrs $wzr, $wzr, 0
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: br_ab
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: br_ab:
|
|
bb.0.entry:
|
|
successors: %bb.2, %bb.1
|
|
liveins: $w2
|
|
$x8 = ADRP target-flags(aarch64-page) @ptr_ab
|
|
renamable $x8 = ADDXri $x8, target-flags(aarch64-pageoff, aarch64-nc) @ptr_ab, 0
|
|
renamable $x8 = LDRXroW killed renamable $x8, killed renamable $w2, 1, 1
|
|
BRAA killed renamable $x8, $sp
|
|
; CHECK: braa x8, sp
|
|
; ISBDSB-NEXT: dsb sy
|
|
; ISBDSB-NEXT: isb
|
|
; SB-NEXT: {{ sb$}}
|
|
|
|
bb.1.l2 (address-taken):
|
|
renamable $w0 = MOVZWi 1, 0
|
|
RET undef $lr, implicit $w0
|
|
|
|
bb.2.return (address-taken):
|
|
$w0 = ORRWrs $wzr, $wzr, 0
|
|
RET undef $lr, implicit $w0
|
|
...
|
|
---
|
|
name: br_abz
|
|
tracksRegLiveness: true
|
|
body: |
|
|
; CHECK-LABEL: br_abz:
|
|
bb.0.entry:
|
|
successors: %bb.2, %bb.1
|
|
liveins: $w2
|
|
$x8 = ADRP target-flags(aarch64-page) @ptr_abz
|
|
renamable $x8 = ADDXri $x8, target-flags(aarch64-pageoff, aarch64-nc) @ptr_abz, 0
|
|
renamable $x8 = LDRXroW killed renamable $x8, killed renamable $w2, 1, 1
|
|
BRAAZ killed renamable $x8
|
|
; CHECK: braaz x8
|
|
; ISBDSB-NEXT: dsb sy
|
|
; ISBDSB-NEXT: isb
|
|
; SB-NEXT: {{ sb$}}
|
|
|
|
bb.1.l2 (address-taken):
|
|
renamable $w0 = MOVZWi 1, 0
|
|
RET undef $lr, implicit $w0
|
|
|
|
bb.2.return (address-taken):
|
|
$w0 = ORRWrs $wzr, $wzr, 0
|
|
RET undef $lr, implicit $w0
|
|
...
|