]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - arch/x86/kernel/cpu/bugs.c
nospec: Allow getting/setting on non-current task
[mirror_ubuntu-artful-kernel.git] / arch / x86 / kernel / cpu / bugs.c
index ec06501ec783986bd44ed304640d4285d02a0f15..cdf39837c80f13304081aaa22feefb633acd5ea7 100644 (file)
@@ -489,31 +489,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:
@@ -523,24 +527,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;
        }