diff options
author | Will Deacon <will@kernel.org> | 2020-09-28 16:03:00 +0300 |
---|---|---|
committer | Will Deacon <will@kernel.org> | 2020-09-29 18:08:17 +0300 |
commit | 780c083a8f840ca9162c7a4090ff5e10d15152a2 (patch) | |
tree | 1af4d1abd14d9882e5ac4cced04406f9ee8a022c /arch/arm64/kernel/proton-pack.c | |
parent | 5c8b0cbd9d6bac5f40943b5a7d8eac8cb86cbe7f (diff) | |
download | linux-780c083a8f840ca9162c7a4090ff5e10d15152a2.tar.xz |
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>
Diffstat (limited to 'arch/arm64/kernel/proton-pack.c')
-rw-r--r-- | arch/arm64/kernel/proton-pack.c | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c index 16c9a095a746..68b710f1b43f 100644 --- a/arch/arm64/kernel/proton-pack.c +++ b/arch/arm64/kernel/proton-pack.c @@ -660,6 +660,20 @@ void spectre_v4_enable_task_mitigation(struct task_struct *tsk) * prctl() may be necessary even when PSTATE.SSBS can be toggled directly * from userspace. */ +static void ssbd_prctl_enable_mitigation(struct task_struct *task) +{ + task_clear_spec_ssb_noexec(task); + task_set_spec_ssb_disable(task); + set_tsk_thread_flag(task, TIF_SSBD); +} + +static void ssbd_prctl_disable_mitigation(struct task_struct *task) +{ + task_clear_spec_ssb_noexec(task); + task_clear_spec_ssb_disable(task); + clear_tsk_thread_flag(task, TIF_SSBD); +} + static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) { switch (ctrl) { @@ -679,8 +693,7 @@ static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) if (spectre_v4_mitigations_on()) return -EPERM; - task_clear_spec_ssb_disable(task); - clear_tsk_thread_flag(task, TIF_SSBD); + ssbd_prctl_disable_mitigation(task); break; case PR_SPEC_FORCE_DISABLE: /* Force disable speculation: force enable mitigation */ @@ -699,8 +712,22 @@ static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) if (spectre_v4_mitigations_off()) return -EPERM; - task_set_spec_ssb_disable(task); - set_tsk_thread_flag(task, TIF_SSBD); + ssbd_prctl_enable_mitigation(task); + break; + case PR_SPEC_DISABLE_NOEXEC: + /* Disable speculation until execve(): enable mitigation */ + /* + * If the mitigation state is forced one way or the other, then + * we must fail now before we try to toggle it on execve(). + */ + if (task_spec_ssb_force_disable(task) || + spectre_v4_mitigations_off() || + spectre_v4_mitigations_on()) { + return -EPERM; + } + + ssbd_prctl_enable_mitigation(task); + task_set_spec_ssb_noexec(task); break; default: return -ERANGE; @@ -745,6 +772,9 @@ static int ssbd_prctl_get(struct task_struct *task) if (task_spec_ssb_force_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; + if (task_spec_ssb_noexec(task)) + return PR_SPEC_PRCTL | PR_SPEC_DISABLE_NOEXEC; + if (task_spec_ssb_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_DISABLE; |