From: Bill Roberts <bill.roberts@arm.com>
To: "H. Peter Anvin" <hpa@zytor.com>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
Ingo Molnar <mingo@redhat.com>,
rick.p.edgecombe@intel.com, Shuah Khan <shuah@kernel.org>,
Thomas Gleixner <tglx@kernel.org>,
x86@kernel.org
Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org,
Bill Roberts <bill.roberts@arm.com>
Subject: [PATCH v5 4/6] x86/shstk: support via prctl
Date: Mon, 9 Nov 2026 12:27:56 -0600 [thread overview]
Message-ID: <20261109182758.252223-5-bill.roberts@arm.com> (raw)
In-Reply-To: <20261109182758.252223-1-bill.roberts@arm.com>
On x86, userspace shadow stack state is managed through the
architecture-specific arch_prctl() interface. Other architectures,
including arm64 and RISC-V, use the generic shadow stack prctl()
interface instead.
This difference requires userspace runtimes, toolchains, and libc
implementations to support architecture-specific interfaces for
managing shadow stack state. It also complicates efforts to provide
consistent LSM mediation of control-flow integrity state changes.
Implement the generic PR_SET_SHADOW_STACK_STATUS,
PR_GET_SHADOW_STACK_STATUS, and PR_LOCK_SHADOW_STACK_STATUS
operations on x86 using the existing shadow stack helpers.
Retain the arch_prctl() interface for compatibility with
existing userspace.
Unlike arch_prctl(), which enables or disables individual features,
PR_SET_SHADOW_STACK_STATUS specifies the desired state of the
supported feature set. Translate this state into the corresponding
shadow stack and WRSS operations, changing only features whose
state differs from the requested state.
Avoid unnecessary operations because the underlying shadow stack
helpers check locked bits before checking whether the requested
feature state is already satisfied. If enabling or disabling WRSS
fails after enabling shadow stack, restore the original shadow
stack state.
Disabling shadow stack also disables WRSS, so do not disable WRSS
separately when clearing the entire feature set. This avoids
allowing a locked WRSS feature to prevent shadow stack disablement.
Reject unsupported feature combinations and use the existing
shadow stack helpers to enforce feature locking.
Signed-off-by: Bill Roberts <bill.roberts@arm.com>
---
arch/x86/kernel/shstk.c | 80 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c
index eb690ba90180..6dfe310634b0 100644
--- a/arch/x86/kernel/shstk.c
+++ b/arch/x86/kernel/shstk.c
@@ -18,6 +18,7 @@
#include <linux/sizes.h>
#include <linux/user.h>
#include <linux/syscalls.h>
+#include <linux/prctl.h>
#include <asm/msr.h>
#include <asm/fpu/xstate.h>
#include <asm/fpu/types.h>
@@ -630,3 +631,82 @@ bool shstk_is_enabled(void)
{
return features_enabled(ARCH_SHSTK_SHSTK);
}
+
+/* Handles the generic prctl interface for PR_SET_SHADOW_STACK_STATUS and its feature bits */
+int arch_set_shadow_stack_status(struct task_struct *t, unsigned long status)
+{
+ int rc;
+ bool shstk_was_enabled = features_enabled(ARCH_SHSTK_SHSTK);
+
+ /*
+ * Enable/disable the full feature set and preserve the original state for rollback.
+ * Only act on changed features, since shstk_prctl() checks locked bits before checking
+ * feature status.
+ */
+ switch (status) {
+ case 0:
+ /*
+ * Do not explicitly disable WRSS. Disabling shadow stack also
+ * disables WRSS, and a locked WRSS must not prevent this.
+ */
+ return shstk_was_enabled ?
+ shstk_prctl(t, ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK) : 0;
+
+ case PR_SHADOW_STACK_ENABLE:
+ if (!shstk_was_enabled) {
+ rc = shstk_prctl(t, ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK);
+ if (rc)
+ return rc;
+ }
+
+ if (features_enabled(ARCH_SHSTK_WRSS)) {
+ rc = shstk_prctl(t, ARCH_SHSTK_DISABLE, ARCH_SHSTK_WRSS);
+ if (rc && !shstk_was_enabled)
+ shstk_prctl(t, ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK);
+ return rc;
+ }
+
+ return 0;
+
+ case PR_SHADOW_STACK_ENABLE|PR_SHADOW_STACK_WRITE:
+ if (!shstk_was_enabled) {
+ rc = shstk_prctl(t, ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK);
+ if (rc)
+ return rc;
+ }
+
+ if (!features_enabled(ARCH_SHSTK_WRSS)) {
+ rc = shstk_prctl(t, ARCH_SHSTK_ENABLE, ARCH_SHSTK_WRSS);
+ if (rc && !shstk_was_enabled)
+ shstk_prctl(t, ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK);
+
+ return rc;
+ }
+
+ return 0;
+
+ /*
+ * Unknown bit mapping, unsupported PR_SHADOW_STACK_PUSH or *only*
+ * PR_SHADOW_STACK_WRITE.
+ */
+ default:
+ return -EINVAL;
+ }
+}
+
+/* Handles the generic prctl interface for PR_LOCK_SHADOW_STACK_STATUS and its feature bits */
+int arch_lock_shadow_stack_status(struct task_struct *t, unsigned long status)
+{
+ return shstk_prctl(t, ARCH_SHSTK_LOCK, status);
+}
+
+/*
+ * We assume the prctl() feature bits line up with the arch_prctl() specific ones. If not,
+ * the flags returned via arch_get_shadow_stack_status will be mapped wrong.
+ */
+static_assert(PR_SHADOW_STACK_ENABLE == ARCH_SHSTK_SHSTK);
+static_assert(PR_SHADOW_STACK_WRITE == ARCH_SHSTK_WRSS);
+int arch_get_shadow_stack_status(struct task_struct *t, unsigned long __user *status)
+{
+ return shstk_prctl(t, ARCH_SHSTK_STATUS, (unsigned long)status);
+}
--
2.55.0
next prev parent reply other threads:[~2026-11-09 18:28 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 18:27 [PATCH v5 0/6] x86: Support shstk " Bill Roberts
2026-11-09 18:27 ` [PATCH v5 1/6] selftests/x86: fix Makefile dependencies Bill Roberts
2026-11-09 18:27 ` [PATCH v5 2/6] selftests/x86: fix fork bug Bill Roberts
2026-11-09 18:27 ` [PATCH v5 3/6] selftests/x86: add shadow stack lock test Bill Roberts
2026-11-09 18:27 ` Bill Roberts [this message]
2026-11-09 18:27 ` [PATCH v5 5/6] selftests/x86: support header files in extra-files Bill Roberts
2026-11-09 18:27 ` [PATCH v5 6/6] selftests/x86: add generic prctl shadow stack test Bill Roberts
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261109182758.252223-5-bill.roberts@arm.com \
--to=bill.roberts@arm.com \
--cc=bp@alien8.de \
--cc=bpf@vger.kernel.org \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=rick.p.edgecombe@intel.com \
--cc=shuah@kernel.org \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®