On 8/29/18 3:51 AM, Thomas Preudhomme wrote:
> Resend hopefully without HTML this time.
> 
> On Wed, 29 Aug 2018 at 10:49, Thomas Preudhomme
> <thomas.preudho...@linaro.org> wrote:
>> Hi,
>>
>> I've reworked the patch fixing PR85434 (spilling of stack protector guard's 
>> address on ARM) to address the testsuite regression on powerpc and x86 as 
>> well as glibc testsuite regression on ARM. Issues were due to 
>> unconditionally attempting to generate the new patterns. The code now tests 
>> if there is a pattern for them for the target before generating them. In the 
>> ARM side of the patch, I've also added a more specific predicate for the new 
>> patterns. The new patch is found below.
>>
>>
>> In case of high register pressure in PIC mode, address of the stack
>> protector's guard can be spilled on ARM targets as shown in PR85434,
>> thus allowing an attacker to control what the canary would be compared
>> against. ARM does lack stack_protect_set and stack_protect_test insn
>> patterns, defining them does not help as the address is expanded
>> regularly and the patterns only deal with the copy and test of the
>> guard with the canary.
>>
>> This problem does not occur for x86 targets because the PIC access and
>> the test can be done in the same instruction. Aarch64 is exempt too
>> because PIC access insn pattern are mov of UNSPEC which prevents it from
>> the second access in the epilogue being CSEd in cse_local pass with the
>> first access in the prologue.
>>
>> The approach followed here is to create new "combined" set and test
>> standard pattern names that take the unexpanded guard and do the set or
>> test. This allows the target to use an opaque pattern (eg. using UNSPEC)
>> to hide the individual instructions being generated to the compiler and
>> split the pattern into generic load, compare and branch instruction
>> after register allocator, therefore avoiding any spilling. This is here
>> implemented for the ARM targets. For targets not implementing these new
>> standard pattern names, the existing stack_protect_set and
>> stack_protect_test pattern names are used.
>>
>> To be able to split PIC access after register allocation, the functions
>> had to be augmented to force a new PIC register load and to control
>> which register it loads into. This is because sharing the PIC register
>> between prologue and epilogue could lead to spilling due to CSE again
>> which an attacker could use to control what the canary gets compared
>> against.
>>
>> ChangeLog entries are as follows:
>>
>> *** gcc/ChangeLog ***
>>
>> 2018-08-09  Thomas Preud'homme  <thomas.preudho...@linaro.org>
>>
>>     * target-insns.def (stack_protect_combined_set): Define new standard
>>     pattern name.
>>     (stack_protect_combined_test): Likewise.
>>     * cfgexpand.c (stack_protect_prologue): Try new
>>     stack_protect_combined_set pattern first.
>>     * function.c (stack_protect_epilogue): Try new
>>     stack_protect_combined_test pattern first.
>>     * config/arm/arm.c (require_pic_register): Add pic_reg and compute_now
>>     parameters to control which register to use as PIC register and force
>>     reloading PIC register respectively.  Insert in the stream of insns if
>>     possible.
>>     (legitimize_pic_address): Expose above new parameters in prototype and
>>     adapt recursive calls accordingly.
>>     (arm_legitimize_address): Adapt to new legitimize_pic_address
>>     prototype.
>>     (thumb_legitimize_address): Likewise.
>>     (arm_emit_call_insn): Adapt to new require_pic_register prototype.
>>     * config/arm/arm-protos.h (legitimize_pic_address): Adapt to prototype
>>     change.
>>     * config/arm/predicated.md (guard_operand): New predicate.
>>     * config/arm/arm.md (movsi expander): Adapt to legitimize_pic_address
>>     prototype change.
>>     (stack_protect_combined_set): New insn_and_split pattern.
>>     (stack_protect_set): New insn pattern.
>>     (stack_protect_combined_test): New insn_and_split pattern.
>>     (stack_protect_test): New insn pattern.
>>     * config/arm/unspecs.md (UNSPEC_SP_SET): New unspec.
>>     (UNSPEC_SP_TEST): Likewise.
>>     * doc/md.texi (stack_protect_combined_set): Document new standard
>>     pattern name.
>>     (stack_protect_set): Clarify that the operand for guard's address is
>>     legal.
>>     (stack_protect_combined_test): Document new standard pattern name.
>>     (stack_protect_test): Clarify that the operand for guard's address is
>>     legal.
>>
>> *** gcc/testsuite/ChangeLog ***
>>
>> 2018-07-05  Thomas Preud'homme  <thomas.preudho...@linaro.org>
>>
>>     * gcc.target/arm/pr85434.c: New test.
>>
>>
>> Testing:
>>
>> native x86_64: bootstrap + testsuite -> no regression, can see failures with 
>> previous version of patch but not with new version
>> native powerpc64: bootstrap + testsuite -> no regression, can see failures 
>> from pr86834 with previous version of patch but not with new version
>> cross ARM Linux: build + testsuite -> no regression
>> native ARM Thumb-2: bootstrap + testsuite + glibc build + glibc test -> no 
>> regression
>> native ARM Arm: bootstrap + testsuite + glibc build + glibc test -> no 
>> regression
>> Aarch64: bootstrap + testsuite + glibc build + glibc test-> no regression
>>
>> Is this ok for trunk?
>>
>> Best regards,
>>
>> Thomas
> 
> fix_pr85434_prevent_spilling_stack_protector_guard_address.patch
> 
> From 922cc5d7054bc598732e4ad6d408c7e4297c519a Mon Sep 17 00:00:00 2001
> From: Thomas Preud'homme <thomas.preudho...@linaro.org>
> Date: Tue, 8 May 2018 15:47:05 +0100
> Subject: [PATCH] PR85434: Prevent spilling of stack protector guard's address
>  on ARM
> 
> In case of high register pressure in PIC mode, address of the stack
> protector's guard can be spilled on ARM targets as shown in PR85434,
> thus allowing an attacker to control what the canary would be compared
> against. ARM does lack stack_protect_set and stack_protect_test insn
> patterns, defining them does not help as the address is expanded
> regularly and the patterns only deal with the copy and test of the
> guard with the canary.
> 
> This problem does not occur for x86 targets because the PIC access and
> the test can be done in the same instruction. Aarch64 is exempt too
> because PIC access insn pattern are mov of UNSPEC which prevents it from
> the second access in the epilogue being CSEd in cse_local pass with the
> first access in the prologue.
> 
> The approach followed here is to create new "combined" set and test
> standard pattern names that take the unexpanded guard and do the set or
> test. This allows the target to use an opaque pattern (eg. using UNSPEC)
> to hide the individual instructions being generated to the compiler and
> split the pattern into generic load, compare and branch instruction
> after register allocator, therefore avoiding any spilling. This is here
> implemented for the ARM targets. For targets not implementing these new
> standard pattern names, the existing stack_protect_set and
> stack_protect_test pattern names are used.
> 
> To be able to split PIC access after register allocation, the functions
> had to be augmented to force a new PIC register load and to control
> which register it loads into. This is because sharing the PIC register
> between prologue and epilogue could lead to spilling due to CSE again
> which an attacker could use to control what the canary gets compared
> against.
> 
> ChangeLog entries are as follows:
> 
> *** gcc/ChangeLog ***
> 
> 2018-08-09  Thomas Preud'homme  <thomas.preudho...@linaro.org>
> 
>       * target-insns.def (stack_protect_combined_set): Define new standard
>       pattern name.
>       (stack_protect_combined_test): Likewise.
>       * cfgexpand.c (stack_protect_prologue): Try new
>       stack_protect_combined_set pattern first.
>       * function.c (stack_protect_epilogue): Try new
>       stack_protect_combined_test pattern first.
>       * config/arm/arm.c (require_pic_register): Add pic_reg and compute_now
>       parameters to control which register to use as PIC register and force
>       reloading PIC register respectively.  Insert in the stream of insns if
>       possible.
>       (legitimize_pic_address): Expose above new parameters in prototype and
>       adapt recursive calls accordingly.
>       (arm_legitimize_address): Adapt to new legitimize_pic_address
>       prototype.
>       (thumb_legitimize_address): Likewise.
>       (arm_emit_call_insn): Adapt to new require_pic_register prototype.
>       * config/arm/arm-protos.h (legitimize_pic_address): Adapt to prototype
>       change.
>       * config/arm/predicated.md (guard_operand): New predicate.
>       * config/arm/arm.md (movsi expander): Adapt to legitimize_pic_address
>       prototype change.
>       (stack_protect_combined_set): New insn_and_split pattern.
>       (stack_protect_set): New insn pattern.
>       (stack_protect_combined_test): New insn_and_split pattern.
>       (stack_protect_test): New insn pattern.
>       * config/arm/unspecs.md (UNSPEC_SP_SET): New unspec.
>       (UNSPEC_SP_TEST): Likewise.
>       * doc/md.texi (stack_protect_combined_set): Document new standard
>       pattern name.
>       (stack_protect_set): Clarify that the operand for guard's address is
>       legal.
>       (stack_protect_combined_test): Document new standard pattern name.
>       (stack_protect_test): Clarify that the operand for guard's address is
>       legal.
> 
> *** gcc/testsuite/ChangeLog ***
> 
> 2018-07-05  Thomas Preud'homme  <thomas.preudho...@linaro.org>
> 
>       * gcc.target/arm/pr85434.c: New test.
> 
> Testing: Bootstrapped on ARM in both Arm and Thumb-2 mode as well as on
> Aarch64. Testsuite shows no regression on these 3 variants either both
> with default flags and with -fstack-protector-all.
> 
> Is this ok for trunk? If yes, would this be acceptable as a backport to
> GCC 6, 7 and 8 provided that no regression is found?
> 
> Best regards,
> 
> Thomas
> 
> Change-Id: I993343e3063fb570af706624e08b475732a5ec57
> ---
>  gcc/cfgexpand.c                        |  17 +++
>  gcc/config/arm/arm-protos.h            |   2 +-
>  gcc/config/arm/arm.c                   |  56 +++++--
>  gcc/config/arm/arm.md                  |  94 +++++++++++-
>  gcc/config/arm/predicates.md           |  10 ++
>  gcc/config/arm/unspecs.md              |   3 +
>  gcc/doc/md.texi                        |  55 ++++++-
>  gcc/function.c                         |  32 +++-
>  gcc/target-insns.def                   |   2 +
>  gcc/testsuite/gcc.target/arm/pr85434.c | 200 +++++++++++++++++++++++++
>  10 files changed, 438 insertions(+), 33 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/arm/pr85434.c
I think the target independent bits here are still fine.


Jeff

Reply via email to