Skip to content

Commit 7bbf137

Browse files
keesKAGA-KOKO
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]>
1 parent a73ec77 commit 7bbf137

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
@@ -530,31 +530,35 @@ static void ssb_select_mitigation()
530530

531531
#undef pr_fmt
532532

533-
static int ssb_prctl_set(unsigned long ctrl)
533+
static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
534534
{
535-
bool rds = !!test_tsk_thread_flag(current, TIF_RDS);
535+
bool rds = !!test_tsk_thread_flag(task, TIF_RDS);
536536

537537
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL)
538538
return -ENXIO;
539539

540540
if (ctrl == PR_SPEC_ENABLE)
541-
clear_tsk_thread_flag(current, TIF_RDS);
541+
clear_tsk_thread_flag(task, TIF_RDS);
542542
else
543-
set_tsk_thread_flag(current, TIF_RDS);
543+
set_tsk_thread_flag(task, TIF_RDS);
544544

545-
if (rds != !!test_tsk_thread_flag(current, TIF_RDS))
545+
/*
546+
* If being set on non-current task, delay setting the CPU
547+
* mitigation until it is next scheduled.
548+
*/
549+
if (task == current && rds != !!test_tsk_thread_flag(task, TIF_RDS))
546550
speculative_store_bypass_update();
547551

548552
return 0;
549553
}
550554

551-
static int ssb_prctl_get(void)
555+
static int ssb_prctl_get(struct task_struct *task)
552556
{
553557
switch (ssb_mode) {
554558
case SPEC_STORE_BYPASS_DISABLE:
555559
return PR_SPEC_DISABLE;
556560
case SPEC_STORE_BYPASS_PRCTL:
557-
if (test_tsk_thread_flag(current, TIF_RDS))
561+
if (test_tsk_thread_flag(task, TIF_RDS))
558562
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
559563
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
560564
default:
@@ -564,24 +568,25 @@ static int ssb_prctl_get(void)
564568
}
565569
}
566570

567-
int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
571+
int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
572+
unsigned long ctrl)
568573
{
569574
if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE)
570575
return -ERANGE;
571576

572577
switch (which) {
573578
case PR_SPEC_STORE_BYPASS:
574-
return ssb_prctl_set(ctrl);
579+
return ssb_prctl_set(task, ctrl);
575580
default:
576581
return -ENODEV;
577582
}
578583
}
579584

580-
int arch_prctl_spec_ctrl_get(unsigned long which)
585+
int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
581586
{
582587
switch (which) {
583588
case PR_SPEC_STORE_BYPASS:
584-
return ssb_prctl_get();
589+
return ssb_prctl_get(task);
585590
default:
586591
return -ENODEV;
587592
}

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
@@ -2244,12 +2244,13 @@ static int propagate_has_child_subreaper(struct task_struct *p, void *data)
22442244
return 1;
22452245
}
22462246

2247-
int __weak arch_prctl_spec_ctrl_get(unsigned long which)
2247+
int __weak arch_prctl_spec_ctrl_get(struct task_struct *t, unsigned long which)
22482248
{
22492249
return -EINVAL;
22502250
}
22512251

2252-
int __weak arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
2252+
int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which,
2253+
unsigned long ctrl)
22532254
{
22542255
return -EINVAL;
22552256
}
@@ -2465,12 +2466,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
24652466
case PR_GET_SPECULATION_CTRL:
24662467
if (arg3 || arg4 || arg5)
24672468
return -EINVAL;
2468-
error = arch_prctl_spec_ctrl_get(arg2);
2469+
error = arch_prctl_spec_ctrl_get(me, arg2);
24692470
break;
24702471
case PR_SET_SPECULATION_CTRL:
24712472
if (arg4 || arg5)
24722473
return -EINVAL;
2473-
error = arch_prctl_spec_ctrl_set(arg2, arg3);
2474+
error = arch_prctl_spec_ctrl_set(me, arg2, arg3);
24742475
break;
24752476
default:
24762477
error = -EINVAL;

0 commit comments

Comments
 (0)