|
|
@@ -700,10 +700,29 @@ static void ssb_select_mitigation(void)
|
|
|
#undef pr_fmt
|
|
|
#define pr_fmt(fmt) "Speculation prctl: " fmt
|
|
|
|
|
|
-static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
|
|
|
+static void task_update_spec_tif(struct task_struct *tsk, int tifbit, bool on)
|
|
|
{
|
|
|
bool update;
|
|
|
|
|
|
+ if (on)
|
|
|
+ update = !test_and_set_tsk_thread_flag(tsk, tifbit);
|
|
|
+ else
|
|
|
+ update = test_and_clear_tsk_thread_flag(tsk, tifbit);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Immediately update the speculation control MSRs for the current
|
|
|
+ * task, but for a non-current task delay setting the CPU
|
|
|
+ * mitigation until it is scheduled next.
|
|
|
+ *
|
|
|
+ * This can only happen for SECCOMP mitigation. For PRCTL it's
|
|
|
+ * always the current task.
|
|
|
+ */
|
|
|
+ if (tsk == current && update)
|
|
|
+ speculation_ctrl_update_current();
|
|
|
+}
|
|
|
+
|
|
|
+static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
|
|
|
+{
|
|
|
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL &&
|
|
|
ssb_mode != SPEC_STORE_BYPASS_SECCOMP)
|
|
|
return -ENXIO;
|
|
|
@@ -714,28 +733,20 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
|
|
|
if (task_spec_ssb_force_disable(task))
|
|
|
return -EPERM;
|
|
|
task_clear_spec_ssb_disable(task);
|
|
|
- update = test_and_clear_tsk_thread_flag(task, TIF_SSBD);
|
|
|
+ task_update_spec_tif(task, TIF_SSBD, false);
|
|
|
break;
|
|
|
case PR_SPEC_DISABLE:
|
|
|
task_set_spec_ssb_disable(task);
|
|
|
- update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
|
|
|
+ task_update_spec_tif(task, TIF_SSBD, true);
|
|
|
break;
|
|
|
case PR_SPEC_FORCE_DISABLE:
|
|
|
task_set_spec_ssb_disable(task);
|
|
|
task_set_spec_ssb_force_disable(task);
|
|
|
- update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
|
|
|
+ task_update_spec_tif(task, TIF_SSBD, true);
|
|
|
break;
|
|
|
default:
|
|
|
return -ERANGE;
|
|
|
}
|
|
|
-
|
|
|
- /*
|
|
|
- * If being set on non-current task, delay setting the CPU
|
|
|
- * mitigation until it is next scheduled.
|
|
|
- */
|
|
|
- if (task == current && update)
|
|
|
- speculation_ctrl_update_current();
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|