mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
nospec: Allow getting/setting on non-current task
commit 7bbf1373e228840bb0295a2ca26d548ef37f448e upstream 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d855391162
commit
7d1254a148
@ -530,31 +530,35 @@ static void ssb_select_mitigation()
|
|||||||
|
|
||||||
#undef pr_fmt
|
#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)
|
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
if (ctrl == PR_SPEC_ENABLE)
|
if (ctrl == PR_SPEC_ENABLE)
|
||||||
clear_tsk_thread_flag(current, TIF_RDS);
|
clear_tsk_thread_flag(task, TIF_RDS);
|
||||||
else
|
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();
|
speculative_store_bypass_update();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ssb_prctl_get(void)
|
static int ssb_prctl_get(struct task_struct *task)
|
||||||
{
|
{
|
||||||
switch (ssb_mode) {
|
switch (ssb_mode) {
|
||||||
case SPEC_STORE_BYPASS_DISABLE:
|
case SPEC_STORE_BYPASS_DISABLE:
|
||||||
return PR_SPEC_DISABLE;
|
return PR_SPEC_DISABLE;
|
||||||
case SPEC_STORE_BYPASS_PRCTL:
|
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_DISABLE;
|
||||||
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
|
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
|
||||||
default:
|
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)
|
if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case PR_SPEC_STORE_BYPASS:
|
case PR_SPEC_STORE_BYPASS:
|
||||||
return ssb_prctl_set(ctrl);
|
return ssb_prctl_set(task, ctrl);
|
||||||
default:
|
default:
|
||||||
return -ENODEV;
|
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) {
|
switch (which) {
|
||||||
case PR_SPEC_STORE_BYPASS:
|
case PR_SPEC_STORE_BYPASS:
|
||||||
return ssb_prctl_get();
|
return ssb_prctl_get(task);
|
||||||
default:
|
default:
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#define _LINUX_NOSPEC_H
|
#define _LINUX_NOSPEC_H
|
||||||
#include <asm/barrier.h>
|
#include <asm/barrier.h>
|
||||||
|
|
||||||
|
struct task_struct;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
|
* array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
|
||||||
* @index: array element index
|
* @index: array element index
|
||||||
@ -57,7 +59,8 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
|
|||||||
})
|
})
|
||||||
|
|
||||||
/* Speculation control prctl */
|
/* Speculation control prctl */
|
||||||
int arch_prctl_spec_ctrl_get(unsigned long which);
|
int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which);
|
||||||
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);
|
||||||
|
|
||||||
#endif /* _LINUX_NOSPEC_H */
|
#endif /* _LINUX_NOSPEC_H */
|
||||||
|
@ -2186,12 +2186,13 @@ static int propagate_has_child_subreaper(struct task_struct *p, void *data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __weak arch_prctl_spec_ctrl_get(unsigned long which)
|
int __weak arch_prctl_spec_ctrl_get(struct task_struct *t, unsigned long which)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __weak arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
|
int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which,
|
||||||
|
unsigned long ctrl)
|
||||||
{
|
{
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -2401,12 +2402,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
|
|||||||
case PR_GET_SPECULATION_CTRL:
|
case PR_GET_SPECULATION_CTRL:
|
||||||
if (arg3 || arg4 || arg5)
|
if (arg3 || arg4 || arg5)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
error = arch_prctl_spec_ctrl_get(arg2);
|
error = arch_prctl_spec_ctrl_get(me, arg2);
|
||||||
break;
|
break;
|
||||||
case PR_SET_SPECULATION_CTRL:
|
case PR_SET_SPECULATION_CTRL:
|
||||||
if (arg4 || arg5)
|
if (arg4 || arg5)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
error = arch_prctl_spec_ctrl_set(arg2, arg3);
|
error = arch_prctl_spec_ctrl_set(me, arg2, arg3);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user