futex: Move futex exit handling into futex code
authorThomas Gleixner <tglx@linutronix.de>
Wed, 6 Nov 2019 21:55:36 +0000 (22:55 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Dec 2019 14:38:23 +0000 (15:38 +0100)
commit ba31c1a48538992316cc71ce94fa9cd3e7b427c0 upstream.

The futex exit handling is #ifdeffed into mm_release() which is not pretty
to begin with. But upcoming changes to address futex exit races need to add
more functionality to this exit code.

Split it out into a function, move it into futex code and make the various
futex exit functions static.

Preparatory only and no functional change.

Folded build fix from Borislav.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20191106224556.049705556@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/compat.h
include/linux/futex.h
kernel/fork.c
kernel/futex.c

index 23909d12f729228795bc2b2b415d3e981c978a65..cec96d4794d0f8627cc40f003ead6deb1c79273d 100644 (file)
@@ -324,8 +324,6 @@ struct compat_kexec_segment;
 struct compat_mq_attr;
 struct compat_msgbuf;
 
-extern void compat_exit_robust_list(struct task_struct *curr);
-
 asmlinkage long
 compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
                           compat_size_t len);
index d05e753232ba8fc1cd4c15d0da42b1cd9a7e6a3a..bc4138b87035530021c86339fff9554b2935b617 100644 (file)
@@ -2,7 +2,9 @@
 #ifndef _LINUX_FUTEX_H
 #define _LINUX_FUTEX_H
 
+#include <linux/sched.h>
 #include <linux/ktime.h>
+
 #include <uapi/linux/futex.h>
 
 struct inode;
@@ -51,19 +53,24 @@ union futex_key {
 #define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } }
 
 #ifdef CONFIG_FUTEX
-extern void exit_robust_list(struct task_struct *curr);
-#else
-static inline void exit_robust_list(struct task_struct *curr)
+
+static inline void futex_init_task(struct task_struct *tsk)
 {
-}
+       tsk->robust_list = NULL;
+#ifdef CONFIG_COMPAT
+       tsk->compat_robust_list = NULL;
 #endif
+       INIT_LIST_HEAD(&tsk->pi_state_list);
+       tsk->pi_state_cache = NULL;
+}
 
-#ifdef CONFIG_FUTEX_PI
-extern void exit_pi_state_list(struct task_struct *curr);
+void futex_mm_release(struct task_struct *tsk);
+
+long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
+             u32 __user *uaddr2, u32 val2, u32 val3);
 #else
-static inline void exit_pi_state_list(struct task_struct *curr)
-{
-}
+static inline void futex_init_task(struct task_struct *tsk) { }
+static inline void futex_mm_release(struct task_struct *tsk) { }
 #endif
 
 #endif
index 3d9d6a28e21d9fcd29b1a1659c54c61de72d26db..1dc6b9ecc33ac181b81b0fa0a97dc3c73acfa3da 100644 (file)
@@ -1135,20 +1135,7 @@ static int wait_for_vfork_done(struct task_struct *child,
 void mm_release(struct task_struct *tsk, struct mm_struct *mm)
 {
        /* Get rid of any futexes when releasing the mm */
-#ifdef CONFIG_FUTEX
-       if (unlikely(tsk->robust_list)) {
-               exit_robust_list(tsk);
-               tsk->robust_list = NULL;
-       }
-#ifdef CONFIG_COMPAT
-       if (unlikely(tsk->compat_robust_list)) {
-               compat_exit_robust_list(tsk);
-               tsk->compat_robust_list = NULL;
-       }
-#endif
-       if (unlikely(!list_empty(&tsk->pi_state_list)))
-               exit_pi_state_list(tsk);
-#endif
+       futex_mm_release(tsk);
 
        uprobe_free_utask(tsk);
 
@@ -1796,14 +1783,8 @@ static __latent_entropy struct task_struct *copy_process(
 #ifdef CONFIG_BLOCK
        p->plug = NULL;
 #endif
-#ifdef CONFIG_FUTEX
-       p->robust_list = NULL;
-#ifdef CONFIG_COMPAT
-       p->compat_robust_list = NULL;
-#endif
-       INIT_LIST_HEAD(&p->pi_state_list);
-       p->pi_state_cache = NULL;
-#endif
+       futex_init_task(p);
+
        /*
         * sigaltstack should be cleared when sharing the same VM
         */
index d0a36cba905d3d0b6cb93855e211d141c3a0c636..75edb19fa3a2330acfe7896e8601a268d76fa5a0 100644 (file)
@@ -341,6 +341,12 @@ static inline bool should_fail_futex(bool fshared)
 }
 #endif /* CONFIG_FAIL_FUTEX */
 
+#ifdef CONFIG_COMPAT
+static void compat_exit_robust_list(struct task_struct *curr);
+#else
+static inline void compat_exit_robust_list(struct task_struct *curr) { }
+#endif
+
 static inline void futex_get_mm(union futex_key *key)
 {
        mmgrab(key->private.mm);
@@ -890,7 +896,7 @@ static struct task_struct *futex_find_get_task(pid_t pid)
  * Kernel cleans up PI-state, but userspace is likely hosed.
  * (Robust-futex cleanup is separate and might save the day for userspace.)
  */
-void exit_pi_state_list(struct task_struct *curr)
+static void exit_pi_state_list(struct task_struct *curr)
 {
        struct list_head *next, *head = &curr->pi_state_list;
        struct futex_pi_state *pi_state;
@@ -960,7 +966,8 @@ void exit_pi_state_list(struct task_struct *curr)
        }
        raw_spin_unlock_irq(&curr->pi_lock);
 }
-
+#else
+static inline void exit_pi_state_list(struct task_struct *curr) { }
 #endif
 
 /*
@@ -3611,7 +3618,7 @@ static inline int fetch_robust_entry(struct robust_list __user **entry,
  *
  * We silently return on any sign of list-walking problem.
  */
-void exit_robust_list(struct task_struct *curr)
+static void exit_robust_list(struct task_struct *curr)
 {
        struct robust_list_head __user *head = curr->robust_list;
        struct robust_list __user *entry, *next_entry, *pending;
@@ -3676,6 +3683,24 @@ void exit_robust_list(struct task_struct *curr)
        }
 }
 
+void futex_mm_release(struct task_struct *tsk)
+{
+       if (unlikely(tsk->robust_list)) {
+               exit_robust_list(tsk);
+               tsk->robust_list = NULL;
+       }
+
+#ifdef CONFIG_COMPAT
+       if (unlikely(tsk->compat_robust_list)) {
+               compat_exit_robust_list(tsk);
+               tsk->compat_robust_list = NULL;
+       }
+#endif
+
+       if (unlikely(!list_empty(&tsk->pi_state_list)))
+               exit_pi_state_list(tsk);
+}
+
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
                u32 __user *uaddr2, u32 val2, u32 val3)
 {
@@ -3801,7 +3826,7 @@ static void __user *futex_uaddr(struct robust_list __user *entry,
  *
  * We silently return on any sign of list-walking problem.
  */
-void compat_exit_robust_list(struct task_struct *curr)
+static void compat_exit_robust_list(struct task_struct *curr)
 {
        struct compat_robust_list_head __user *head = curr->compat_robust_list;
        struct robust_list __user *entry, *next_entry, *pending;