This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH 08/22] Add Intel CET support for EH in libgcc.
- From: Jeff Law <law at redhat dot com>
- To: "Tsimbalist, Igor V" <igor dot v dot tsimbalist at intel dot com>, "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: "ian at airs dot com" <ian at airs dot com>
- Date: Mon, 30 Oct 2017 22:48:49 -0600
- Subject: Re: [PATCH 08/22] Add Intel CET support for EH in libgcc.
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=law at redhat dot com
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D8B2CC0467D5
- References: <D511F25789BA7F4EBA64C8A63891A00291F42252@IRSMSX102.ger.corp.intel.com>
On 10/12/2017 01:56 PM, Tsimbalist, Igor V wrote:
> Control-flow Enforcement Technology (CET), published by Intel, Introduces
> the Shadow Stack feature, which ensures a return from a function is done
> to exactly the same location from where the function was called. When EH
> is present the control-flow transfer may skip some stack frames and the
> shadow stack has to be adjusted not to signal a violation of a
> control-flow transfer. It's done by counting a number of skipping frames
> and adjusting shadow stack pointer by this number.
>
> gcc/
> * config/i386/i386.c (ix86_expand_epilogue): Change simple
> return to indirect jump for EH return. Change explicit 'false'
> argument in pro_epilogue_adjust_stack with a value of
> flag_cf_protection.
> * config/i386/i386.md (simple_return_indirect_internal): Remove
> SImode restriction to support 64-bit.
>
> libgcc/
> * config/i386/linux-unwind.h: Include
> config/i386/shadow-stack-unwind.h.
> * config/i386/shadow-stack-unwind.h: New file.
> * unwind-dw2.c: (uw_install_context): Add a FRAMES argument and
> pass it to _Unwind_Frames_Extra.
> * unwind-generic.h (FRAMES_P_DECL): New.
> (FRAMES_VAR): Likewise.
> (FRAMES_VAR_P): Likewise.
> (FRAMES_VAR_DECL): Likewise.
> (FRAMES_VAR_DECL_1): Likewise.
> (FRAMES_VAR_INC): Likewise.
> (FRAMES_P_UPDATE): Likewise.
> (_Unwind_Frames_Extra): Likewise.
> * unwind.inc (_Unwind_RaiseException_Phase2): Use FRAMES_P_DECL,
> FRAMES_VAR_DECL_1, FRAMES_VAR_INC and FRAMES_P_UPDATE.
> (_Unwind_RaiseException): Use FRAMES_VAR_DECL, FRAMES_VAR_P and
> FRAMES_VAR.
> (_Unwind_ForcedUnwind_Phase2): Use FRAMES_P_DECL,
> FRAMES_VAR_DECL_1, FRAMES_VAR_INC, FRAMES_P_UPDATE.
> (_Unwind_ForcedUnwind): Use FRAMES_VAR_DECL, FRAMES_VAR_P and
> FRAMES_VAR.
> (_Unwind_Resume): Use FRAMES_VAR_DECL, FRAMES_VAR_P and
> FRAMES_VAR.
> (_Unwind_Resume_or_Rethrow): Use FRAMES_VAR_DECL, FRAMES_VAR_P
> and FRAMES_VAR.
>
> Igor
>
>
>
> 0008-Add-Intel-CET-support-for-EH-in-libgcc.patch
>
>
> From 16eb1d0d9239e039fba28f1ae71762f19061b157 Mon Sep 17 00:00:00 2001
> From: Igor Tsimbalist <igor.v.tsimbalist@intel.com>
> Date: Wed, 19 Jul 2017 03:04:46 +0300
> Subject: [PATCH 08/22] Add Intel CET support for EH in libgcc.
>
> Control-flow Enforcement Technology (CET), published by Intel,
> introduces
> the Shadow Stack feature, which ensures a return from a function is done
> to exactly the same location from where the function was called. When EH
> is present the control-flow transfer may skip some stack frames and the
> shadow stack has to be adjusted not to signal a violation of a
> control-flow transfer. It's done by counting a number of skiping frames
> and adjasting shadow stack pointer by this number.
>
> Having new semantic of the 'ret' instruction if CET is supported in HW
> the 'ret' instruction cannot be generated in ix86_expand_epilogue when
> we are returning after EH is processed. Added a code in
> ix86_expand_epilogue to adjust Shadow Stack pointer and to generate an
> indirect jump instead of 'ret'. As sp register is used during this
> adjustment thus the argument in pro_epilogue_adjust_stack is changed
> to update cfa_reg based on whether control-flow instrumentation is set.
> Without updating the cfa_reg field there is an assert later in dwarf2
> pass related to mismatch the stack register and cfa_reg value.
>
> gcc/
> * config/i386/i386.c (ix86_expand_epilogue): Change simple
> return to indirect jump for EH return. Change explicit 'false'
> argument in pro_epilogue_adjust_stack with a value of
> flag_cf_protection.
> * config/i386/i386.md (simple_return_indirect_internal): Remove
> SImode restriction to support 64-bit.
>
> libgcc/
> * config/i386/linux-unwind.h: Include
> config/i386/shadow-stack-unwind.h.
> * config/i386/shadow-stack-unwind.h: New file.
> * unwind-dw2.c: (uw_install_context): Add a FRAMES argument and
> pass it to _Unwind_Frames_Extra.
> * unwind-generic.h (FRAMES_P_DECL): New.
> (FRAMES_VAR): Likewise.
> (FRAMES_VAR_P): Likewise.
> (FRAMES_VAR_DECL): Likewise.
> (FRAMES_VAR_DECL_1): Likewise.
> (FRAMES_VAR_INC): Likewise.
> (FRAMES_P_UPDATE): Likewise.
> (_Unwind_Frames_Extra): Likewise.
> * unwind.inc (_Unwind_RaiseException_Phase2): Use FRAMES_P_DECL,
> FRAMES_VAR_DECL_1, FRAMES_VAR_INC and FRAMES_P_UPDATE.
> (_Unwind_RaiseException): Use FRAMES_VAR_DECL, FRAMES_VAR_P and
> FRAMES_VAR.
> (_Unwind_ForcedUnwind_Phase2): Use FRAMES_P_DECL,
> FRAMES_VAR_DECL_1, FRAMES_VAR_INC, FRAMES_P_UPDATE.
> (_Unwind_ForcedUnwind): Use FRAMES_VAR_DECL, FRAMES_VAR_P and
> FRAMES_VAR.
> (_Unwind_Resume): Use FRAMES_VAR_DECL, FRAMES_VAR_P and
> FRAMES_VAR.
> (_Unwind_Resume_or_Rethrow): Use FRAMES_VAR_DECL, FRAMES_VAR_P
> and FRAMES_VAR.
>
>
> diff --git a/libgcc/config/i386/shadow-stack-unwind.h b/libgcc/config/i386/shadow-stack-unwind.h
> new file mode 100644
> index 0000000..c5d0d56
> --- /dev/null
> +++ b/libgcc/config/i386/shadow-stack-unwind.h
> @@ -0,0 +1,66 @@
> +/* _Unwind_Frames_Extra with shadow stack for x86-64 and x86.
> + Copyright (C) 2017 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation; either version 3, or (at your option)
> +any later version.
> +
> +GCC is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +GNU General Public License for more details.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
> +<http://www.gnu.org/licenses/>. */
> +
> +#ifdef __x86_64__
> +# define incssp(x) __builtin_ia32_incsspq ((x))
> +# define rdssp(x) __builtin_ia32_rdsspq (x)
> +#else
> +# define incssp(x) __builtin_ia32_incsspd ((x))
> +# define rdssp(x) __builtin_ia32_rdsspd (x)
> +#endif
> +
> +/* Unwind the shadow stack for EH. */
> +#undef _Unwind_Frames_Extra
> +#define _Unwind_Frames_Extra(x) \
> + do \
> + { \
> + unsigned long ssp = 0; \
> + ssp = rdssp (ssp); \
> + if (ssp != 0) \
> + { \
> + unsigned long tmp = (x); \
> + while (tmp > 255) \
> + { \
> + incssp (tmp); \
> + tmp -= 255; \
> + } \
> + incssp (tmp); \
> + } \
> + } \
> + while (0)
> +
> +#undef FRAMES_P_DECL
> +#undef FRAMES_VAR
> +#undef FRAMES_VAR_P
> +#undef FRAMES_VAR_DECL
> +#undef FRAMES_VAR_DECL_1
> +#undef FRAMES_VAR_INC
> +#undef FRAMES_P_UPDATE
> +#define FRAMES_P_DECL , unsigned long *frames_p
> +#define FRAMES_VAR frames
> +#define FRAMES_VAR_P , &frames
> +#define FRAMES_VAR_DECL unsigned long frames
> +#define FRAMES_VAR_DECL_1 unsigned long frames = 1
> +#define FRAMES_VAR_INC frames++
> +#define FRAMES_P_UPDATE *frames_p = frames
> diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
> index 3f26eaf..7e9d26b 100644
> --- a/libgcc/unwind-dw2.c
> +++ b/libgcc/unwind-dw2.c
> @@ -1646,12 +1646,13 @@ uw_frob_return_addr (struct _Unwind_Context *current
> macro because __builtin_eh_return must be invoked in the context of
> our caller. */
>
> -#define uw_install_context(CURRENT, TARGET) \
> +#define uw_install_context(CURRENT, TARGET, FRAMES) \
Comment likely needs updating to describe the new parameter.
I must say that I'm not happy with all the macro games we're playing in
this patch. Is there no cleaner way to get the desired behavior?
Are there any ABI/API implications of this patch? Ie, does the
signature of any exported function change?
Has this been tested anywhere other than x86/x86_64 linux?
Jeff