This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [1/5][AArch64] Return address protection on AArch64
- From: "Richard Earnshaw (lists)" <Richard dot Earnshaw at arm dot com>
- To: Jiong Wang <jiong dot wang at foss dot arm dot com>, Andrew Pinski <pinskia at gmail dot com>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>, James Greenhalgh <james dot greenhalgh at arm dot com>
- Date: Fri, 20 Jan 2017 16:22:52 +0000
- Subject: Re: [1/5][AArch64] Return address protection on AArch64
- Authentication-results: sourceware.org; auth=none
- References: <c9da17a6-c3de-4466-c023-4e4ddbe38efb@foss.arm.com> <4cf21d03-0a88-c6fa-df37-59ec4edf1d89@foss.arm.com> <ac547390-abfc-3d6a-f10b-dbb9e4bad5b2@foss.arm.com> <ae7c1f2a-06e4-55d1-d3be-e43ae7ec76df@foss.arm.com> <6f8e65e0-643d-d0b0-26ad-4a20c3daf421@foss.arm.com> <f38fbbb0-067b-d996-46aa-1ce9c3dd2d75@foss.arm.com> <CA+=Sn1kW-Ne8zd3Q4UtE-oy6ewi3zENY1oEDOPb2N1A4R56gwg@mail.gmail.com> <e4d3aa42-331e-48ce-161c-40f9ef5489d5@foss.arm.com> <b6ab7ee6-7b77-0a12-e0be-39faee8fa388@foss.arm.com>
On 20/01/17 12:36, Jiong Wang wrote:
>
>
> On 20/01/17 11:15, Jiong Wang wrote:
>>
>>
>> On 20/01/17 03:39, Andrew Pinski wrote:
>>> On Fri, Jan 6, 2017 at 3:47 AM, Jiong Wang <jiong.wang@foss.arm.com>
>>> wrote:
>>>> On 11/11/16 18:22, Jiong Wang wrote:
>>>>> As described in the cover letter, this patch implements return address
>>>>> signing
>>>>> for AArch64, it's controlled by the new option:
>>>>>
>>>>> -msign-return-address=[none | non-leaf | all]
>>>>>
>>>>> "none" means don't do return address signing at all on any function.
>>>>> "non-leaf"
>>>>> means only sign non-leaf function. "all" means sign all functions.
>>>>> Return
>>>>> address signing is currently disabled on ILP32. I haven't tested it.
>>>>>
>>>>> The instructions added in the architecture are of 2 kinds.
>>>>>
>>>>> * In the NOP instruction space, which allows binaries to run
>>>>> without any
>>>>> traps
>>>>> on older versions of the architecture. This doesn't give any
>>>>> additional
>>>>> protection on older hardware but allows for the same binary to be
>>>>> used on
>>>>> earlier versions of the architecture and newer versions of the
>>>>> architecture.
>>>>>
>>>>> * New instructions that are only valid for v8.3 and will trap if
>>>>> used on
>>>>> earlier
>>>>> versions of the architecture.
>>>>>
>>>>> At default, once return address signing is enabled, it will only
>>>>> generates
>>>>> NOP
>>>>> instruction.
>>>>>
>>>>> While if -march=armv8.3-a specified, GCC will try to use the most
>>>>> efficient
>>>>> pointer authentication instruction as it can.
>>>>>
>>>>> The architecture has 2 user invisible system keys for signing and
>>>>> creating
>>>>> signed addresses as part of these instructions. For some use case, the
>>>>> user
>>>>> might want to use difference key for different functions. The new
>>>>> option
>>>>> "-msign-return-address-key=key_name" let GCC select the key used for
>>>>> return
>>>>> address signing. Permissible values are "a_key" for A key and
>>>>> "b_key" for
>>>>> B
>>>>> key, and this option are supported by function target attribute and
>>>>> LTO
>>>>> will
>>>>> hopefully just work.
>>>>>
>>>>>
>>>>>
>>>>> gcc/
>>>>> 2016-11-09 Jiong Wang<jiong.wang@arm.com>
>>>>>
>>>>> * config/aarch64/aarch64-opts.h
>>>>> (aarch64_pauth_key_index): New
>>>>> enum.
>>>>> (aarch64_function_type): New enum.
>>>>> * config/aarch64/aarch64-protos.h
>>>>> (aarch64_output_sign_auth_reg):
>>>>> New
>>>>> declaration.
>>>>> * config/aarch64/aarch64.c (aarch64_expand_prologue):
>>>>> Sign return
>>>>> address before it's pushed onto stack.
>>>>> (aarch64_expand_epilogue): Authenticate return address
>>>>> fetched
>>>>> from
>>>>> stack.
>>>>> (aarch64_output_sign_auth_reg): New function.
>>>>> (aarch64_override_options): Sanity check for ILP32 and
>>>>> ISA level.
>>>>> (aarch64_attributes): New function attributes for
>>>>> "sign-return-address",
>>>>> "pauth-key".
>>>>> * config/aarch64/aarch64.md (UNSPEC_AUTH_REG,
>>>>> UNSPEC_AUTH_REG1716,
>>>>> UNSPEC_SIGN_REG, UNSPEC_SIGN_REG1716, UNSPEC_STRIP_REG_SIGN,
>>>>> UNSPEC_STRIP_X30_SIGN): New unspecs.
>>>>> ("*do_return"): Generate combined instructions according
>>>>> to key
>>>>> index.
>>>>> ("sign_reg", "sign_reg1716", "auth_reg", "auth_reg1716",
>>>>> "strip_reg_sign", "strip_lr_sign"): New.
>>>>> * config/aarch64/aarch64.opt (msign-return-address,
>>>>> mpauth-key):
>>>>> New.
>>>>> * config/aarch64/predicates.md (aarch64_const0_const1): New
>>>>> predicate.
>>>>> * doc/extend.texi (AArch64 Function Attributes): Documents
>>>>> "sign-return-address=", "pauth-key".
>>>>> * doc/invoke.texi (AArch64 Options): Documents
>>>>> "-msign-return-address=",
>>>>> "-pauth-key".
>>>>>
>>>>> gcc/testsuite/
>>>>> 2016-11-09 Jiong Wang<jiong.wang@arm.com>
>>>>>
>>>>> * gcc.target/aarch64/return_address_sign_1.c: New testcase.
>>>>> * gcc.target/aarch64/return_address_sign_scope_1.c: New
>>>>> testcase.
>>>>
>>>> Update the patchset according to new DWARF proposal described at
>>>>
>>>> https://gcc.gnu.org/ml/gcc-patches/2016-11/msg03010.html
>>> One of these patches of this patch set break ILP32 building for
>>> aarch64-elf and most likely also aarch64-linux-gnu.
>>>
>>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:
>>>
>>> In function â??uw_init_context_1â??:
>>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/libgcc/unwind-dw2.c:1567:6:
>>>
>>> internal compiler error: in emit_move_insn, at expr.c:3698
>>> ra = MD_POST_EXTRACT_ROOT_ADDR (ra);
>>> 0x8270cf emit_move_insn(rtx_def*, rtx_def*)
>>> /home/jenkins/workspace/BuildToolchainAARCH64_thunder_elf_upstream/toolchain/scripts/../src/gcc/expr.c:3697
>>>
>>> 0x80867b force_reg(machine_mode, rtx_def*)
>> Must be the Pmode issue under ILP32, I am testing a fix (I don't have
>> full ILP32 environment, so can only test simply by force libgcc build
>> with -mabi=ilp32)
>
> Here is the patch.
>
> For XPACLRI builtin which drops the signature in a pointer, it's
> prototype is "void *foo (void *)"
> FOR PAC/AUT builtin which sign or authenticate a pointer, it's prototype
> is "void *foo (void *, uint64)".
>
> This patch adjusted those modes to make sure they strictly follow the C
> prototype. I also borrow the type define in ARM backend
>
> typedef unsigned _uw64 __attribute__((mode(__DI__)));
>
> And this is need to type cast the salt value which is always DImode.
>
> It passed my local ILP32 cross build.
>
> OK for trunk?
>
> gcc/
> 2017-01-20 Jiong Wang <jiong.wang@arm.com>
> * config/aarch64/aarch64-builtins.c (aarch64_expand_builtin):
> Fix modes
> for AARCH64_PAUTH_BUILTIN_XPACLRI,
> AARCH64_PAUTH_BUILTIN_PACIA1716 and
> AARCH64_PAUTH_BUILTIN_AUTIA1716.
>
> libgcc/
> * config/aarch64/aarch64-unwind.h (_uw64): New typedef.
> (aarch64_post_extract_frame_addr): Cast salt to _uw64.
> (aarch64_post_frob_eh_handler_addr): Likewise.
>
>
Hmm, we currently don't support ILP32 at all for pointer signing (sorry
("Return address signing is only supported for -mabi=lp64");), so I
wonder if it would be better for now to simply suppress all the new
hooks in aarch64-unwind.h ifdef __ILP32__.
R.
> k.patch
>
>
> diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
> index 6c6530c..7ef351e 100644
> --- a/gcc/config/aarch64/aarch64-builtins.c
> +++ b/gcc/config/aarch64/aarch64-builtins.c
> @@ -1333,18 +1333,20 @@ aarch64_expand_builtin (tree exp,
> case AARCH64_PAUTH_BUILTIN_PACIA1716:
> case AARCH64_PAUTH_BUILTIN_XPACLRI:
> arg0 = CALL_EXPR_ARG (exp, 0);
> - op0 = force_reg (Pmode, expand_normal (arg0));
> + /* Operand0 should have ptr_mode as its a ptr_type_node, this makes both
> + LP64 and ILP32 expand correctly. */
> + op0 = force_reg (ptr_mode, expand_normal (arg0));
>
> if (!target)
> - target = gen_reg_rtx (Pmode);
> + target = gen_reg_rtx (ptr_mode);
> else
> - target = force_reg (Pmode, target);
> + target = force_reg (ptr_mode, target);
>
> emit_move_insn (target, op0);
>
> if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
> {
> - rtx lr = gen_rtx_REG (Pmode, R30_REGNUM);
> + rtx lr = gen_rtx_REG (ptr_mode, R30_REGNUM);
> icode = CODE_FOR_xpaclri;
> emit_move_insn (lr, op0);
> emit_insn (GEN_FCN (icode) ());
> @@ -1353,12 +1355,13 @@ aarch64_expand_builtin (tree exp,
> else
> {
> tree arg1 = CALL_EXPR_ARG (exp, 1);
> - rtx op1 = force_reg (Pmode, expand_normal (arg1));
> + /* Operand1 for either PAC or AUT is a unsigned_intDI_type_node. */
> + rtx op1 = force_reg (DImode, expand_normal (arg1));
> icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
> ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
>
> - rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
> - rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
> + rtx x16_reg = gen_rtx_REG (DImode, R16_REGNUM);
> + rtx x17_reg = gen_rtx_REG (ptr_mode, R17_REGNUM);
> emit_move_insn (x17_reg, op0);
> emit_move_insn (x16_reg, op1);
> emit_insn (GEN_FCN (icode) ());
> diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h
> index a43d965..7dd2549 100644
> --- a/libgcc/config/aarch64/aarch64-unwind.h
> +++ b/libgcc/config/aarch64/aarch64-unwind.h
> @@ -35,6 +35,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
> #define MD_FROB_UPDATE_CONTEXT(context, fs) \
> aarch64_frob_update_context (context, fs)
>
> +typedef unsigned _uw64 __attribute__((mode(__DI__)));
> +
> /* Do AArch64 private extraction on ADDR based on context info CONTEXT and
> unwind frame info FS. If ADDR is signed, we do address authentication on it
> using CFA of current frame. */
> @@ -45,7 +47,7 @@ aarch64_post_extract_frame_addr (struct _Unwind_Context *context,
> {
> if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1)
> {
> - _Unwind_Word salt = (_Unwind_Word) context->cfa;
> + _uw64 salt = (_uw64) context->cfa;
> return __builtin_aarch64_autia1716 (addr, salt);
> }
> else
> @@ -64,7 +66,7 @@ aarch64_post_frob_eh_handler_addr (struct _Unwind_Context *current,
> {
> if (current->flags & RA_A_SIGNED_BIT)
> return __builtin_aarch64_pacia1716 (handler_addr,
> - (_Unwind_Word) current->cfa);
> + (_uw64) current->cfa);
> else
> return handler_addr;
> }
>