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

Message ID 20241129163721.2385847-1-yury.khrustalev@arm.com (mailing list archive)
Headers
Series aarch64: Add support for Guarded Control Stack extension |

Message

Yury Khrustalev Nov. 29, 2024, 4:36 p.m. UTC
  This patch series adds support for the Guarded Control Stack extension [1] that
allows to use shadow stacks on AArch64 systems 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 very close to stable ABI.
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 master
 - glibc: this patch series
 - 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 and target libraries configuring with --enable-standard-branch-protection

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

To enable GCS, run tests with environment variable:

  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

---

Changes in v4:
 - Merged patches 17 and 18 from v3 series.
 - Amended tests that would fail if executed on a system with GCS.

Link to v3:
https://inbox.sourceware.org/libc-alpha/20241023083920.466015-1-yury.khrustalev@arm.com/

---

Szabolcs Nagy (21):
  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: 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

Yury Khrustalev (1):
  aarch64: Fix tests not compatible with targets supporting GCS

 elf/elf.h                                     |  1 +
 elf/tst-asm-helper.h                          | 49 ++++++++++
 elf/tst-big-note-lib.S                        |  2 +
 elf/tst-ro-dynamic-mod.map                    |  7 +-
 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/aarch64/tst-vpcs-mod.S                |  4 +-
 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 +-
 34 files changed, 766 insertions(+), 34 deletions(-)
 create mode 100644 elf/tst-asm-helper.h
 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
  

Comments

Yury Khrustalev Dec. 2, 2024, 4:21 p.m. UTC | #1
On Fri, Nov 29, 2024 at 04:36:59PM +0000, Yury Khrustalev wrote:
> This patch series adds support for the Guarded Control Stack extension [1] that
> allows to use shadow stacks on AArch64 systems with enabled GCS.

> Sources and branches:
>  - binutils-gdb: sourceware.org/git/binutils-gdb.git users/ARM/gcs
>  - gcc: gcc.gnu.org/git/gcc.git master
>  - glibc: this patch series
>  - kernel: git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/gcs

Update on relevant sources:

 - binutils can now be taken from master
 - in case there are Glibc test failures, it could partly be due to the
   7828dc07051 commit in GCC that can be rolled back to allow building
   and running Glibc tests, see [1] for details

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=32366

Kind regards,
Yury
  
Carlos O'Donell Dec. 2, 2024, 9:18 p.m. UTC | #2
On 11/29/24 11:36 AM, Yury Khrustalev wrote:
> This patch series adds support for the Guarded Control Stack extension [1] that
> allows to use shadow stacks on AArch64 systems 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 very close to stable ABI.
> GCS marking for binaries is specified in [3].
> Regression tested on AArch64 and no regressions have been found.
> 
> Any feedback is welcome and appreciated.

I think we could commit a lot of the changes in this series with the exception of
exporting the public header constants?

The tunable could be added, but have it do nothing, and mark it in the manual as
"reserved for future use."

Then once the kernel comes out we can backport a commit that adds the header
constants (allowed and doesn't impact ABI) and then the tunable gets documented
as working and functional (no impact on ld.so<->libc.so.6 private ABI).

Cheers,
Carlos.
  
Yury Khrustalev Dec. 6, 2024, 1:37 p.m. UTC | #3
Hi Carlos,

On Mon, Dec 02, 2024 at 04:18:01PM -0500, Carlos O'Donell wrote:
> On 11/29/24 11:36 AM, Yury Khrustalev wrote:
> > This patch series adds support for the Guarded Control Stack extension [1] that
> > allows to use shadow stacks on AArch64 systems with enabled GCS.
> >
> > ...
> >
> > Corresponding Linux kernel patches [2] are very close to stable ABI.
> > GCS marking for binaries is specified in [3].
> > Regression tested on AArch64 and no regressions have been found.
> > 
> > Any feedback is welcome and appreciated.
> 
> I think we could commit a lot of the changes in this series with the exception of
> exporting the public header constants?
> 
> The tunable could be added, but have it do nothing, and mark it in the manual as
> "reserved for future use."
> 
> Then once the kernel comes out we can backport a commit that adds the header
> constants (allowed and doesn't impact ABI) and then the tunable gets documented
> as working and functional (no impact on ld.so<->libc.so.6 private ABI).
> 
> Cheers,
> Carlos.

Thank you for your suggestions and comments. I've updated patch series to exclude
and public headers constants: hopefully v5 [1] is much better suited to be merged
ahead of the upcoming Linux release.

[1] https://inbox.sourceware.org/libc-alpha/20241206132952.2410680-1-yury.khrustalev@arm.com/

Kind regards,
Yury