@@ -28,5 +28,6 @@
/* ARCH_CET_ features bits */
#define CET_SHSTK (1ULL << 0)
+#define CET_WRSS (1ULL << 1)
#endif /* _ASM_X86_PRCTL_H */
@@ -364,6 +364,35 @@ void shstk_free(struct task_struct *tsk)
unmap_shadow_stack(shstk->base, shstk->size);
}
+static int wrss_control(bool enable)
+{
+ 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(CET_SHSTK))
+ return -EPERM;
+
+ /* Already enabled/disabled? */
+ if (features_enabled(CET_WRSS) == enable)
+ return 0;
+
+ fpregs_lock_and_load();
+ if (enable) {
+ set_clr_bits_msrl(MSR_IA32_U_CET, CET_WRSS_EN, 0);
+ features_set(CET_WRSS);
+ } else {
+ set_clr_bits_msrl(MSR_IA32_U_CET, 0, CET_WRSS_EN);
+ features_clr(CET_WRSS);
+ }
+ fpregs_unlock();
+
+ return 0;
+}
static int shstk_disable(void)
{
@@ -376,12 +405,12 @@ static int shstk_disable(void)
fpregs_lock_and_load();
/* Disable WRSS too when disabling shadow stack */
- set_clr_bits_msrl(MSR_IA32_U_CET, 0, CET_SHSTK_EN);
+ set_clr_bits_msrl(MSR_IA32_U_CET, 0, CET_SHSTK_EN | CET_WRSS_EN);
wrmsrl(MSR_IA32_PL3_SSP, 0);
fpregs_unlock();
shstk_free(current);
- features_clr(CET_SHSTK);
+ features_clr(CET_SHSTK | CET_WRSS);
return 0;
}