From patchwork Thu Aug 22 01:15:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 13772387 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 507E2C52D6F for ; Thu, 22 Aug 2024 01:23:20 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id CA3986B0124; Wed, 21 Aug 2024 21:23:19 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id C52CA6B0126; Wed, 21 Aug 2024 21:23:19 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A7F7F6B0128; Wed, 21 Aug 2024 21:23:19 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id 87E866B0124 for ; Wed, 21 Aug 2024 21:23:19 -0400 (EDT) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id ABBE61A1277 for ; Thu, 22 Aug 2024 01:23:18 +0000 (UTC) X-FDA: 82478133276.03.6D72875 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by imf03.hostedemail.com (Postfix) with ESMTP id 466AE20016 for ; Thu, 22 Aug 2024 01:23:15 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Y4RtFVRC; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf03.hostedemail.com: domain of broonie@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=broonie@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1724289731; a=rsa-sha256; cv=none; b=myxePSu4OcHR2BYOqt5VO8rMYoSv+w/OZyHMdPJuHBx2N3Jmjm5dmP1ShtKi0tjU4w34Dx QiyatFJAXz+dfpgsAPyiiOXJyMp5VKJt89Ba9471vExhdGI7ZAeWkFNEgiVRsZRY/+X7qQ 8C0Jp8kgmH8M8axaYHO3JZz9M0iVHDM= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Y4RtFVRC; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf03.hostedemail.com: domain of broonie@kernel.org designates 145.40.73.55 as permitted sender) smtp.mailfrom=broonie@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1724289731; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=qeTei2+Rv9TmGzFj/jgAMv84+i3cbC0I/TqETm/VMk4=; b=mzJW/s+vxJp7ACzngFDxfr0mCJPvy5QRk1d25xgCGGAFkt4vULYFpt/Y930OPKnPjv3NsI WRwFRmAav0Xa5dcZe7jOkLQmNmsgFIAMd6WAIA8LmPcNpENsM45+JsPiiHqikJxy/cCn18 PbN0G+LDPKgdeJhODcczyyojPvGxndY= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id 72B39CE0B61; Thu, 22 Aug 2024 01:23:13 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 49F14C32781; Thu, 22 Aug 2024 01:23:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1724289792; bh=/b4fLgBxrOG/LTGvqBDUXcUFQWiOWxSYArOHQoaOV+E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Y4RtFVRCr29PIUgkzAY+XbAdLBhRDwWOqbMJ2d312DSc9+ZbtTxiFvX3vElNEba9m C1BmXvN3SKR4VgdoluHQ9R9APT/mhxYFEgKcb9l1T8H0UG2KhmD2E+Av2ciYtP2r/q c3PWZjeyGT9G/PKIo2YjZ/bgvUDjth4ZTyZ7ej6kOeaqHAX/vVHRT1W6nvNoVAbf+I 1+O+i7Vb1GG9I6TY7ZNaEp6nfAMYhK18ZTBsr2NTFVHLkazwWl/q1kwgr4GzGj98vw +D66JCBXjDRZcRUgmYDGCe0xpfAmu+7LtIwj5QMAvNSZQMuloKbzRVhVIxMmv0ZJfE +6s/GYI7hRNuQ== From: Mark Brown Date: Thu, 22 Aug 2024 02:15:38 +0100 Subject: [PATCH v11 35/39] kselftest/arm64: Add test coverage for GCS mode locking MIME-Version: 1.0 Message-Id: <20240822-arm64-gcs-v11-35-41b81947ecb5@kernel.org> References: <20240822-arm64-gcs-v11-0-41b81947ecb5@kernel.org> In-Reply-To: <20240822-arm64-gcs-v11-0-41b81947ecb5@kernel.org> To: Catalin Marinas , Will Deacon , Jonathan Corbet , Andrew Morton , Marc Zyngier , Oliver Upton , James Morse , Suzuki K Poulose , Arnd Bergmann , Oleg Nesterov , Eric Biederman , Shuah Khan , "Rick P. Edgecombe" , Deepak Gupta , Ard Biesheuvel , Szabolcs Nagy , Kees Cook Cc: "H.J. Lu" , Paul Walmsley , Palmer Dabbelt , Albert Ou , Florian Weimer , Christian Brauner , Thiago Jung Bauermann , Ross Burton , Yury Khrustalev , Wilco Dijkstra , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, kvmarm@lists.linux.dev, linux-fsdevel@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org, Mark Brown X-Mailer: b4 0.15-dev-37811 X-Developer-Signature: v=1; a=openpgp-sha256; l=7382; i=broonie@kernel.org; h=from:subject:message-id; bh=/b4fLgBxrOG/LTGvqBDUXcUFQWiOWxSYArOHQoaOV+E=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBmxpE/isGW7OQJkuu8ReWnaH8lJAorwHq2yQobWtk5 1aRbRAOJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCZsaRPwAKCRAk1otyXVSH0ExZB/ 9sQqgy2L5T0j4x/ehMRhrSHqRqOH1ayILAsZuRPy0t0qR4727c8NWwnibGIxk5d3rFpOWJWySsAFBA khDI/1NfNGnL/2m7hR5EgdusKvJnFc611vr/Jp1MWTnAuYccHFIE3atcJSBrn1o5a0j+JoGOd2HwDG I7eLHbqb9b7z/SgRP7beokELidNB+lz+HhYuQe16EDBujNRKFYMtp8xqonffgMdAL6N3tNljJYj2tl g02b/0pNuka2tLU+EnMXlpQfL5AcjiICaY6KlHEojdpctPihrbrpLbL7vlSw19XLLwfgwvLhhWYAj2 /30lTG7tSR4LI+QAImwlkHiBf2N5mu X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 466AE20016 X-Stat-Signature: o34yaay1dy7yqgpwih7hqhexhid4yemk X-Rspam-User: X-HE-Tag: 1724289795-225238 X-HE-Meta: U2FsdGVkX1/lL/lrh/MlhzN7ZGmvowXLm4whXLYxQDGNQmlyn9tdBtfmBdg3AkEzqNxcxhn6uC5hYsJbXQ6oYnhASZXj4FJX+EkZyAOUE3QtWGg35R7j7LKlJSTgI2n6d2edqNosLyJh5oHZsSV9zPthRWqYIz3dTWVWlpnFMzK8gYLdp7zWGcwlpJwO8c6KY/6BBw6deDU010Urc8s9L9/D42SHJ2eAGvegoz6Odti+mBK6CdxGKJMV2VyK+szI/zG5qB5HlfIHdUeKgln2xqco5jIakaNZTs95aujbG9T4n7vg3A4+md1gg+b98YEuIWDx6BjIEnO41gRUyF58PGoa+ma8FRIbNhjAKl1Cv9H+DFXBQk5Uw7T/14jfSUpuUHsqXIHDMZIZY6WNPVd9w8pFNGbZgDC3AlgKdICqHYrKtic7C/ay3v3C1OoaCpMo/mNEop8CuqjqT1VdqSUBM8VsZ+qeHarS9yLA4xFAsh0nk+E+YQX++yqu18zgT/9rEeisZHFywxepH7VjcRLFg20kB8EPV4KwMQk8Gria6LgSXCyG5iyyLBXtTOrYoPK7dZvAy/lcpCDuH30OnrHoyNgmRBNVTIRQvv3Pg0eabDxlo0ppFYSRuDg54G3idabzqwv8tpWCwTmVFxSpQKr1xXeJ7em5whypPYAuOq8cpa+TT+mgwqpTaglwUyyOHTWQvwl+L1buwB6x3ZuTQnLO98A+tbt6gpXVzgAhBWLTkylHIdVQVYYjo+Ng6Au+wlGRu7EmSVaKvkQwh85mAqjnvWNgn0qlPsfNl9LcN0o6LJONXYm03ME9IAKiVVo79WLgNEKiCW/gcR05+qDjhhSbv8Ci33kGzHTVRS5tuAeCdpOHjTGlT/IuF2MSYkO/JE9PwaRzCmgG1rTKKLPNCGn5jMFo/P8Az9lXjk7furuyjgKtgg4bOsANzOp9S6MYfwo+vr77QsjHXLIxmsd6ggO vvTgZK50 FxhBoWJ+z8vvmHRQVD5W+pByQfcR5HgdUbKAhjjeKCUmzCBd06cYCyxHZ4zZ0lcCMLovwtlGBlItiKx8Qnma5T6n462Rc7Ktzgn8nqym/UO2eZ/pN4yDOhUlOxDjfkvkstK7TK+Ns5xrhTnricFkA+AZ72052Gx+J9Jwcp/bo70qYEYIt9AByiOBsOQemHYrnfCCKnPTmkRqLdrpmSc20+q5pw6HcbGmt5tKDVSpSwsnyjHQ0CyHMe8s0E1/CHZungT/VjTNv0IuFNwNW9+KI7Ecdz/dtV6TkGuVGP9rnh2CZXCU7LxrLCVHiWZMp3v/Aa44MCswqnx9SSltZ5kS3JJszynwnTHTSsJne5bQXADyrDdBUpk98bq/hwwggPbrRDzlJ X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Verify that we can lock individual GCS mode bits, that other modes aren't affected and as a side effect also that every combination of modes can be enabled. Normally the inability to reenable GCS after disabling it would be an issue with testing but fortunately the kselftest_harness runs each test within a fork()ed child. This can be inconvenient for some kinds of testing but here it means that each test is in a separate thread and therefore won't be affected by other tests in the suite. Once we get toolchains with support for enabling GCS by default we will need to take care to not do that in the build system but there are no such toolchains yet so it is not yet an issue. Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- tools/testing/selftests/arm64/gcs/.gitignore | 1 + tools/testing/selftests/arm64/gcs/Makefile | 2 +- tools/testing/selftests/arm64/gcs/gcs-locking.c | 200 ++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/arm64/gcs/.gitignore b/tools/testing/selftests/arm64/gcs/.gitignore index 5810c4a163d4..0c86f53f68ad 100644 --- a/tools/testing/selftests/arm64/gcs/.gitignore +++ b/tools/testing/selftests/arm64/gcs/.gitignore @@ -1,2 +1,3 @@ basic-gcs libc-gcs +gcs-locking diff --git a/tools/testing/selftests/arm64/gcs/Makefile b/tools/testing/selftests/arm64/gcs/Makefile index a8fdf21e9a47..2173d6275956 100644 --- a/tools/testing/selftests/arm64/gcs/Makefile +++ b/tools/testing/selftests/arm64/gcs/Makefile @@ -6,7 +6,7 @@ # nolibc. # -TEST_GEN_PROGS := basic-gcs libc-gcs +TEST_GEN_PROGS := basic-gcs libc-gcs gcs-locking LDLIBS+=-lpthread diff --git a/tools/testing/selftests/arm64/gcs/gcs-locking.c b/tools/testing/selftests/arm64/gcs/gcs-locking.c new file mode 100644 index 000000000000..f6a73254317e --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/gcs-locking.c @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 ARM Limited. + * + * Tests for GCS mode locking. These tests rely on both having GCS + * unconfigured on entry and on the kselftest harness running each + * test in a fork()ed process which will have it's own mode. + */ + +#include + +#include +#include + +#include + +#include "kselftest_harness.h" + +#include "gcs-util.h" + +#define my_syscall2(num, arg1, arg2) \ +({ \ + register long _num __asm__ ("x8") = (num); \ + register long _arg1 __asm__ ("x0") = (long)(arg1); \ + register long _arg2 __asm__ ("x1") = (long)(arg2); \ + register long _arg3 __asm__ ("x2") = 0; \ + register long _arg4 __asm__ ("x3") = 0; \ + register long _arg5 __asm__ ("x4") = 0; \ + \ + __asm__ volatile ( \ + "svc #0\n" \ + : "=r"(_arg1) \ + : "r"(_arg1), "r"(_arg2), \ + "r"(_arg3), "r"(_arg4), \ + "r"(_arg5), "r"(_num) \ + : "memory", "cc" \ + ); \ + _arg1; \ +}) + +/* No mode bits are rejected for locking */ +TEST(lock_all_modes) +{ + int ret; + + ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, ULONG_MAX, 0, 0, 0); + ASSERT_EQ(ret, 0); +} + +FIXTURE(valid_modes) +{ +}; + +FIXTURE_VARIANT(valid_modes) +{ + unsigned long mode; +}; + +FIXTURE_VARIANT_ADD(valid_modes, enable) +{ + .mode = PR_SHADOW_STACK_ENABLE, +}; + +FIXTURE_VARIANT_ADD(valid_modes, enable_write) +{ + .mode = PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE, +}; + +FIXTURE_VARIANT_ADD(valid_modes, enable_push) +{ + .mode = PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_PUSH, +}; + +FIXTURE_VARIANT_ADD(valid_modes, enable_write_push) +{ + .mode = PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE | + PR_SHADOW_STACK_PUSH, +}; + +FIXTURE_SETUP(valid_modes) +{ +} + +FIXTURE_TEARDOWN(valid_modes) +{ +} + +/* We can set the mode at all */ +TEST_F(valid_modes, set) +{ + int ret; + + ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, + variant->mode); + ASSERT_EQ(ret, 0); + + _exit(0); +} + +/* Enabling, locking then disabling is rejected */ +TEST_F(valid_modes, enable_lock_disable) +{ + unsigned long mode; + int ret; + + ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, + variant->mode); + ASSERT_EQ(ret, 0); + + ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + ASSERT_EQ(mode, variant->mode); + + ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, variant->mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + + ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, 0); + ASSERT_EQ(ret, -EBUSY); + + _exit(0); +} + +/* Locking then enabling is rejected */ +TEST_F(valid_modes, lock_enable) +{ + unsigned long mode; + int ret; + + ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, variant->mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + + ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, + variant->mode); + ASSERT_EQ(ret, -EBUSY); + + ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + ASSERT_EQ(mode, 0); + + _exit(0); +} + +/* Locking then changing other modes is fine */ +TEST_F(valid_modes, lock_enable_disable_others) +{ + unsigned long mode; + int ret; + + ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, + variant->mode); + ASSERT_EQ(ret, 0); + + ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + ASSERT_EQ(mode, variant->mode); + + ret = prctl(PR_LOCK_SHADOW_STACK_STATUS, variant->mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + + ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, + PR_SHADOW_STACK_ALL_MODES); + ASSERT_EQ(ret, 0); + + ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + ASSERT_EQ(mode, PR_SHADOW_STACK_ALL_MODES); + + + ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, + variant->mode); + ASSERT_EQ(ret, 0); + + ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); + ASSERT_EQ(ret, 0); + ASSERT_EQ(mode, variant->mode); + + _exit(0); +} + +int main(int argc, char **argv) +{ + unsigned long mode; + int ret; + + if (!(getauxval(AT_HWCAP2) & HWCAP2_GCS)) + ksft_exit_skip("SKIP GCS not supported\n"); + + ret = prctl(PR_GET_SHADOW_STACK_STATUS, &mode, 0, 0, 0); + if (ret) { + ksft_print_msg("Failed to read GCS state: %d\n", ret); + return EXIT_FAILURE; + } + + if (mode & PR_SHADOW_STACK_ENABLE) { + ksft_print_msg("GCS was enabled, test unsupported\n"); + return KSFT_SKIP; + } + + return test_harness_run(argc, argv); +}