From patchwork Tue Oct 1 22:58:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Brown X-Patchwork-Id: 13818907 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 A254BCF3189 for ; Tue, 1 Oct 2024 23:01:23 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 37BD86B00A5; Tue, 1 Oct 2024 19:01:23 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 302BE68002B; Tue, 1 Oct 2024 19:01:23 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 17E296B0108; Tue, 1 Oct 2024 19:01:23 -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 E4E3768002B for ; Tue, 1 Oct 2024 19:01:22 -0400 (EDT) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 5BAC91A0611 for ; Tue, 1 Oct 2024 23:01:22 +0000 (UTC) X-FDA: 82626556404.04.72FCBFF Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf10.hostedemail.com (Postfix) with ESMTP id 835ECC001A for ; Tue, 1 Oct 2024 23:01:20 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=jVZM9w2T; spf=pass (imf10.hostedemail.com: domain of broonie@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=broonie@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1727823615; a=rsa-sha256; cv=none; b=NrPdGovlBk5KE1uHIKwH7kJcLBwtZGNneJNr2H2CSt1TnL3vydvy4VSVUsQJOTXAMPnOl0 TzkbVi3QOgXHniUJFDqxqAyXld5Zt1KRIQx4D8R0E020IeSKOttr2iBcNLdhcdcF1Dp6h0 UBn/2cx8qmrP2WreBBuwE8jjEcoqfxY= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=jVZM9w2T; spf=pass (imf10.hostedemail.com: domain of broonie@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=broonie@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1727823615; 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=KRwT3C5l7QqZ3o+UtXod0+pqLsc5A2nTc9YPPINulIE=; b=HuhCuqsjUKQHPnJji+Q2Flu9iIaULxAgQ3SVsjDvnAY7lYnOJAg3xMbhkfB8R6B2oCMnpA H/d7xJJOEXCDmLWFM8FvbItflRYVgFwCQHFxiS/1bTSd/NMY47jEP9/IKz/xl3JsXCJ/4/ nayU/kLE113XH7n5REX3BYT1QWx1WhI= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 948D55C045A; Tue, 1 Oct 2024 23:01:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1CB2CC4CECF; Tue, 1 Oct 2024 23:01:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1727823679; bh=Vf2uNluHz2rca3mw8TcTX+NsJV/Qh5T4cYUs2i7TXxM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jVZM9w2TFPYRXcHqVrP0Qzet5ZimUajVBnGH0EhpBkabdMfLXa+RzCA+jUnjyGM1m CJ8EFXdP1PgHrC1tKvVGnJWlxMjAFQMP2gFRgwEqZO8N6qSYimU8ejOpwwGHnFZuXY 86DXvpsvB3FWiEMk+ntP0Lha7xlDlV5qpMAZOggrQuJm3djAJfUnCgt713hfxPM+Ev 0BXqsx8xr/0zc257E+hP6isHgW4XTx+znlwISB5hvczbAi1lqyvDXPzJ5/yi8ANzdt jNLailjxmqcTsawgpffDetmjcAUOgQOmif3/O5yhtJeanlELsfO43OyWb9ZUezbd+v tN8vKA+l6a/Pg== From: Mark Brown Date: Tue, 01 Oct 2024 23:58:46 +0100 Subject: [PATCH v13 07/40] arm64/gcs: Document the ABI for Guarded Control Stacks MIME-Version: 1.0 Message-Id: <20241001-arm64-gcs-v13-7-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=10660; i=broonie@kernel.org; h=from:subject:message-id; bh=Vf2uNluHz2rca3mw8TcTX+NsJV/Qh5T4cYUs2i7TXxM=; b=owEBbQGS/pANAwAKASTWi3JdVIfQAcsmYgBm/H7Ju1pToDWaUGEp3Hkm5trwDDFmJAt21ggli5wt 1wpFq4aJATMEAAEKAB0WIQSt5miqZ1cYtZ/in+ok1otyXVSH0AUCZvx+yQAKCRAk1otyXVSH0HYwB/ 91P3Xkg8BBGXxh3Fgc894UqDHkhXWVd3t+Pksyai5obwhEVa85s8Wg9ISM+HTQkh460hHADA/xDbFF 2YjD56YVZP5Dg+ORNWhRRVdTKX/eo1sLcWdJvt9xONO7FI9kLgypXqSp630Xos/2fq/AHJy62H/9l8 q9RceRohuQOKkPBoI66VYnysha3TgtYDEMxt4978KiJe/JB0aYFC1ixMNEa8hdorjk8s7JUw0RK8wd MbGVvFdRIm33dFehcmpQPYMvJSvBGHAq3ED4DFY8dttj9OB30BGbU64SftZehNJudxSMnvy8NHs8NB dI+RpTjveoc1pWc7Ojpl1gXEDkyEIa X-Developer-Key: i=broonie@kernel.org; a=openpgp; fpr=3F2568AAC26998F9E813A1C5C3F436CA30F5D8EB X-Stat-Signature: ypwxrrmc5gbm8znmfi31s8xy1qhfwf89 X-Rspamd-Queue-Id: 835ECC001A X-Rspam-User: X-Rspamd-Server: rspam10 X-HE-Tag: 1727823680-780706 X-HE-Meta: U2FsdGVkX1+73FcA2JhZTfNDBTdx965LJ+WVCRL7veNi3R90VPzZd21yB7EGHV+t/vAN7tPE2mfbky/2Ypu1rAjwjfMe9Y7THXbFZxDYHKSGSAMIDFFqsP48zCrYOpnbNn5cfkKGEVy3FVbkWDHuXfoB0h/kWg5zDLbexYZ9eBvVEeoY15D+++qQPUTPogLF22JGsP0rW04XIhcFJJ5myPUs3zjKrKurB5BtzC8fPqWOKMzuXbJ8ymnbQVt9U0MMF8bXgEZW4L8YBjGxeI+ARM7rT6adOZlYrg4gW868P2/ESYm667M/6kyUFNPXnTjhBSPtmtpudyeGXPz/0+oFs+8j0FrJDp3OX95fAwk1/6dUsHLx8u6YSITe1DgEE7t2rT7ECPKwYIeC4U+moGgyIwaDwLjlLF8XRxH3kYq3btHMlUrdgFd8r5iEI/UsAlhB/ba/Xt8x46ZrThg5ZdmTBzP1g2MnPFsbmBi4h+c1KAZRQSpE7Job+59aIeDtZFndP/YvtK+YspNuI4otiGsWHGk/PyC3eJ63/6L6FtaBapqbHSZoQ++3tDcNQv31O/u2zyQWf1WO6jSsiqk3Krg4//6B8kWJNFUCHSsR3NY/YMfcu3zeVGOdMf+WpkbxPCx4KnaXwfb7+I5rYe53s8ZqqPWxEtWk4d2EwwvOKoZyeLmNlf+Rbd4QVnjPKkRf0Cp42xbnLPpHDHU7PYPeqLVexy9ZhJpHfVkRRHYNOU2dKionisiy1aPM13WzDudZB99D55r6TGBAPplKThqK7bcIrmJWuYiBWjGkylpadSdEMDpXmKJ8I7Dof4YdUziIrJg6Kmez9XE45UZa4gNG7TbBJf9EPueFz0CCat9SWIbnIGYcDpI+/OnvN7qBTFbCsJldf2HGNnc06BeKtuAWRVgkmTljA8DCUTkmV8XQFtR/ok28TWIJiSojMBEbBF0pp7kYQAjyjsR4eHuN3PWTJPu 9wbTlh1p IllRC/O9aabiFrFmN+yQkd4oFJKnaClNxQxneRuM/ZfOL/nkGKr6dgMzC22YMHNBsMGZSD5eVPhhotHHsjVQ7e6npqsR8DnnOV6aIVjpjUdpW2Cl+e6777AoRBXDzvez9xJaADNZebilWXbJEBQmlL0TUNM/GHNF0+uqUPjR0X58KgludB9sqkIqmipLvh80T73v++VQGpYevzVscS5795TbaBKG/adnhDCANs33hxjczVrxNeviHXYhgs1cKk1c7O864Ulb7+pnsHwd5E8AOjSvcbtRqvn/lBTaKdsEHdwYGPEbc2n4FUsW/CPS0TR8gNEhtzz2UdDBO7szAeG/iXE5Lmdpge7x+2vO5jf1ajczeqHjTjYCst+FEmBOCFHJyjUf46VqzdMdJ6JERnsycM8UinDSCsb9C84shGMf9IZu3Y/I08ap1fpBQ3A== 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: Add some documentation of the userspace ABI for Guarded Control Stacks. Reviewed-by: Thiago Jung Bauermann Reviewed-by: Catalin Marinas Acked-by: Yury Khrustalev Signed-off-by: Mark Brown --- Documentation/arch/arm64/gcs.rst | 230 +++++++++++++++++++++++++++++++++++++ Documentation/arch/arm64/index.rst | 1 + 2 files changed, 231 insertions(+) diff --git a/Documentation/arch/arm64/gcs.rst b/Documentation/arch/arm64/gcs.rst new file mode 100644 index 000000000000..af58d9151cb7 --- /dev/null +++ b/Documentation/arch/arm64/gcs.rst @@ -0,0 +1,230 @@ +=============================================== +Guarded Control Stack support for AArch64 Linux +=============================================== + +This document outlines briefly the interface provided to userspace by Linux in +order to support use of the ARM Guarded Control Stack (GCS) feature. + +This is an outline of the most important features and issues only and not +intended to be exhaustive. + + + +1. General +----------- + +* GCS is an architecture feature intended to provide greater protection + against return oriented programming (ROP) attacks and to simplify the + implementation of features that need to collect stack traces such as + profiling. + +* When GCS is enabled a separate guarded control stack is maintained by the + PE which is writeable only through specific GCS operations. This + stores the call stack only, when a procedure call instruction is + performed the current PC is pushed onto the GCS and on RET the + address in the LR is verified against that on the top of the GCS. + +* When active the current GCS pointer is stored in the system register + GCSPR_EL0. This is readable by userspace but can only be updated + via specific GCS instructions. + +* The architecture provides instructions for switching between guarded + control stacks with checks to ensure that the new stack is a valid + target for switching. + +* The functionality of GCS is similar to that provided by the x86 Shadow + Stack feature, due to sharing of userspace interfaces the ABI refers to + shadow stacks rather than GCS. + +* Support for GCS is reported to userspace via HWCAP_GCS in the aux vector + AT_HWCAP2 entry. + +* GCS is enabled per thread. While there is support for disabling GCS + at runtime this should be done with great care. + +* GCS memory access faults are reported as normal memory access faults. + +* GCS specific errors (those reported with EC 0x2d) will be reported as + SIGSEGV with a si_code of SEGV_CPERR (control protection error). + +* GCS is supported only for AArch64. + +* On systems where GCS is supported GCSPR_EL0 is always readable by EL0 + regardless of the GCS configuration for the thread. + +* The architecture supports enabling GCS without verifying that return values + in LR match those in the GCS, the LR will be ignored. This is not supported + by Linux. + + + +2. Enabling and disabling Guarded Control Stacks +------------------------------------------------- + +* GCS is enabled and disabled for a thread via the PR_SET_SHADOW_STACK_STATUS + prctl(), this takes a single flags argument specifying which GCS features + should be used. + +* When set PR_SHADOW_STACK_ENABLE flag allocates a Guarded Control Stack + and enables GCS for the thread, enabling the functionality controlled by + GCSCRE0_EL1.{nTR, RVCHKEN, PCRSEL}. + +* When set the PR_SHADOW_STACK_PUSH flag enables the functionality controlled + by GCSCRE0_EL1.PUSHMEn, allowing explicit GCS pushes. + +* When set the PR_SHADOW_STACK_WRITE flag enables the functionality controlled + by GCSCRE0_EL1.STREn, allowing explicit stores to the Guarded Control Stack. + +* Any unknown flags will cause PR_SET_SHADOW_STACK_STATUS to return -EINVAL. + +* PR_LOCK_SHADOW_STACK_STATUS is passed a bitmask of features with the same + values as used for PR_SET_SHADOW_STACK_STATUS. Any future changes to the + status of the specified GCS mode bits will be rejected. + +* PR_LOCK_SHADOW_STACK_STATUS allows any bit to be locked, this allows + userspace to prevent changes to any future features. + +* There is no support for a process to remove a lock that has been set for + it. + +* PR_SET_SHADOW_STACK_STATUS and PR_LOCK_SHADOW_STACK_STATUS affect only the + thread that called them, any other running threads will be unaffected. + +* New threads inherit the GCS configuration of the thread that created them. + +* GCS is disabled on exec(). + +* The current GCS configuration for a thread may be read with the + PR_GET_SHADOW_STACK_STATUS prctl(), this returns the same flags that + are passed to PR_SET_SHADOW_STACK_STATUS. + +* If GCS is disabled for a thread after having previously been enabled then + the stack will remain allocated for the lifetime of the thread. At present + any attempt to reenable GCS for the thread will be rejected, this may be + revisited in future. + +* It should be noted that since enabling GCS will result in GCS becoming + active immediately it is not normally possible to return from the function + that invoked the prctl() that enabled GCS. It is expected that the normal + usage will be that GCS is enabled very early in execution of a program. + + + +3. Allocation of Guarded Control Stacks +---------------------------------------- + +* When GCS is enabled for a thread a new Guarded Control Stack will be + allocated for it of half the standard stack size or 2 gigabytes, + whichever is smaller. + +* When a new thread is created by a thread which has GCS enabled then a + new Guarded Control Stack will be allocated for the new thread with + half the size of the standard stack. + +* When a stack is allocated by enabling GCS or during thread creation then + the top 8 bytes of the stack will be initialised to 0 and GCSPR_EL0 will + be set to point to the address of this 0 value, this can be used to + detect the top of the stack. + +* Additional Guarded Control Stacks can be allocated using the + map_shadow_stack() system call. + +* Stacks allocated using map_shadow_stack() can optionally have an end of + stack marker and cap placed at the top of the stack. If the flag + SHADOW_STACK_SET_TOKEN is specified a cap will be placed on the stack, + if SHADOW_STACK_SET_MARKER is not specified the cap will be the top 8 + bytes of the stack and if it is specified then the cap will be the next + 8 bytes. While specifying just SHADOW_STACK_SET_MARKER by itself is + valid since the marker is all bits 0 it has no observable effect. + +* Stacks allocated using map_shadow_stack() must have a size which is a + multiple of 8 bytes larger than 8 bytes and must be 8 bytes aligned. + +* An address can be specified to map_shadow_stack(), if one is provided then + it must be aligned to a page boundary. + +* When a thread is freed the Guarded Control Stack initially allocated for + that thread will be freed. Note carefully that if the stack has been + switched this may not be the stack currently in use by the thread. + + +4. Signal handling +-------------------- + +* A new signal frame record gcs_context encodes the current GCS mode and + pointer for the interrupted context on signal delivery. This will always + be present on systems that support GCS. + +* The record contains a flag field which reports the current GCS configuration + for the interrupted context as PR_GET_SHADOW_STACK_STATUS would. + +* The signal handler is run with the same GCS configuration as the interrupted + context. + +* When GCS is enabled for the interrupted thread a signal handling specific + GCS cap token will be written to the GCS, this is an architectural GCS cap + with the token type (bits 0..11) all clear. The GCSPR_EL0 reported in the + signal frame will point to this cap token. + +* The signal handler will use the same GCS as the interrupted context. + +* When GCS is enabled on signal entry a frame with the address of the signal + return handler will be pushed onto the GCS, allowing return from the signal + handler via RET as normal. This will not be reported in the gcs_context in + the signal frame. + + +5. Signal return +----------------- + +When returning from a signal handler: + +* If there is a gcs_context record in the signal frame then the GCS flags + and GCSPR_EL0 will be restored from that context prior to further + validation. + +* If there is no gcs_context record in the signal frame then the GCS + configuration will be unchanged. + +* If GCS is enabled on return from a signal handler then GCSPR_EL0 must + point to a valid GCS signal cap record, this will be popped from the + GCS prior to signal return. + +* If the GCS configuration is locked when returning from a signal then any + attempt to change the GCS configuration will be treated as an error. This + is true even if GCS was not enabled prior to signal entry. + +* GCS may be disabled via signal return but any attempt to enable GCS via + signal return will be rejected. + + +6. ptrace extensions +--------------------- + +* A new regset NT_ARM_GCS is defined for use with PTRACE_GETREGSET and + PTRACE_SETREGSET. + +* Due to the complexity surrounding allocation and deallocation of stacks and + lack of practical application it is not possible to enable GCS via ptrace. + GCS may be disabled via the ptrace interface. + +* Other GCS modes may be configured via ptrace. + +* Configuration via ptrace ignores locking of GCS mode bits. + + +7. ELF coredump extensions +--------------------------- + +* NT_ARM_GCS notes will be added to each coredump for each thread of the + dumped process. The contents will be equivalent to the data that would + have been read if a PTRACE_GETREGSET of the corresponding type were + executed for each thread when the coredump was generated. + + + +8. /proc extensions +-------------------- + +* Guarded Control Stack pages will include "ss" in their VmFlags in + /proc//smaps. diff --git a/Documentation/arch/arm64/index.rst b/Documentation/arch/arm64/index.rst index 78544de0a8a9..056f6a739d25 100644 --- a/Documentation/arch/arm64/index.rst +++ b/Documentation/arch/arm64/index.rst @@ -15,6 +15,7 @@ ARM64 Architecture cpu-feature-registers cpu-hotplug elf_hwcaps + gcs hugetlbpage kdump legacy_instructions