From patchwork Wed Nov 22 09:42:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 13464429 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 CD15FC61D9B for ; Wed, 22 Nov 2023 09:47:39 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6B5316B05D0; Wed, 22 Nov 2023 04:47:39 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 664FC6B05D1; Wed, 22 Nov 2023 04:47:39 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4E7A66B05D2; Wed, 22 Nov 2023 04:47:39 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 3A69C6B05D0 for ; Wed, 22 Nov 2023 04:47:39 -0500 (EST) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 11A201402E7 for ; Wed, 22 Nov 2023 09:47:39 +0000 (UTC) X-FDA: 81485113038.03.AE0EAA6 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by imf28.hostedemail.com (Postfix) with ESMTP id 295F7C0011 for ; Wed, 22 Nov 2023 09:47:36 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=LB7SgNo6; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf28.hostedemail.com: domain of broonie@kernel.org designates 145.40.68.75 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=1700646457; 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=GalVSC6rr/Hea1I+hx1kwCDZhCMKe4O85XK5pBaDCk0=; b=NhtE/fPC9KPlKa3XQByJ+SvOX5ER9CC1aNUi8uYLEkA1sGBlpfgBAuEfu0UAjrUeGW38Hr 1hES03LPQ1LR00A7oM0ktXR7Qi/2niRCwhDwxvPIUJZZUYIFXEiog0qNjncC+AU4qtweaX UIwMSE0T/2BAcdseXkhS6nqK/9MPHwk= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=LB7SgNo6; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf28.hostedemail.com: domain of broonie@kernel.org designates 145.40.68.75 as permitted sender) smtp.mailfrom=broonie@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1700646457; a=rsa-sha256; cv=none; b=igTqWY6/eztgm53j/+qYWTKE4tAk2ZdRN8grbs3d9BuNmezJmGjheIwjQv0qncbTN+rFXq DdA2DqPgL2JRMmJkMod2CCKHYnSuBWA4fBiZbUsvcVFdVPkUhH7sp9+h2fXkAaVLCdMCd/ BZ0ZjvK1JdG6U5Z47uXDjd45cWRLOu8= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by ams.source.kernel.org (Postfix) with ESMTP id E9F10B811A1; Wed, 22 Nov 2023 09:47:35 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4F21C433CA; Wed, 22 Nov 2023 09:47:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1700646455; bh=IY5iS/oB2kmvzWci1tpDsay+5IRKl4+rZruMuksVAkE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LB7SgNo6RWsd/lBKNFyJagX+3r7PWPvlIJ5G3FMo2sllE01HAa9PKVh2iTUQC1Rb0 yJO3uvkYJBQLOOKiPyugzUzRJOTqPRpAXQEHDVNvJz+dmwM9loA2xCVU0eBxB3Adhk 4eSvxd0/5uB+sqB75puTFV1XqKmTd3U0Gw31hE0HN6Hm27frLA/QcTSwmZEi+tgcDJ CrMhDqL4E66FQF+J95ojydeB9TeDY71OMglxa5YAcKrxIFSz3hAI+zVA8FGHv8xGjH Y5hgS/ewIyrkErkAXzLwEgeiwm9G3lgz4rDYZhyOrYs6lKfIfkWGMCC+hbucH9LeSw 3D7zj3rB2jY2Q== From: Mark Brown Date: Wed, 22 Nov 2023 09:42:45 +0000 Subject: [PATCH v7 35/39] kselftest/arm64: Add test coverage for GCS mode locking MIME-Version: 1.0 Message-Id: <20231122-arm64-gcs-v7-35-201c483bd775@kernel.org> References: <20231122-arm64-gcs-v7-0-201c483bd775@kernel.org> In-Reply-To: <20231122-arm64-gcs-v7-0-201c483bd775@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 , Kees Cook , Shuah Khan , "Rick P. Edgecombe" , Deepak Gupta , Ard Biesheuvel , Szabolcs Nagy Cc: "H.J. Lu" , Paul Walmsley , Palmer Dabbelt , Albert Ou , Florian Weimer , Christian Brauner , Thiago Jung Bauermann , 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.13-dev-0438c X-Developer-Signature: v=1; a=openpgp-sha256; l=7316; i=broonie@kernel.org; h=from:subject:message-id; bh=IY5iS/oB2kmvzWci1tpDsay+5IRKl4+rZruMuksVAkE=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBlXc0R4LQ2MwbVplKl/x3FSskzznneCR0XUHsAY ynLlIjNK3GJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCZV3NEQAKCRAk1otyXVSH 0E0WB/9tkEX9bs6tnZMZkzAOlUq8oTeqBNNURyadraQK2/RhxR4Sy+dX4QUAjn/b45ZksrLYaWY bcOelN06l97omQdTH6MJ4L/6kUTEafS/Ev4AUAQNjnyWSNkqgunuuq9dwz004R3UXCTWQYNkYQX HG2Ivmx378wXBBzq9LcKWfObX4bk9rAmTOp+RwzKVQwavq9+YIZ7u7TrjibaNUyb4vYYWoDDpmT smMy1dPOM/qExaIIV8j/HbHFNDKkfhLqt8Wsw0PR8c/smnGUz3BHs8VKklqSDgxE0CGIkKN6mKP pyaZ1dWc8QfLKzLZZMEUhb5Xt4ZvlwpIIHbYlm1gvInEP27j X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 295F7C0011 X-Stat-Signature: rigr46zyh65h64u6aynn1eg1rgtjgs64 X-HE-Tag: 1700646456-718995 X-HE-Meta: U2FsdGVkX1966ScGgwmUO7qqLAE1zH2RLttXClzo1BDl7ct5HDnyTqmYXF0aKYVmdQpdKEihRkd3n5EwVhNBH75uafRTZhjb1sze9kS+YbsFS5ui9bIqKcsc3Fc2nGFyPomv377pXYKuiCykQ82asrZoOqR+Q3ry/u9r2GGXGNvR2wWmhn5vhmwXv7VTWoM6gbZSyjwpfxi7TZoc4r9WvXzZfHdR7GYBFa2VG1zdJXibRI1OtbUig+zGr3ssYbOTopS5INQoQuX1sMFbaxlMMuOVHwerR62Ysi8g0ztMn3Zp815tkWdAQRWuSD04Mj6BJMeWdHBzcOz8T6SI8AcBQVVI5yJWedRQQmUtJnw2ZV+r4G2Qg08TdfUXNt4lWTj2+CVM//bBr+SndSpHMf9dUoppjiTtLaGYrKXgC9yyS0CQRTqlDEv6d54AB+P724OTPwzSbl6m/WjqQShxYP3D260KJMV3a+I0oyYVh1DzlyK4bqXUz0+oKyO+9ZK9Dv0oxDQdYV3F49DV84lHZyz4rCi+cT6WbxgHoKwT7/tGazkmuSP+BOMwXwq6B/YFtjnP8aFSRu21dHdGe7WAMgrszj8SVSTSdCg4T7VIKosuSv9xqaCKxGCgArFxYquf2zjkKCSVRLnNhGl+gBs19gEiN5FzfwL9zL6zFVtheKvTj7TWUWy3AUxC5QQvTZ8Xy3tkYWZVEvx+v+Fx4vKsurT5Chezir9iGMX6ciDcLmlNFBoiVPHOX3jse2ZKU/H5iewBDCT/SaHdwvLduGpgbYhazusuv4iUGmsoWbdwWtcyiUETJZg+GmgUX7T53SVpSDE6qJt3yc5gRxDeQzL7mJwtl9d7W1Q3WqwbqD9+tbyrirExsPlFUQipR9ZyA46TmFk/+8qH9j/9JZYj0bjTdDQhMdjvrTWk84mQj+gpBuCurTviyA9RgjRPJ8FMuHtnYwZk8aoJiHXMkwN0VOFV28l W4cIRXh2 1Oq3buAOFqt06XPIaYwPWul3Ui/5LhRfQHejvO5iFMBNCOCn4Zg+ThYYXURkdvAP4pFgy6VJbJTM0hgnpNQrTzjZKDhSvUYcv84+fL3Wxk5b6V4fQuuExicDwo0J3rHfi5l1HBm3NpHv8hVjOuIb9Cyen3HXFXpy9PTvdYOoDIf1PS9SAibru8VYLCIF4nEn06XcWNOLabjbwoFX9ctHvgXX9rcN7uFa7zFvuvcW1fDhDSfkJ1WZwpYYMc/B/fkvjJA8MxmryjJj2Wwt4cgKYuufGFZJg8+C3vbXJQDDYdTaT+u3Bm63WEr9igqPy2SzaTrl9 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. 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); +}