Skip to content

Commit 1d62c65

Browse files
rpedgecohansendc
authored andcommitted
x86/shstk: Support WRSS for userspace
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 <[email protected]> Signed-off-by: Dave Hansen <[email protected]> Reviewed-by: Borislav Petkov (AMD) <[email protected]> Reviewed-by: Kees Cook <[email protected]> Acked-by: Mike Rapoport (IBM) <[email protected]> Tested-by: Pengfei Xu <[email protected]> Tested-by: John Allen <[email protected]> Tested-by: Kees Cook <[email protected]> Link: https://lore.kernel.org/all/20230613001108.3040476-36-rick.p.edgecombe%40intel.com
1 parent c35559f commit 1d62c65

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

arch/x86/include/uapi/asm/prctl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@
3636

3737
/* ARCH_SHSTK_ features bits */
3838
#define ARCH_SHSTK_SHSTK (1ULL << 0)
39+
#define ARCH_SHSTK_WRSS (1ULL << 1)
3940

4041
#endif /* _ASM_X86_PRCTL_H */

arch/x86/kernel/shstk.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,47 @@ void shstk_free(struct task_struct *tsk)
390390
unmap_shadow_stack(shstk->base, shstk->size);
391391
}
392392

393+
static int wrss_control(bool enable)
394+
{
395+
u64 msrval;
396+
397+
if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK))
398+
return -EOPNOTSUPP;
399+
400+
/*
401+
* Only enable WRSS if shadow stack is enabled. If shadow stack is not
402+
* enabled, WRSS will already be disabled, so don't bother clearing it
403+
* when disabling.
404+
*/
405+
if (!features_enabled(ARCH_SHSTK_SHSTK))
406+
return -EPERM;
407+
408+
/* Already enabled/disabled? */
409+
if (features_enabled(ARCH_SHSTK_WRSS) == enable)
410+
return 0;
411+
412+
fpregs_lock_and_load();
413+
rdmsrl(MSR_IA32_U_CET, msrval);
414+
415+
if (enable) {
416+
features_set(ARCH_SHSTK_WRSS);
417+
msrval |= CET_WRSS_EN;
418+
} else {
419+
features_clr(ARCH_SHSTK_WRSS);
420+
if (!(msrval & CET_WRSS_EN))
421+
goto unlock;
422+
423+
msrval &= ~CET_WRSS_EN;
424+
}
425+
426+
wrmsrl(MSR_IA32_U_CET, msrval);
427+
428+
unlock:
429+
fpregs_unlock();
430+
431+
return 0;
432+
}
433+
393434
static int shstk_disable(void)
394435
{
395436
if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK))
@@ -406,7 +447,7 @@ static int shstk_disable(void)
406447
fpregs_unlock();
407448

408449
shstk_free(current);
409-
features_clr(ARCH_SHSTK_SHSTK);
450+
features_clr(ARCH_SHSTK_SHSTK | ARCH_SHSTK_WRSS);
410451

411452
return 0;
412453
}

0 commit comments

Comments
 (0)