[PATCH 4.4 068/107] nospec: Allow getting/setting on non-current task

2018-07-23 Thread Greg Kroah-Hartman
4.4-stable review patch.  If anyone has any objections, please let me know.

--

From: Kees Cook 

commit 7bbf1373e228840bb0295a2ca26d548ef37f448e upstream

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 
Signed-off-by: Thomas Gleixner 
Signed-off-by: David Woodhouse 
Signed-off-by: Greg Kroah-Hartman 
Signed-off-by: Srivatsa S. Bhat 
Reviewed-by: Matt Helsley (VMware) 
Reviewed-by: Alexey Makhalov 
Reviewed-by: Bo Gan 
Signed-off-by: Greg Kroah-Hartman 
---

 arch/x86/kernel/cpu/bugs.c |   27 ---
 include/linux/nospec.h |7 +--
 kernel/sys.c   |9 +
 3 files changed, 26 insertions(+), 17 deletions(-)

--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -529,31 +529,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:
@@ -563,24 +567,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;
}
--- a/include/linux/nospec.h
+++ b/include/linux/nospec.h
@@ -7,6 +7,8 @@
 #define _LINUX_NOSPEC_H
 #include 
 
+struct task_struct;
+
 /**
  * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 
otherwise
  * @index: array element index
@@ -57,7 +59,8 @@ static inline unsigned long array_index_
 })
 
 /* 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);
 
 #endif /* _LINUX_NOSPEC_H */
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2075,12 +2075,13 @@ static int prctl_get_tid_address(struct
 }
 #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;
 }
@@ -2282,12 +2283,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
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 

[PATCH 4.4 068/107] nospec: Allow getting/setting on non-current task

2018-07-23 Thread Greg Kroah-Hartman
4.4-stable review patch.  If anyone has any objections, please let me know.

--

From: Kees Cook 

commit 7bbf1373e228840bb0295a2ca26d548ef37f448e upstream

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 
Signed-off-by: Thomas Gleixner 
Signed-off-by: David Woodhouse 
Signed-off-by: Greg Kroah-Hartman 
Signed-off-by: Srivatsa S. Bhat 
Reviewed-by: Matt Helsley (VMware) 
Reviewed-by: Alexey Makhalov 
Reviewed-by: Bo Gan 
Signed-off-by: Greg Kroah-Hartman 
---

 arch/x86/kernel/cpu/bugs.c |   27 ---
 include/linux/nospec.h |7 +--
 kernel/sys.c   |9 +
 3 files changed, 26 insertions(+), 17 deletions(-)

--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -529,31 +529,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:
@@ -563,24 +567,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;
}
--- a/include/linux/nospec.h
+++ b/include/linux/nospec.h
@@ -7,6 +7,8 @@
 #define _LINUX_NOSPEC_H
 #include 
 
+struct task_struct;
+
 /**
  * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 
otherwise
  * @index: array element index
@@ -57,7 +59,8 @@ static inline unsigned long array_index_
 })
 
 /* 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);
 
 #endif /* _LINUX_NOSPEC_H */
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2075,12 +2075,13 @@ static int prctl_get_tid_address(struct
 }
 #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;
 }
@@ -2282,12 +2283,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
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