[PATCH 2/2] aarch64: Tests for locking GCS

Yury Khrustalev yury.khrustalev@arm.com
Fri Dec 12 15:46:59 GMT 2025


Check that GCS is locked properly with the new tunable
glibc.cpu.aarch64_gcs_lock
---
 sysdeps/unix/sysv/linux/aarch64/Makefile      | 17 +++++
 .../unix/sysv/linux/aarch64/tst-gcs-execv.c   | 62 ++++++++++++++++++
 .../sysv/linux/aarch64/tst-gcs-lock-static.c  |  1 +
 .../unix/sysv/linux/aarch64/tst-gcs-lock.c    | 63 +++++++++++++++++++
 .../linux/aarch64/tst-gcs-unlock-static.c     |  2 +
 .../unix/sysv/linux/aarch64/tst-gcs-unlock.c  |  2 +
 6 files changed, 147 insertions(+)
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/tst-gcs-execv.c
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock-static.c
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock.c
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock-static.c
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock.c

diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile
index 6741f8ec00..8938ef68a0 100644
--- a/sysdeps/unix/sysv/linux/aarch64/Makefile
+++ b/sysdeps/unix/sysv/linux/aarch64/Makefile
@@ -28,6 +28,8 @@ gcs-tests-dynamic = \
   tst-gcs-dlopen-override \
   tst-gcs-enforced \
   tst-gcs-enforced-abort \
+  tst-gcs-execv \
+  tst-gcs-lock \
   tst-gcs-noreturn \
   tst-gcs-optional-off \
   tst-gcs-optional-on \
@@ -36,15 +38,18 @@ gcs-tests-dynamic = \
   tst-gcs-shared-enforced-abort \
   tst-gcs-shared-optional \
   tst-gcs-shared-override \
+  tst-gcs-unlock \
   # gcs-tests-dynamic
 
 gcs-tests-static = \
   tst-gcs-disabled-static \
   tst-gcs-enforced-static \
   tst-gcs-enforced-static-abort \
+  tst-gcs-lock-static \
   tst-gcs-optional-static-off \
   tst-gcs-optional-static-on \
   tst-gcs-override-static \
+  tst-gcs-unlock-static \
   # gcs-tests-static
 
 tests += \
@@ -94,6 +99,18 @@ tst-gcs-optional-static-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
 tst-gcs-optional-static-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
 tst-gcs-override-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3
 
+LDFLAGS-tst-gcs-lock += -Wl,-z,gcs=always
+LDFLAGS-tst-gcs-lock-static += -Wl,-z,gcs=always
+LDFLAGS-tst-gcs-unlock += -Wl,-z,gcs=always
+LDFLAGS-tst-gcs-unlock-static += -Wl,-z,gcs=always
+tst-gcs-lock-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
+tst-gcs-lock-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
+tst-gcs-unlock-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1:glibc.cpu.aarch64_gcs_lock=0
+tst-gcs-unlock-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1:glibc.cpu.aarch64_gcs_lock=0
+
+LDFLAGS-tst-gcs-execv += -Wl,-z,gcs=always
+tst-gcs-execv-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1:glibc.cpu.aarch64_gcs_lock=1
+
 # force one of the dependencies to be unmarked
 LDFLAGS-tst-gcs-mod2.so += -Wl,-z,gcs=never
 
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-execv.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-execv.c
new file mode 100644
index 0000000000..d4ac2ccc02
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-execv.c
@@ -0,0 +1,62 @@
+/* AArch64 test for GCS for creating child process.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "tst-gcs-helper.h"
+
+#include <linux/prctl.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef PR_SET_SHADOW_STACK_STATUS
+# define PR_SET_SHADOW_STACK_STATUS	75
+#endif
+
+static int
+do_test_argv (int argc, char **argv)
+{
+  /* Check if GCS could possible by enabled.  */
+  if (!(getauxval (AT_HWCAP) & HWCAP_GCS))
+    FAIL_UNSUPPORTED ("kernel or CPU does not support GCS");
+
+  /* GCS should be enabled for this test at the start.  */
+  TEST_VERIFY (__check_gcs_status ());
+
+  if (argc == 1)
+    {
+      printf ("in parent: %u\n", getpid ());
+      /* Spawn child process.  */
+      char *args[] = { argv[0], (char *)"child", NULL };
+      execv (args[0], args);
+      FAIL_EXIT1 ("execv: %m");
+    }
+
+  /* In child.  */
+  printf ("in child: %u\n", getpid ());
+  TEST_VERIFY (__check_gcs_status ());
+
+  /* Try disabling GCS (should fail with EBUSY).  */
+  int res = prctl (PR_SET_SHADOW_STACK_STATUS, 0, 0, 0, 0);
+  TEST_COMPARE (res, -1);
+  TEST_COMPARE (errno, EBUSY);
+  perror ("prctl could not disable GCS");
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test_argv
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock-static.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock-static.c
new file mode 100644
index 0000000000..b80e2f70e8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock-static.c
@@ -0,0 +1 @@
+#include "tst-gcs-lock.c"
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock.c
new file mode 100644
index 0000000000..8d3a56e38c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-lock.c
@@ -0,0 +1,63 @@
+/* AArch64 test for GCS locking.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "tst-gcs-helper.h"
+
+#include <linux/prctl.h>
+#include <sys/prctl.h>
+#include <errno.h>
+
+#ifndef PR_SET_SHADOW_STACK_STATUS
+# define PR_SET_SHADOW_STACK_STATUS	75
+#endif
+
+static int
+do_test (void)
+{
+  /* Check if GCS could possible by enabled.  */
+  if (!(getauxval (AT_HWCAP) & HWCAP_GCS))
+    FAIL_UNSUPPORTED ("kernel or CPU does not support GCS");
+
+  TEST_VERIFY (__check_gcs_status ());
+
+  /* Try disabling GCS.  */
+  int res = prctl (PR_SET_SHADOW_STACK_STATUS, 0, 0, 0, 0);
+  if (res)
+    {
+      TEST_COMPARE (errno, EBUSY);
+      perror ("prctl");
+#ifdef GCS_SHOULD_UNLOCK
+      FAIL_EXIT1 ("GCS was not unlocked (was supposed to)");
+#else
+      TEST_VERIFY (__check_gcs_status ());
+#endif
+    }
+  else
+    {
+#ifdef GCS_SHOULD_UNLOCK
+      TEST_VERIFY (!__check_gcs_status ());
+      puts ("GCS unlocked successfully");
+#else
+      FAIL_EXIT1 ("GCS was unlocked (was not supposed to)");
+#endif
+    }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock-static.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock-static.c
new file mode 100644
index 0000000000..7e02820031
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock-static.c
@@ -0,0 +1,2 @@
+#define GCS_SHOULD_UNLOCK
+#include "tst-gcs-lock.c"
diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock.c b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock.c
new file mode 100644
index 0000000000..7e02820031
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/tst-gcs-unlock.c
@@ -0,0 +1,2 @@
+#define GCS_SHOULD_UNLOCK
+#include "tst-gcs-lock.c"
-- 
2.47.3



More information about the Libc-alpha mailing list