Skip to content

Commit 780c083

Browse files
committed
arm64: Add support for PR_SPEC_DISABLE_NOEXEC prctl() option
The PR_SPEC_DISABLE_NOEXEC option to the PR_SPEC_STORE_BYPASS prctl() allows the SSB mitigation to be enabled only until the next execve(), at which point the state will revert back to PR_SPEC_ENABLE and the mitigation will be disabled. Add support for PR_SPEC_DISABLE_NOEXEC on arm64. Reported-by: Anthony Steinhauser <asteinhauser@google.com> Signed-off-by: Will Deacon <will@kernel.org>
1 parent 5c8b0cb commit 780c083

2 files changed

Lines changed: 40 additions & 4 deletions

File tree

arch/arm64/kernel/process.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/lockdep.h>
2222
#include <linux/mman.h>
2323
#include <linux/mm.h>
24+
#include <linux/nospec.h>
2425
#include <linux/stddef.h>
2526
#include <linux/sysctl.h>
2627
#include <linux/unistd.h>
@@ -609,6 +610,11 @@ void arch_setup_new_exec(void)
609610
current->mm->context.flags = is_compat_task() ? MMCF_AARCH32 : 0;
610611

611612
ptrauth_thread_init_user(current);
613+
614+
if (task_spec_ssb_noexec(current)) {
615+
arch_prctl_spec_ctrl_set(current, PR_SPEC_STORE_BYPASS,
616+
PR_SPEC_ENABLE);
617+
}
612618
}
613619

614620
#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI

arch/arm64/kernel/proton-pack.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,20 @@ void spectre_v4_enable_task_mitigation(struct task_struct *tsk)
660660
* prctl() may be necessary even when PSTATE.SSBS can be toggled directly
661661
* from userspace.
662662
*/
663+
static void ssbd_prctl_enable_mitigation(struct task_struct *task)
664+
{
665+
task_clear_spec_ssb_noexec(task);
666+
task_set_spec_ssb_disable(task);
667+
set_tsk_thread_flag(task, TIF_SSBD);
668+
}
669+
670+
static void ssbd_prctl_disable_mitigation(struct task_struct *task)
671+
{
672+
task_clear_spec_ssb_noexec(task);
673+
task_clear_spec_ssb_disable(task);
674+
clear_tsk_thread_flag(task, TIF_SSBD);
675+
}
676+
663677
static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
664678
{
665679
switch (ctrl) {
@@ -679,8 +693,7 @@ static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
679693
if (spectre_v4_mitigations_on())
680694
return -EPERM;
681695

682-
task_clear_spec_ssb_disable(task);
683-
clear_tsk_thread_flag(task, TIF_SSBD);
696+
ssbd_prctl_disable_mitigation(task);
684697
break;
685698
case PR_SPEC_FORCE_DISABLE:
686699
/* Force disable speculation: force enable mitigation */
@@ -699,8 +712,22 @@ static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
699712
if (spectre_v4_mitigations_off())
700713
return -EPERM;
701714

702-
task_set_spec_ssb_disable(task);
703-
set_tsk_thread_flag(task, TIF_SSBD);
715+
ssbd_prctl_enable_mitigation(task);
716+
break;
717+
case PR_SPEC_DISABLE_NOEXEC:
718+
/* Disable speculation until execve(): enable mitigation */
719+
/*
720+
* If the mitigation state is forced one way or the other, then
721+
* we must fail now before we try to toggle it on execve().
722+
*/
723+
if (task_spec_ssb_force_disable(task) ||
724+
spectre_v4_mitigations_off() ||
725+
spectre_v4_mitigations_on()) {
726+
return -EPERM;
727+
}
728+
729+
ssbd_prctl_enable_mitigation(task);
730+
task_set_spec_ssb_noexec(task);
704731
break;
705732
default:
706733
return -ERANGE;
@@ -745,6 +772,9 @@ static int ssbd_prctl_get(struct task_struct *task)
745772
if (task_spec_ssb_force_disable(task))
746773
return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
747774

775+
if (task_spec_ssb_noexec(task))
776+
return PR_SPEC_PRCTL | PR_SPEC_DISABLE_NOEXEC;
777+
748778
if (task_spec_ssb_disable(task))
749779
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
750780

0 commit comments

Comments
 (0)