nospec: Allow getting/setting on non-current task
Adjust arch_prctl_get/set_spec_ctrl() to operate on tasks other than current. This is needed both for /proc/$pid/status queries and for seccomp (since thread-syncing can trigger seccomp in non-current threads). Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:

committed by
Thomas Gleixner

parent
a73ec77ee1
commit
7bbf1373e2
@@ -530,31 +530,35 @@ static void ssb_select_mitigation()
|
||||
|
||||
#undef pr_fmt
|
||||
|
||||
static int ssb_prctl_set(unsigned long ctrl)
|
||||
static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
|
||||
{
|
||||
bool rds = !!test_tsk_thread_flag(current, TIF_RDS);
|
||||
bool rds = !!test_tsk_thread_flag(task, TIF_RDS);
|
||||
|
||||
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL)
|
||||
return -ENXIO;
|
||||
|
||||
if (ctrl == PR_SPEC_ENABLE)
|
||||
clear_tsk_thread_flag(current, TIF_RDS);
|
||||
clear_tsk_thread_flag(task, TIF_RDS);
|
||||
else
|
||||
set_tsk_thread_flag(current, TIF_RDS);
|
||||
set_tsk_thread_flag(task, TIF_RDS);
|
||||
|
||||
if (rds != !!test_tsk_thread_flag(current, TIF_RDS))
|
||||
/*
|
||||
* If being set on non-current task, delay setting the CPU
|
||||
* mitigation until it is next scheduled.
|
||||
*/
|
||||
if (task == current && rds != !!test_tsk_thread_flag(task, TIF_RDS))
|
||||
speculative_store_bypass_update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssb_prctl_get(void)
|
||||
static int ssb_prctl_get(struct task_struct *task)
|
||||
{
|
||||
switch (ssb_mode) {
|
||||
case SPEC_STORE_BYPASS_DISABLE:
|
||||
return PR_SPEC_DISABLE;
|
||||
case SPEC_STORE_BYPASS_PRCTL:
|
||||
if (test_tsk_thread_flag(current, TIF_RDS))
|
||||
if (test_tsk_thread_flag(task, TIF_RDS))
|
||||
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
|
||||
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
|
||||
default:
|
||||
@@ -564,24 +568,25 @@ static int ssb_prctl_get(void)
|
||||
}
|
||||
}
|
||||
|
||||
int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
|
||||
int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
|
||||
unsigned long ctrl)
|
||||
{
|
||||
if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE)
|
||||
return -ERANGE;
|
||||
|
||||
switch (which) {
|
||||
case PR_SPEC_STORE_BYPASS:
|
||||
return ssb_prctl_set(ctrl);
|
||||
return ssb_prctl_set(task, ctrl);
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
int arch_prctl_spec_ctrl_get(unsigned long which)
|
||||
int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
|
||||
{
|
||||
switch (which) {
|
||||
case PR_SPEC_STORE_BYPASS:
|
||||
return ssb_prctl_get();
|
||||
return ssb_prctl_get(task);
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
Reference in New Issue
Block a user