aarch64: Prevent canary address being spilled to stack
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 23 Sep 2020 18:25:04 +0000 (19:25 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 23 Sep 2020 18:25:04 +0000 (19:25 +0100)
commit74b27d8eedc7a4c0e8276345107790e6b3c023cb
tree9814ab980a925298f38feb3d81dd3528ad870f14
parent0f0b00033a71ff728d6fab6f9d674fb6b3ba4980
aarch64: Prevent canary address being spilled to stack

This patch fixes the equivalent of arm bug PR85434/CVE-2018-12886
for aarch64: under high register pressure, the -fstack-protector
code might spill the address of the canary onto the stack and
reload it at the test site, giving an attacker the opportunity
to change the expected canary value.

This would happen in two cases:

- when generating PIC for -mstack-protector-guard=global
  (tested by stack-protector-6.c).  This is a direct analogue
  of PR85434, which was also about PIC for the global case.

- when using -mstack-protector-guard=sysreg.

The two problems were really separate bugs and caused by separate code,
but it was more convenient to fix them together.

The post-patch code still spills _GLOBAL_OFFSET_TABLE_ for
stack-protector-6.c, which is a more general problem.  However,
it no longer spills the canary address itself.

The patch also fixes an ICE when using -mstack-protector-guard=sysreg
with ILP32: even if the register read is SImode, the address
calculation itself should still be DImode.

gcc/
* config/aarch64/aarch64-protos.h (aarch64_salt_type): New enum.
(aarch64_stack_protect_canary_mem): Declare.
* config/aarch64/aarch64.md (UNSPEC_SALT_ADDR): New unspec.
(stack_protect_set): Forward to stack_protect_combined_set.
(stack_protect_combined_set): New pattern.  Use
aarch64_stack_protect_canary_mem.
(reg_stack_protect_address_<mode>): Add a salt operand.
(stack_protect_test): Forward to stack_protect_combined_test.
(stack_protect_combined_test): New pattern.  Use
aarch64_stack_protect_canary_mem.
* config/aarch64/aarch64.c (strip_salt): New function.
(strip_offset_and_salt): Likewise.
(tls_symbolic_operand_type): Use strip_offset_and_salt.
(aarch64_stack_protect_canary_mem): New function.
(aarch64_cannot_force_const_mem): Use strip_offset_and_salt.
(aarch64_classify_address): Likewise.
(aarch64_symbolic_address_p): Likewise.
(aarch64_print_operand): Likewise.
(aarch64_output_addr_const_extra): New function.
(aarch64_tls_symbol_p): Use strip_salt.
(aarch64_classify_symbol): Likewise.
(aarch64_legitimate_pic_operand_p): Use strip_offset_and_salt.
(aarch64_legitimate_constant_p): Likewise.
(aarch64_mov_operand_p): Use strip_salt.
(TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Override.

gcc/testsuite/
* gcc.target/aarch64/stack-protector-5.c: New test.
* gcc.target/aarch64/stack-protector-6.c: Likewise.
* gcc.target/aarch64/stack-protector-7.c: Likewise.
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.target/aarch64/stack-protector-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/stack-protector-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/stack-protector-7.c [new file with mode: 0644]