From patchwork Tue Oct 1 22:59:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 13818974 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 6CDE6CF318A for ; Tue, 1 Oct 2024 23:06:42 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 023D168003D; Tue, 1 Oct 2024 19:06:42 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id F146668002B; Tue, 1 Oct 2024 19:06:41 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DB78C68003D; Tue, 1 Oct 2024 19:06:41 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id B670F68002B for ; Tue, 1 Oct 2024 19:06:41 -0400 (EDT) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 5199D141082 for ; Tue, 1 Oct 2024 23:06:41 +0000 (UTC) X-FDA: 82626569802.26.5A639CF Received: from nyc.source.kernel.org (nyc.source.kernel.org [147.75.193.91]) by imf26.hostedemail.com (Postfix) with ESMTP id 9461F140007 for ; Tue, 1 Oct 2024 23:06:39 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=sF0vzapk; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf26.hostedemail.com: domain of broonie@kernel.org designates 147.75.193.91 as permitted sender) smtp.mailfrom=broonie@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1727823978; a=rsa-sha256; cv=none; b=UuCKlI6P27e6dDwxFs9q6XxIo0UQxOB6PQlxNa6u2FK6E7wv6h2+Ep5soyJvmUAZ4XFD6F QRNrOtSkKT0JoEoVvAXCwOglxC5O4B3mG+Mjv/X0ufxv3pTK6FJiODkOkFdMJL90SfjlGj OSanjFunIi57BZlCBI8hnNbZmR7vH7E= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=sF0vzapk; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf26.hostedemail.com: domain of broonie@kernel.org designates 147.75.193.91 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=1727823978; 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=djWkkQJqS47t9Ws8YI1DK+6nZrq+sA911sh7UG9LF34=; b=qI76YN4MAVgpvzyriVL7hkeBykJfMsCp1e+yJW2NW8avGp0pIm6uBVSd20Gycbrb6Fib5y y7lBO89Pmh+HCQb8G2Bqfu5Mz/R6d058uHUjtdXDChUWUKwnhG5wlI9+ezEF2dqYvr+shI I9mDZa0hJNEfY+6Gj34l6lM5TY9QSNE= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id 58603A43329; Tue, 1 Oct 2024 23:06:30 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 774DAC4CED2; Tue, 1 Oct 2024 23:06:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1727823998; bh=Keu8ANmZTdMHjv5XQqqLSm0bGXVuBnTuWvLw/oRshns=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=sF0vzapkZ6OWVZ0k/kSzj3dKXchXzPS8npUmWJm1MibYtXim0Q9mxZwMWt97Di6xU yda6vZmOzJlaTRdQT2nxKlx9PcxcmeUxFRTv3juYtpJgOn1vaCcg1jaqPL1PPqxujd 7TuUsHctTr/bSf6uZlOYdv0qiVEXBHPousZcV8ZuvmzC10O3rKJQqPnnjo6ANTQbSq oV5u++OT6okSC9IE/37dGxczAWt268dY6guvk/M0eAqQ9wDSMOLN53HqS5ZVAv20Dp v9NkRpNaV2Bs19uxW+xQ4VJoATkfLh9VT9jvZwgQVU5xHwRdyg3XlTKeFsJ5OgwiAF LO80OecjvMfQw== From: Mark Brown Date: Tue, 01 Oct 2024 23:59:15 +0100 Subject: [PATCH v13 36/40] kselftest/arm64: Add test coverage for GCS mode locking MIME-Version: 1.0 Message-Id: <20241001-arm64-gcs-v13-36-222b78d87eee@kernel.org> References: <20241001-arm64-gcs-v13-0-222b78d87eee@kernel.org> In-Reply-To: <20241001-arm64-gcs-v13-0-222b78d87eee@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 , David Spickett , 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-99b12 X-Developer-Signature: v=1; a=openpgp-sha256; l=7444; i=broonie@kernel.org; h=from:subject:message-id; bh=Keu8ANmZTdMHjv5XQqqLSm0bGXVuBnTuWvLw/oRshns=; b=owGbwMvMwMWocq27KDak/QLjabUkhrQ/dQ9seMOy9MQMBIJ+ba6S1nVc7f8h0+Ve3ik2vRO8cwRe Oe/sZDRmYWDkYpAVU2RZ+yxjVXq4xNb5j+a/ghnEygQyhYGLUwAmIhbG/r9AVzTE7VlHEu8a91ecHA f2KbDWB+VsursoMLVvTcYLlk+TfV4sU2EK2eZb+qFWYNlJhx1qW20EVdMUejhU2SyiF8/fPz/D9Zlx +34bz/r7F5TTAk3OyMwqbJHjeH805R3XSf4XORIiKYnbc5VVrXsy/x1qnOVUf9fS/9lxyat9/gsfrY 6pD4r+7X1PQFL+Ma/MgpKjnSszynmzP1TKKoh4yMRsL1r0/XXChhtO8wUWCy9ybnwY1pzsPPe6SYpb xO7VO6RmC/5d8TbIu3+awIT5M9YZPinXiZYTm/67mPm6iGDzU3P+DU+rUzPL8459OGb06qyu0y+2Aj /NK9WPfTL53i+SePD25PyIo/McAQ== X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB X-Rspam-User: X-Stat-Signature: tjts3aapm6hrsxgun3zw6riq4x6k6mcc X-Rspamd-Queue-Id: 9461F140007 X-Rspamd-Server: rspam02 X-HE-Tag: 1727823999-314888 X-HE-Meta: U2FsdGVkX1+dT4kYuL/PhXe3fXHZWFKibMFHDcRpOvlsldzhGDe2oeVGD1zcZvdXuPUa1Fsd6+bvsX6B5D6RwvvHKiq3TJ8iNtZx1phs7b6Gtd9G0NMp4aT1qDTQSivirkCz/jCcBO89uli/ZOyOvk+bGDsCjnUwASUEYZpSSM14v9XxX8iulhUrX7nPQjZa3LcQM8DV93O0AUKYGFe3bNaUGBvD7Daanpb0L94aMs8XgeKqUryaFv7jq+fc61ID5ITYaoAceGwE7xFYESIyd9kvCbqf9hHm85VGYIA/tB1sa/cYk5QYU9583IQKebWtXmxcaq9qFFVe5yIppUGfafhrbPZ3wmNhA9L4XkY0MGhYT4eF0H6VQnnBD1JRjY+Tna3yAfCcBREAFGkwKRZPL9Xhit6ehTRVzqc4juE90XeKtVDRA3EvydFJ66kVcnSM4EfkTX/fBcfBx4EH1ppQhnx3/8tU2MMPa3tz0A0g0EejBi6ip6IdHC5+3TxT2EPL8kEgRQmlfBHkyerx7Se6hhV/tC/poDvU/Zkj+cWT2HNn7pnz0alvur09Gi8SAKiV6M8XGb0uNQo0EVYdVi7H022mERnlszYaROpQCAcH3ZyWtDRQsBzIehD99iZr8oj/r7YtQBbGYQiC9EZPYjz5mAHwfyUKOa9iP1M141tNzTXmPk+dHxt7Is5aXZFc2vnPhj4dPtbp3DEF3RqRzpfW8KPI5no9+SgOIOsTYCM2cPH++NUm57GNPYoMgASHu0DTwXOcxvu34N8ftUkjrlhvH0mSissAQhBYmq/Qz0sQRXxRDIDGvSxsN3SSbrpgBsZlLw+JHQ0MxWr34lQxUwEqXDzXdgDVn4SvhDU/E1hgZE/t/ns85nxLNpnZixIlXb6dzniKBugWZ+8ELjyiQ214JI5IpzOG9stFlH+nWPpK1uts2D4w71923+iaxJo5mRq0y1+uBW4vRPN0VRKhf24 eCZiCQG0 eFiYow4r9yY+qpV4qQFr3kKlzlSfl2KrbYR8zEcMcz7AEHQozWX0pTaqo9Z0ZtHtD+5nkHY0e6PBLFAP5QNixaxotrblmLyB3ikD471JtUwEoyJTivCkMAW2EEA/3nsMNA0mwZI6KHJ0sleS24lpAsOAVH/8tpNF6DlgPxzMhkjX1Wv7pPha7K5YM2pwrTtAE4s77aO9K363TPmOzPD9hB2J4GNzL86wDVD8hRisHZCJ66fqUhxbVPUcbCPiLe32lxOjl1KikU56M6Zk0yT2eNPJyM5uIQvE/HhsDBkQirqglqbp9Sbql8zX02cYsfwkkTqF8vygwjEDmy2WqwKuI7pCBDna7sMLdNfmqcYaOhADKspze4eE7d/6d5w== 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 Tested-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..989f75a491b7 --- /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_HWCAP) & HWCAP_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); +}