From patchwork Fri Dec 12 15:46:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Khrustalev X-Patchwork-Id: 126461 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 2A3474BA2E1E for ; Fri, 12 Dec 2025 15:47:44 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2A3474BA2E1E X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id 971444BA2E04 for ; Fri, 12 Dec 2025 15:47:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 971444BA2E04 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 971444BA2E04 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765554433; cv=none; b=p2KHHJXeL1Z/K5j434BIsEpc433t4fsN0qSBq/+NgT4LC8FbHEJQvjEI4mwhsKbhf31fFxZzzAFAWVPnV+ogXvDzY7YQh3ZkfXzmWc/uVldpR/Q/L7troyUFtsNkjL3agWPRtJM5pCz3kWZSPSJNU+TTN4y8xL5uamaLSAy6UuI= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765554433; c=relaxed/simple; bh=Nl/6TxQrQTAD/Lmhd7UzNr3wZ0Nzhlj2HV8aYHpw5vA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Y/ldKJ955cgQwThuy+2CvlLeABCxUwRYOHDUm4RJuh4nHMVTIyyUrxKN88Bo1XqGw1sVK/PslVLXNSUoCD1Nzrnj4PWo09175W6cdEoogLY8yloRdzb0IzgI/PzW+JXYaSTD77Jf5R+PQ7kygp7d5gc30N1o2LraYVWQivrr0tk= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 971444BA2E04 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 0BF1B1575; Fri, 12 Dec 2025 07:47:06 -0800 (PST) Received: from fdebian.localdomain (unknown [10.57.76.253]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 052E33F73B; Fri, 12 Dec 2025 07:47:11 -0800 (PST) From: Yury Khrustalev To: libc-alpha@sourceware.org Cc: adhemerval.zanella@linaro.org, wilco.dijkstra@arm.com, broonie@kernel.org, jeremy.linton@arm.com, bill.roberts@foss.arm.com, steve.capper@arm.com Subject: [PATCH 2/2] aarch64: Tests for locking GCS Date: Fri, 12 Dec 2025 15:46:59 +0000 Message-ID: <20251212154659.142848-3-yury.khrustalev@arm.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20251212154659.142848-1-yury.khrustalev@arm.com> References: <20251212154659.142848-1-yury.khrustalev@arm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org 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 + . */ + +#include "tst-gcs-helper.h" + +#include +#include +#include +#include + +#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 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 + . */ + +#include "tst-gcs-helper.h" + +#include +#include +#include + +#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 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"