]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
nospec: Allow getting/setting on non-current task
authorKees Cook <keescook@chromium.org>
Tue, 1 May 2018 22:19:04 +0000 (15:19 -0700)
committerBrian Maly <brian.maly@oracle.com>
Mon, 21 May 2018 22:05:02 +0000 (18:05 -0400)
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).

OraBug: 28041771
CVE: CVE-2018-3639

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
(cherry picked from commit 7bbf1373e228840bb0295a2ca26d548ef37f448e)
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Mihai Carabas <mihai.carabas@oracle.com>
 Conflicts:
arch/x86/kernel/cpu/bugs.c
include/linux/nospec.h
kernel/sys.c

Signed-off-by: Brian Maly <brian.maly@oracle.com>
arch/x86/include/asm/nospec-branch.h
arch/x86/kernel/cpu/bugs_64.c
kernel/sys.c

index 434a7807b80a0406e37722bdbf98a7839cf3ada9..f0280ae075f6a1c46e4ae871000d46945f2398cd 100644 (file)
@@ -195,8 +195,8 @@ extern char __indirect_thunk_start[];
 extern char __indirect_thunk_end[];
 
 /* Speculation control prctl */
-int arch_prctl_spec_ctrl_get(unsigned long which);
-int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl);
+int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which);
+int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, unsigned long ctrl);
 
 /*
  * On VMEXIT we must ensure that no RSB predictions learned in the guest
index 60e2ecd3cabea98aa989f3a172efc21d8b5c2253..e2c073539f813013cd2e6f3caaad39bee17c533f 100644 (file)
@@ -805,32 +805,36 @@ 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_USERSPACE:
        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:
@@ -840,24 +844,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;
        }
index d0fb4a75f1c4244d39b0c38e9bf3d88c9bb24ec1..b58e79dd6d8d31a4257bfec05e86f40e4a122259 100644 (file)
@@ -2050,12 +2050,13 @@ static int prctl_get_tid_address(struct task_struct *me, int __user **tid_addr)
 }
 #endif
 
-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;
 }
 
-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;
 }
@@ -2257,12 +2258,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
        case PR_GET_SPECULATION_CTRL:
                if (arg3 || arg4 || arg5)
                        return -EINVAL;
-               error = arch_prctl_spec_ctrl_get(arg2);
+               error = arch_prctl_spec_ctrl_get(me, arg2);
                break;
        case PR_SET_SPECULATION_CTRL:
                if (arg4 || arg5)
                        return -EINVAL;
-               error = arch_prctl_spec_ctrl_set(arg2, arg3);
+               error = arch_prctl_spec_ctrl_set(me, arg2, arg3);
        default:
                error = -EINVAL;
                break;