Skip to content

Commit

Permalink
x86/shstk: Support WRSS for userspace
Browse files Browse the repository at this point in the history
For the current shadow stack implementation, shadow stacks contents can't
easily be provisioned with arbitrary data. This property helps apps
protect themselves better, but also restricts any potential apps that may
want to do exotic things at the expense of a little security.

The x86 shadow stack feature introduces a new instruction, WRSS, which
can be enabled to write directly to shadow stack memory from userspace.
Allow it to get enabled via the prctl interface.

Only enable the userspace WRSS instruction, which allows writes to
userspace shadow stacks from userspace. Do not allow it to be enabled
independently of shadow stack, as HW does not support using WRSS when
shadow stack is disabled.

>From a fault handler perspective, WRSS will behave very similar to WRUSS,
which is treated like a user access from a #PF err code perspective.

Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Mike Rapoport (IBM) <rppt@kernel.org>
Tested-by: Pengfei Xu <pengfei.xu@intel.com>
Tested-by: John Allen <john.allen@amd.com>
Tested-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/all/20230613001108.3040476-36-rick.p.edgecombe%40intel.com
  • Loading branch information
Rick Edgecombe authored and Dave Hansen committed Aug 2, 2023
1 parent c35559f commit 1d62c65
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
1 change: 1 addition & 0 deletions arch/x86/include/uapi/asm/prctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@

/* ARCH_SHSTK_ features bits */
#define ARCH_SHSTK_SHSTK (1ULL << 0)
#define ARCH_SHSTK_WRSS (1ULL << 1)

#endif /* _ASM_X86_PRCTL_H */
43 changes: 42 additions & 1 deletion arch/x86/kernel/shstk.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,47 @@ void shstk_free(struct task_struct *tsk)
unmap_shadow_stack(shstk->base, shstk->size);
}

static int wrss_control(bool enable)
{
u64 msrval;

if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK))
return -EOPNOTSUPP;

/*
* Only enable WRSS if shadow stack is enabled. If shadow stack is not
* enabled, WRSS will already be disabled, so don't bother clearing it
* when disabling.
*/
if (!features_enabled(ARCH_SHSTK_SHSTK))
return -EPERM;

/* Already enabled/disabled? */
if (features_enabled(ARCH_SHSTK_WRSS) == enable)
return 0;

fpregs_lock_and_load();
rdmsrl(MSR_IA32_U_CET, msrval);

if (enable) {
features_set(ARCH_SHSTK_WRSS);
msrval |= CET_WRSS_EN;
} else {
features_clr(ARCH_SHSTK_WRSS);
if (!(msrval & CET_WRSS_EN))
goto unlock;

msrval &= ~CET_WRSS_EN;
}

wrmsrl(MSR_IA32_U_CET, msrval);

unlock:
fpregs_unlock();

return 0;
}

static int shstk_disable(void)
{
if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK))
Expand All @@ -406,7 +447,7 @@ static int shstk_disable(void)
fpregs_unlock();

shstk_free(current);
features_clr(ARCH_SHSTK_SHSTK);
features_clr(ARCH_SHSTK_SHSTK | ARCH_SHSTK_WRSS);

return 0;
}
Expand Down

0 comments on commit 1d62c65

Please sign in to comment.