All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Bill Roberts" <bill.roberts@arm.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH v5 4/6] x86/shstk: support via prctl
Date: Mon, 09 Nov 2026 18:52:41 +0000	[thread overview]
Message-ID: <sashiko-outbox-205446@kernel.org> (raw)
In-Reply-To: <20261109182758.252223-5-bill.roberts@arm.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] x86/shstk: missing 32-bit check in prctl status helpers
  corrupts user stack
- [Medium] x86/shstk: missing X86_FEATURE_USER_SHSTK check in shadow
  stack prctl helpers
- [Low] x86/shstk: unreachable rollback path in
  arch_set_shadow_stack_status()
--

commit 9a3ff7cedb6830c75ef0c0aa6dd108c66cfde589
Author: Bill Roberts <bill.roberts@arm.com>

x86/shstk: support via prctl

This commit implements the generic PR_SET_SHADOW_STACK_STATUS,
PR_GET_SHADOW_STACK_STATUS, and PR_LOCK_SHADOW_STACK_STATUS prctl()
operations on x86 using the existing shadow stack helpers.

> diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c
> index eb690ba90180c..6dfe310634b02 100644
> --- a/arch/x86/kernel/shstk.c
> +++ b/arch/x86/kernel/shstk.c

[ ... ]

> @@ -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;

[Severity: Medium]
Does returning 0 here when shstk_was_enabled is false, and delegating
arch_lock_shadow_stack_status() and arch_get_shadow_stack_status() to
shstk_prctl() without checking cpu_feature_enabled(X86_FEATURE_USER_SHSTK),
cause these prctl() calls to succeed on CPUs without shadow stack support?

shstk_disable(), shstk_setup(), and wrss_control() all check
!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) and return -EOPNOTSUPP, but
ARCH_SHSTK_STATUS and ARCH_SHSTK_LOCK in shstk_prctl() do not, and case 0
here bypasses shstk_disable() when shadow stack is not enabled.  On systems
without X86_FEATURE_USER_SHSTK (or booted with nousershstk),
PR_GET_SHADOW_STACK_STATUS, PR_LOCK_SHADOW_STACK_STATUS, and
PR_SET_SHADOW_STACK_STATUS(0) return 0 instead of an error, misleading
userspace probing for shadow stack support.

> +
> +	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;
> +		}

[Severity: Low]
Can the rollback check (if (rc && !shstk_was_enabled)) ever be reached?

wrss_control(true) requires ARCH_SHSTK_SHSTK to be enabled, shstk_disable()
clears both ARCH_SHSTK_SHSTK and ARCH_SHSTK_WRSS, and shstk_setup() only
enables ARCH_SHSTK_SHSTK.  Whenever features_enabled(ARCH_SHSTK_WRSS) is
true here, shstk_was_enabled is already true.

[ ... ]

> +/* 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);
> +}

[Severity: High]
Can a 32-bit compat or x32 caller corrupt 4 bytes past its status variable
via PR_GET_SHADOW_STACK_STATUS?

Previously, shstk_prctl() was only reachable from sys_arch_prctl(), which
rejects in_ia32_syscall() upfront, so shstk_prctl() only checks
in_ia32_syscall() inside shstk_setup().  Because sys_prctl() is wired to
32-bit and x32 syscalls, calling prctl(PR_GET_SHADOW_STACK_STATUS, &status,
0, 0, 0) from 32-bit or x32 userspace reaches shstk_prctl(ARCH_SHSTK_STATUS)
and executes an 8-byte put_user() into a 4-byte userspace unsigned long:

arch/x86/kernel/shstk.c:shstk_prctl() {
	if (option == ARCH_SHSTK_STATUS) {
		return put_user(task->thread.features, (unsigned long __user *)arg2);
	}
    ...
}

32-bit IA32 callers can also lock features via
arch_lock_shadow_stack_status() and call arch_set_shadow_stack_status() to
disable shadow stack, toggle WRSS, or get 0 back for status == 0 instead of
-EINVAL.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261109182758.252223-1-bill.roberts@arm.com?part=4

  reply	other threads:[~2026-11-09 18:52 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 18:27 [PATCH v5 0/6] x86: Support shstk via prctl 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:36   ` sashiko-bot
2026-11-09 18:27 ` [PATCH v5 3/6] selftests/x86: add shadow stack lock test Bill Roberts
2026-11-09 18:35   ` sashiko-bot
2026-11-09 18:27 ` [PATCH v5 4/6] x86/shstk: support via prctl Bill Roberts
2026-11-09 18:52   ` sashiko-bot [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
2026-11-09 18:46   ` sashiko-bot

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=sashiko-outbox-205446@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bill.roberts@arm.com \
    --cc=bpf@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.