Skip to content

Commit 5765ec2

Browse files
keeskonradwilk
authored andcommitted
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 <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> (cherry picked from commit 7bbf137) Orabug: 28034177 CVE: CVE-2018-3639 Signed-off-by: Konrad Rzeszutek Wilk <[email protected]> Tested-by: Mihai Carabas <[email protected]> Reviewed-by: Mihai Carabas <[email protected]> Reviewed-by: John Haxby <[email protected]>
1 parent 648702f commit 5765ec2

File tree

3 files changed

+26
-17
lines changed

3 files changed

+26
-17
lines changed

arch/x86/kernel/cpu/bugs.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -812,32 +812,36 @@ static void ssb_select_mitigation()
812812

813813
#undef pr_fmt
814814

815-
static int ssb_prctl_set(unsigned long ctrl)
815+
static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
816816
{
817-
bool rds = !!test_tsk_thread_flag(current, TIF_RDS);
817+
bool rds = !!test_tsk_thread_flag(task, TIF_RDS);
818818

819819
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL)
820820
return -ENXIO;
821821

822822
if (ctrl == PR_SPEC_ENABLE)
823-
clear_tsk_thread_flag(current, TIF_RDS);
823+
clear_tsk_thread_flag(task, TIF_RDS);
824824
else
825-
set_tsk_thread_flag(current, TIF_RDS);
825+
set_tsk_thread_flag(task, TIF_RDS);
826826

827-
if (rds != !!test_tsk_thread_flag(current, TIF_RDS))
827+
/*
828+
* If being set on non-current task, delay setting the CPU
829+
* mitigation until it is next scheduled.
830+
*/
831+
if (task == current && rds != !!test_tsk_thread_flag(task, TIF_RDS))
828832
speculative_store_bypass_update();
829833

830834
return 0;
831835
}
832836

833-
static int ssb_prctl_get(void)
837+
static int ssb_prctl_get(struct task_struct *task)
834838
{
835839
switch (ssb_mode) {
836840
case SPEC_STORE_BYPASS_USERSPACE:
837841
case SPEC_STORE_BYPASS_DISABLE:
838842
return PR_SPEC_DISABLE;
839843
case SPEC_STORE_BYPASS_PRCTL:
840-
if (test_tsk_thread_flag(current, TIF_RDS))
844+
if (test_tsk_thread_flag(task, TIF_RDS))
841845
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
842846
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
843847
default:
@@ -847,24 +851,25 @@ static int ssb_prctl_get(void)
847851
}
848852
}
849853

850-
int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
854+
int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
855+
unsigned long ctrl)
851856
{
852857
if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE)
853858
return -ERANGE;
854859

855860
switch (which) {
856861
case PR_SPEC_STORE_BYPASS:
857-
return ssb_prctl_set(ctrl);
862+
return ssb_prctl_set(task, ctrl);
858863
default:
859864
return -ENODEV;
860865
}
861866
}
862867

863-
int arch_prctl_spec_ctrl_get(unsigned long which)
868+
int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
864869
{
865870
switch (which) {
866871
case PR_SPEC_STORE_BYPASS:
867-
return ssb_prctl_get();
872+
return ssb_prctl_get(task);
868873
default:
869874
return -ENODEV;
870875
}

include/linux/nospec.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#define _LINUX_NOSPEC_H
88
#include <asm/barrier.h>
99

10+
struct task_struct;
11+
1012
/**
1113
* array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
1214
* @index: array element index
@@ -57,7 +59,8 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
5759
})
5860

5961
/* Speculation control prctl */
60-
int arch_prctl_spec_ctrl_get(unsigned long which);
61-
int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl);
62+
int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which);
63+
int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
64+
unsigned long ctrl);
6265

6366
#endif /* _LINUX_NOSPEC_H */

kernel/sys.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,12 +2192,13 @@ static int propagate_has_child_subreaper(struct task_struct *p, void *data)
21922192
return 1;
21932193
}
21942194

2195-
int __weak arch_prctl_spec_ctrl_get(unsigned long which)
2195+
int __weak arch_prctl_spec_ctrl_get(struct task_struct *t, unsigned long which)
21962196
{
21972197
return -EINVAL;
21982198
}
21992199

2200-
int __weak arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
2200+
int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which,
2201+
unsigned long ctrl)
22012202
{
22022203
return -EINVAL;
22032204
}
@@ -2413,12 +2414,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
24132414
case PR_GET_SPECULATION_CTRL:
24142415
if (arg3 || arg4 || arg5)
24152416
return -EINVAL;
2416-
error = arch_prctl_spec_ctrl_get(arg2);
2417+
error = arch_prctl_spec_ctrl_get(me, arg2);
24172418
break;
24182419
case PR_SET_SPECULATION_CTRL:
24192420
if (arg4 || arg5)
24202421
return -EINVAL;
2421-
error = arch_prctl_spec_ctrl_set(arg2, arg3);
2422+
error = arch_prctl_spec_ctrl_set(me, arg2, arg3);
24222423
break;
24232424
default:
24242425
error = -EINVAL;

0 commit comments

Comments
 (0)