mbox series

[RFC,v2,00/22] aarch64: Add support for Guarded Control Stack extension

Message ID 20241018095653.2954868-1-yury.khrustalev@arm.com
Headers show
Series aarch64: Add support for Guarded Control Stack extension | expand

Message

Yury Khrustalev Oct. 18, 2024, 9:56 a.m. UTC
This patch series adds support for the Guarded Control Stack extension [1] that
allows to use shadow stacks on AArch64 targets with enabled GCS.

This patch series includes:
 - New tunables glibc.cpu.aarch64_gcs and glibc.cpu.aarch64_gcs_policy
 - Definition of jmp_buf offset for GCS
 - GCS support in longjmp, vfork, setcontext, makecontext
 - GCS support in static startup code and dynamic linker
 - Handling of GCS marking in dynamic binaries and DSOs
 - Handling of GCS marking in static binaries
 - Mark swapcontext with indirect_return
 - HWCAP_GCS

Corresponding Linux kernel patches [2] are in progress but are very close
to stable ABI. This is the only reason why this patch series is RFC.

GCS marking for binaries is specified in [3].

Regression tested on AArch64 and no regressions have been found.

Any feedback is welcome and appreciated.

Sources and branches:
 - binutils-gdb: sourceware.org/git/binutils-gdb.git users/ARM/gcs
 - gcc: gcc.gnu.org/git/gcc.git vendors/ARM/gcs-v2
   see https://gcc.gnu.org/gitwrite.html#vendor for setup details
 - glibc: this patch series, or
   sourceware.org/git/glibc.git arm/gcs-v2
 - kernel: git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/gcs

Cross-building the toolchain for target aarch64-none-linux-gnu:
 - build and install binutils-gdb
 - build and install GCC stage 1
 - install kernel headers
 - install glibc headers
 - build and install GCC stage 2 configuring with --enable-standard-branch-protection
 - build and install glibc
 - build and install GCC stage 3 along with target libraries configuring with --enable-standard-branch-protection

FVP model provided by the Shrinkwrap tool [4] can be used for testing.

Run with environment var

  GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1:glibc.cpu.aarch64_gcs_policy=2

By default both tunables are 0, the meaning is:
 - glibc.cpu.aarch64_gcs_policy=0:
   GCS is enabled if glibc.cpu.aarch64_gcs is set
 - glibc.cpu.aarch64_gcs_policy=1:
   GCS is enabled if glibc.cpu.aarch64_gcs is set and binary is marked
   if GCS is enabled, an incompatible dlopen is an error
 - glibc.cpu.aarch64_gcs_policy=2:
   GCS is enabled if glibc.cpu.aarch64_gcs is set
   if GCS is enabled, any incompatible binary is an error

[1] https://developer.arm.com/documentation/ddi0487/ka/ (chapter D11)
[2] https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/gcs
[3] https://github.com/ARM-software/abi-aa/blob/main/sysvabi64/sysvabi64.rst
[4] https://git.gitlab.arm.com/tooling/shrinkwrap.git

---

Szabolcs Nagy (22):
  aarch64: Add HWCAP_GCS
  aarch64: Add asm helpers for GCS
  elf.h: Define GNU_PROPERTY_AARCH64_FEATURE_1_GCS
  aarch64: Define jmp_buf offset for GCS
  aarch64: Add GCS support to longjmp
  aarch64: Add GCS support to vfork
  aarch64: Add GCS support for setcontext
  aarch64: Mark swapcontext with indirect_return
  aarch64: Add GCS support for makecontext
  aarch64: Try to free the GCS of makecontext
  aarch64: Add glibc.cpu.aarch64_gcs tunable
  aarch64: Enable GCS in static linked exe
  aarch64: Enable GCS in dynamic linked exe
  aarch64: Mark objects with GCS property note
  aarch64: Add glibc.cpu.aarch64_gcs_policy
  aarch64: Use l_searchlist.r_list for bti
  aarch64: Handle gcs marking
  aarch64: Use l_searchlist.r_list for gcs
  aarch64: Ignore GCS property of ld.so
  aarch64: Process gnu properties in static exe
  aarch64: Add GCS user-space allocation logic
  aarch64: use __alloc_gcs in makecontext

 elf/elf.h                                     |  1 +
 include/set-freeres.h                         |  4 +
 malloc/thread-freeres.c                       |  3 +
 sysdeps/aarch64/Makefile                      | 11 ++-
 sysdeps/aarch64/__alloc_gcs.c                 | 66 +++++++++++++
 sysdeps/aarch64/__longjmp.S                   | 30 ++++++
 sysdeps/aarch64/aarch64-gcs.h                 | 36 +++++++
 sysdeps/aarch64/bits/indirect-return.h        | 36 +++++++
 sysdeps/aarch64/dl-bti.c                      |  5 +-
 sysdeps/aarch64/dl-gcs.c                      | 64 ++++++++++++
 sysdeps/aarch64/dl-prop.h                     | 15 ++-
 sysdeps/aarch64/dl-start.S                    | 23 ++++-
 sysdeps/aarch64/dl-tunables.list              | 10 ++
 sysdeps/aarch64/jmpbuf-offsets.h              | 63 ++++++++++++
 sysdeps/aarch64/linkmap.h                     |  1 +
 sysdeps/aarch64/rtld-global-offsets.sym       |  5 +
 sysdeps/aarch64/setjmp.S                      | 10 ++
 sysdeps/aarch64/sysdep.h                      | 12 ++-
 sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h  |  1 +
 .../unix/sysv/linux/aarch64/cpu-features.c    |  9 ++
 sysdeps/unix/sysv/linux/aarch64/dl-procinfo.c | 13 +++
 .../unix/sysv/linux/aarch64/dl-procruntime.c  | 37 +++++++
 sysdeps/unix/sysv/linux/aarch64/getcontext.S  | 17 +++-
 sysdeps/unix/sysv/linux/aarch64/libc-start.h  | 61 ++++++++++++
 sysdeps/unix/sysv/linux/aarch64/makecontext.c | 97 ++++++++++++++++++-
 sysdeps/unix/sysv/linux/aarch64/setcontext.S  | 57 ++++++++++-
 sysdeps/unix/sysv/linux/aarch64/swapcontext.S | 32 ++++--
 sysdeps/unix/sysv/linux/aarch64/sysdep.h      |  6 +-
 .../sysv/linux/aarch64/ucontext-internal.h    |  5 +
 sysdeps/unix/sysv/linux/aarch64/vfork.S       |  8 +-
 30 files changed, 709 insertions(+), 29 deletions(-)
 create mode 100644 sysdeps/aarch64/__alloc_gcs.c
 create mode 100644 sysdeps/aarch64/aarch64-gcs.h
 create mode 100644 sysdeps/aarch64/bits/indirect-return.h
 create mode 100644 sysdeps/aarch64/dl-gcs.c
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/dl-procruntime.c
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/libc-start.h