public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/vendors/ARM/heads/arm-12-m-pacbti)] [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime
@ 2022-08-12 16:30 Andrea Corallo
  0 siblings, 0 replies; 2+ messages in thread
From: Andrea Corallo @ 2022-08-12 16:30 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:ed73a4c530966fdde43e98572c6cda31574bcf37

commit ed73a4c530966fdde43e98572c6cda31574bcf37
Author: Andrea Corallo <andrea.corallo@arm.com>
Date:   Mon Dec 6 11:42:11 2021 +0100

    [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime
    
    This patch adds authentication for when the stack is unwound when an
    exception is taken.  All the changes here are done to the runtime code
    in libgcc's unwinder code for Arm target. All the changes are guarded
    under defined (__ARM_FEATURE_PAC_DEFAULT) and activated only if the
    +pacbti feature is switched on for the architecture. This means that
    switching on the target feature via -march or -mcpu is sufficient and
    -mbranch-protection need not be enabled. This ensures that the
    unwinder is authenticated only if the PACBTI instructions are
    available in the non-NOP space as it uses AUTG.  Just generating
    PAC/AUT instructions using -mbranch-protection will not enable
    authentication on the unwinder.
    
    Pre-approved with the requested changes here
    <https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586555.html>.
    
    gcc/ChangeLog:
    
            * ginclude/unwind-arm-common.h (_Unwind_VRS_RegClass): Introduce
            new pseudo register class _UVRSC_PAC.
            * libgcc/config/arm/pr-support.c (__gnu_unwind_execute): Decode
            exception opcode (0xb4) for saving RA_AUTH_CODE and authenticate
            with AUTG if found.
            * libgcc/config/arm/unwind-arm.c (struct pseudo_regs): New.
            (phase1_vrs): Introduce new field to store pseudo-reg state.
            (phase2_vrs): Likewise.
            (_Unwind_VRS_Get): Load pseudo register state from virtual reg set.
            (_Unwind_VRS_Set): Store pseudo register state to virtual reg set.
            (_Unwind_VRS_Pop): Load pseudo register value from stack into VRS.
    
    Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>

Diff:
---
 gcc/ginclude/unwind-arm-common.h |  3 ++-
 libgcc/config/arm/pr-support.c   | 32 ++++++++++++++++++++++++++++++++
 libgcc/config/arm/unwind-arm.c   | 26 ++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/gcc/ginclude/unwind-arm-common.h b/gcc/ginclude/unwind-arm-common.h
index d3831f6c60a..f26702e8c6c 100644
--- a/gcc/ginclude/unwind-arm-common.h
+++ b/gcc/ginclude/unwind-arm-common.h
@@ -127,7 +127,8 @@ extern "C" {
       _UVRSC_VFP = 1,       /* vfp */
       _UVRSC_FPA = 2,       /* fpa */
       _UVRSC_WMMXD = 3,     /* Intel WMMX data register */
-      _UVRSC_WMMXC = 4      /* Intel WMMX control register */
+      _UVRSC_WMMXC = 4,     /* Intel WMMX control register */
+      _UVRSC_PAC = 5        /* Armv8.1-M Mainline PAC/AUTH pseudo-register */
     }
   _Unwind_VRS_RegClass;
 
diff --git a/libgcc/config/arm/pr-support.c b/libgcc/config/arm/pr-support.c
index 2de96c2a447..e48854587c6 100644
--- a/libgcc/config/arm/pr-support.c
+++ b/libgcc/config/arm/pr-support.c
@@ -106,6 +106,7 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
 {
   _uw op;
   int set_pc;
+  int set_pac = 0;
   _uw reg;
 
   set_pc = 0;
@@ -114,6 +115,27 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
       op = next_unwind_byte (uws);
       if (op == CODE_FINISH)
 	{
+	  /* When we reach end, we have to authenticate R12 we just popped
+	     earlier.
+
+	     Note: while the check provides additional security against a
+	     corrupted unwind chain, it isn't essential for correct unwinding
+	     of an uncorrupted chain.  */
+#if defined(TARGET_HAVE_PACBTI)
+	  if (set_pac)
+	    {
+	      _uw sp;
+	      _uw lr;
+	      _uw pac;
+	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &sp);
+	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32, &lr);
+	      _Unwind_VRS_Get (context, _UVRSC_PAC, R_IP,
+			       _UVRSD_UINT32, &pac);
+	      __asm__ __volatile__
+		("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);
+	    }
+#endif
+
 	  /* If we haven't already set pc then copy it from lr.  */
 	  if (!set_pc)
 	    {
@@ -227,6 +249,16 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
 		return _URC_FAILURE;
 	      continue;
 	    }
+	  /* Pop PAC off the stack into VRS pseudo.pac.  */
+	  if (op == 0xb4)
+	    {
+	      if (_Unwind_VRS_Pop (context, _UVRSC_PAC, 0, _UVRSD_UINT32)
+		  != _UVRSR_OK)
+		return _URC_FAILURE;
+	      set_pac = 1;
+	      continue;
+	    }
+
 	  if ((op & 0xfc) == 0xb4)  /* Obsolete FPA.  */
 	    return _URC_FAILURE;
 
diff --git a/libgcc/config/arm/unwind-arm.c b/libgcc/config/arm/unwind-arm.c
index 386406564af..89f945d047e 100644
--- a/libgcc/config/arm/unwind-arm.c
+++ b/libgcc/config/arm/unwind-arm.c
@@ -64,6 +64,12 @@ struct wmmxc_regs
   _uw wc[4];
 };
 
+/*  Holds value of pseudo registers eg. PAC.  */
+struct pseudo_regs
+{
+  _uw pac;
+};
+
 /* The ABI specifies that the unwind routines may only use core registers,
    except when actually manipulating coprocessor state.  This allows
    us to write one implementation that works on all platforms by
@@ -78,6 +84,9 @@ typedef struct
   /* The first fields must be the same as a phase2_vrs.  */
   _uw demand_save_flags;
   struct core_regs core;
+  /* Armv8.1-M Mainline PAC/AUTH values.  This field should be in the same field
+     order as phase2_vrs.  */
+  struct pseudo_regs pseudo;
   _uw prev_sp; /* Only valid during forced unwinding.  */
   struct vfp_regs vfp;
   struct vfpv3_regs vfp_regs_16_to_31;
@@ -99,6 +108,7 @@ typedef struct
 {
   _uw demand_save_flags;
   struct core_regs core;
+  struct pseudo_regs pac;
 } phase2_vrs;
 
 /* Coprocessor register state manipulation functions.  */
@@ -175,6 +185,10 @@ _Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
     case _UVRSC_WMMXC:
       return _UVRSR_NOT_IMPLEMENTED;
 
+    case _UVRSC_PAC:
+      *(_uw *) valuep = vrs->pseudo.pac;
+      return _UVRSR_OK;
+
     default:
       return _UVRSR_FAILED;
     }
@@ -206,6 +220,10 @@ _Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
     case _UVRSC_WMMXC:
       return _UVRSR_NOT_IMPLEMENTED;
 
+    case _UVRSC_PAC:
+      vrs->pseudo.pac = *(_uw *) valuep;
+      return _UVRSR_OK;
+
     default:
       return _UVRSR_FAILED;
     }
@@ -246,6 +264,14 @@ _Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
       }
       return _UVRSR_OK;
 
+    case _UVRSC_PAC:
+      {
+	if (discriminator != 0)
+	  return _UVRSR_FAILED;
+	vrs->pseudo.pac = *(_uw *) vrs->core.r[R_SP];
+	return _UVRSR_OK;
+      }
+
     case _UVRSC_VFP:
       {
 	_uw start = discriminator >> 16;


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [gcc(refs/vendors/ARM/heads/arm-12-m-pacbti)] [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime
@ 2023-03-10 16:21 Andrea Corallo
  0 siblings, 0 replies; 2+ messages in thread
From: Andrea Corallo @ 2023-03-10 16:21 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:a2301e7f25466b8d0768aea06a64cc39bb2d9531

commit a2301e7f25466b8d0768aea06a64cc39bb2d9531
Author: Andrea Corallo <andrea.corallo@arm.com>
Date:   Mon Dec 6 11:42:11 2021 +0100

    [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime
    
    This patch adds authentication for when the stack is unwound when an
    exception is taken.  All the changes here are done to the runtime code
    in libgcc's unwinder code for Arm target. All the changes are guarded
    under defined (__ARM_FEATURE_PAC_DEFAULT) and activated only if the
    +pacbti feature is switched on for the architecture. This means that
    switching on the target feature via -march or -mcpu is sufficient and
    -mbranch-protection need not be enabled. This ensures that the
    unwinder is authenticated only if the PACBTI instructions are
    available in the non-NOP space as it uses AUTG.  Just generating
    PAC/AUT instructions using -mbranch-protection will not enable
    authentication on the unwinder.
    
    Pre-approved with the requested changes here
    <https://gcc.gnu.org/pipermail/gcc-patches/2021-December/586555.html>.
    
    gcc/ChangeLog:
    
            * ginclude/unwind-arm-common.h (_Unwind_VRS_RegClass): Introduce
            new pseudo register class _UVRSC_PAC.
    
    libgcc/ChangeLog:
            * config/arm/pr-support.c (__gnu_unwind_execute): Decode
            exception opcode (0xb4) for saving RA_AUTH_CODE and authenticate
            with AUTG if found.
            * config/arm/unwind-arm.c (struct pseudo_regs): New.
            (phase1_vrs): Introduce new field to store pseudo-reg state.
            (phase2_vrs): Likewise.
            (_Unwind_VRS_Get): Load pseudo register state from virtual reg set.
            (_Unwind_VRS_Set): Store pseudo register state to virtual reg set.
            (_Unwind_VRS_Pop): Load pseudo register value from stack into VRS.
    
    Co-Authored-By: Tejas Belagod  <tbelagod@arm.com>
    Co-Authored-By: Srinath Parvathaneni <srinath.parvathaneni@arm.com>

Diff:
---
 gcc/ginclude/unwind-arm-common.h |  3 ++-
 libgcc/config/arm/pr-support.c   | 32 ++++++++++++++++++++++++++++++++
 libgcc/config/arm/unwind-arm.c   | 28 ++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/gcc/ginclude/unwind-arm-common.h b/gcc/ginclude/unwind-arm-common.h
index d3831f6c60a..f26702e8c6c 100644
--- a/gcc/ginclude/unwind-arm-common.h
+++ b/gcc/ginclude/unwind-arm-common.h
@@ -127,7 +127,8 @@ extern "C" {
       _UVRSC_VFP = 1,       /* vfp */
       _UVRSC_FPA = 2,       /* fpa */
       _UVRSC_WMMXD = 3,     /* Intel WMMX data register */
-      _UVRSC_WMMXC = 4      /* Intel WMMX control register */
+      _UVRSC_WMMXC = 4,     /* Intel WMMX control register */
+      _UVRSC_PAC = 5        /* Armv8.1-M Mainline PAC/AUTH pseudo-register */
     }
   _Unwind_VRS_RegClass;
 
diff --git a/libgcc/config/arm/pr-support.c b/libgcc/config/arm/pr-support.c
index 2de96c2a447..e48854587c6 100644
--- a/libgcc/config/arm/pr-support.c
+++ b/libgcc/config/arm/pr-support.c
@@ -106,6 +106,7 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
 {
   _uw op;
   int set_pc;
+  int set_pac = 0;
   _uw reg;
 
   set_pc = 0;
@@ -114,6 +115,27 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
       op = next_unwind_byte (uws);
       if (op == CODE_FINISH)
 	{
+	  /* When we reach end, we have to authenticate R12 we just popped
+	     earlier.
+
+	     Note: while the check provides additional security against a
+	     corrupted unwind chain, it isn't essential for correct unwinding
+	     of an uncorrupted chain.  */
+#if defined(TARGET_HAVE_PACBTI)
+	  if (set_pac)
+	    {
+	      _uw sp;
+	      _uw lr;
+	      _uw pac;
+	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &sp);
+	      _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32, &lr);
+	      _Unwind_VRS_Get (context, _UVRSC_PAC, R_IP,
+			       _UVRSD_UINT32, &pac);
+	      __asm__ __volatile__
+		("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);
+	    }
+#endif
+
 	  /* If we haven't already set pc then copy it from lr.  */
 	  if (!set_pc)
 	    {
@@ -227,6 +249,16 @@ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
 		return _URC_FAILURE;
 	      continue;
 	    }
+	  /* Pop PAC off the stack into VRS pseudo.pac.  */
+	  if (op == 0xb4)
+	    {
+	      if (_Unwind_VRS_Pop (context, _UVRSC_PAC, 0, _UVRSD_UINT32)
+		  != _UVRSR_OK)
+		return _URC_FAILURE;
+	      set_pac = 1;
+	      continue;
+	    }
+
 	  if ((op & 0xfc) == 0xb4)  /* Obsolete FPA.  */
 	    return _URC_FAILURE;
 
diff --git a/libgcc/config/arm/unwind-arm.c b/libgcc/config/arm/unwind-arm.c
index 386406564af..9acb3de6bc3 100644
--- a/libgcc/config/arm/unwind-arm.c
+++ b/libgcc/config/arm/unwind-arm.c
@@ -64,6 +64,12 @@ struct wmmxc_regs
   _uw wc[4];
 };
 
+/*  Holds value of pseudo registers eg. PAC.  */
+struct pseudo_regs
+{
+  _uw pac;
+};
+
 /* The ABI specifies that the unwind routines may only use core registers,
    except when actually manipulating coprocessor state.  This allows
    us to write one implementation that works on all platforms by
@@ -78,6 +84,9 @@ typedef struct
   /* The first fields must be the same as a phase2_vrs.  */
   _uw demand_save_flags;
   struct core_regs core;
+  /* Armv8.1-M Mainline PAC/AUTH values.  This field should be in the same field
+     order as phase2_vrs.  */
+  struct pseudo_regs pseudo;
   _uw prev_sp; /* Only valid during forced unwinding.  */
   struct vfp_regs vfp;
   struct vfpv3_regs vfp_regs_16_to_31;
@@ -99,6 +108,7 @@ typedef struct
 {
   _uw demand_save_flags;
   struct core_regs core;
+  struct pseudo_regs pac;
 } phase2_vrs;
 
 /* Coprocessor register state manipulation functions.  */
@@ -175,6 +185,10 @@ _Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
     case _UVRSC_WMMXC:
       return _UVRSR_NOT_IMPLEMENTED;
 
+    case _UVRSC_PAC:
+      *(_uw *) valuep = vrs->pseudo.pac;
+      return _UVRSR_OK;
+
     default:
       return _UVRSR_FAILED;
     }
@@ -206,6 +220,10 @@ _Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
     case _UVRSC_WMMXC:
       return _UVRSR_NOT_IMPLEMENTED;
 
+    case _UVRSC_PAC:
+      vrs->pseudo.pac = *(_uw *) valuep;
+      return _UVRSR_OK;
+
     default:
       return _UVRSR_FAILED;
     }
@@ -246,6 +264,16 @@ _Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
       }
       return _UVRSR_OK;
 
+    case _UVRSC_PAC:
+      {
+	_uw *ptr = (_uw *) vrs->core.r[R_SP];
+	if (discriminator != 0)
+	  return _UVRSR_FAILED;
+	vrs->pseudo.pac = *(ptr++);
+	vrs->core.r[R_SP] = (_uw) ptr;
+	return _UVRSR_OK;
+      }
+
     case _UVRSC_VFP:
       {
 	_uw start = discriminator >> 16;

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-03-10 16:21 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-12 16:30 [gcc(refs/vendors/ARM/heads/arm-12-m-pacbti)] [PATCH 6/15] arm: Add pointer authentication for stack-unwinding runtime Andrea Corallo
2023-03-10 16:21 Andrea Corallo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).