Skip to content

Commit ba31c1a

Browse files
committed
futex: Move futex exit handling into futex code
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 <[email protected]> Reviewed-by: Ingo Molnar <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent ca16d5b commit ba31c1a

File tree

4 files changed

+48
-41
lines changed

4 files changed

+48
-41
lines changed

include/linux/compat.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,8 +410,6 @@ struct compat_kexec_segment;
410410
struct compat_mq_attr;
411411
struct compat_msgbuf;
412412

413-
extern void compat_exit_robust_list(struct task_struct *curr);
414-
415413
#define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t))
416414

417415
#define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)

include/linux/futex.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#ifndef _LINUX_FUTEX_H
33
#define _LINUX_FUTEX_H
44

5+
#include <linux/sched.h>
56
#include <linux/ktime.h>
7+
68
#include <uapi/linux/futex.h>
79

810
struct inode;
@@ -48,15 +50,24 @@ union futex_key {
4850
#define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = NULL } }
4951

5052
#ifdef CONFIG_FUTEX
51-
extern void exit_robust_list(struct task_struct *curr);
5253

53-
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
54-
u32 __user *uaddr2, u32 val2, u32 val3);
55-
#else
56-
static inline void exit_robust_list(struct task_struct *curr)
54+
static inline void futex_init_task(struct task_struct *tsk)
5755
{
56+
tsk->robust_list = NULL;
57+
#ifdef CONFIG_COMPAT
58+
tsk->compat_robust_list = NULL;
59+
#endif
60+
INIT_LIST_HEAD(&tsk->pi_state_list);
61+
tsk->pi_state_cache = NULL;
5862
}
5963

64+
void futex_mm_release(struct task_struct *tsk);
65+
66+
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
67+
u32 __user *uaddr2, u32 val2, u32 val3);
68+
#else
69+
static inline void futex_init_task(struct task_struct *tsk) { }
70+
static inline void futex_mm_release(struct task_struct *tsk) { }
6071
static inline long do_futex(u32 __user *uaddr, int op, u32 val,
6172
ktime_t *timeout, u32 __user *uaddr2,
6273
u32 val2, u32 val3)
@@ -65,12 +76,4 @@ static inline long do_futex(u32 __user *uaddr, int op, u32 val,
6576
}
6677
#endif
6778

68-
#ifdef CONFIG_FUTEX_PI
69-
extern void exit_pi_state_list(struct task_struct *curr);
70-
#else
71-
static inline void exit_pi_state_list(struct task_struct *curr)
72-
{
73-
}
74-
#endif
75-
7679
#endif

kernel/fork.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,20 +1286,7 @@ static int wait_for_vfork_done(struct task_struct *child,
12861286
void mm_release(struct task_struct *tsk, struct mm_struct *mm)
12871287
{
12881288
/* Get rid of any futexes when releasing the mm */
1289-
#ifdef CONFIG_FUTEX
1290-
if (unlikely(tsk->robust_list)) {
1291-
exit_robust_list(tsk);
1292-
tsk->robust_list = NULL;
1293-
}
1294-
#ifdef CONFIG_COMPAT
1295-
if (unlikely(tsk->compat_robust_list)) {
1296-
compat_exit_robust_list(tsk);
1297-
tsk->compat_robust_list = NULL;
1298-
}
1299-
#endif
1300-
if (unlikely(!list_empty(&tsk->pi_state_list)))
1301-
exit_pi_state_list(tsk);
1302-
#endif
1289+
futex_mm_release(tsk);
13031290

13041291
uprobe_free_utask(tsk);
13051292

@@ -2062,14 +2049,8 @@ static __latent_entropy struct task_struct *copy_process(
20622049
#ifdef CONFIG_BLOCK
20632050
p->plug = NULL;
20642051
#endif
2065-
#ifdef CONFIG_FUTEX
2066-
p->robust_list = NULL;
2067-
#ifdef CONFIG_COMPAT
2068-
p->compat_robust_list = NULL;
2069-
#endif
2070-
INIT_LIST_HEAD(&p->pi_state_list);
2071-
p->pi_state_cache = NULL;
2072-
#endif
2052+
futex_init_task(p);
2053+
20732054
/*
20742055
* sigaltstack should be cleared when sharing the same VM
20752056
*/

kernel/futex.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,12 @@ static inline bool should_fail_futex(bool fshared)
325325
}
326326
#endif /* CONFIG_FAIL_FUTEX */
327327

328+
#ifdef CONFIG_COMPAT
329+
static void compat_exit_robust_list(struct task_struct *curr);
330+
#else
331+
static inline void compat_exit_robust_list(struct task_struct *curr) { }
332+
#endif
333+
328334
static inline void futex_get_mm(union futex_key *key)
329335
{
330336
mmgrab(key->private.mm);
@@ -890,7 +896,7 @@ static void put_pi_state(struct futex_pi_state *pi_state)
890896
* Kernel cleans up PI-state, but userspace is likely hosed.
891897
* (Robust-futex cleanup is separate and might save the day for userspace.)
892898
*/
893-
void exit_pi_state_list(struct task_struct *curr)
899+
static void exit_pi_state_list(struct task_struct *curr)
894900
{
895901
struct list_head *next, *head = &curr->pi_state_list;
896902
struct futex_pi_state *pi_state;
@@ -960,7 +966,8 @@ void exit_pi_state_list(struct task_struct *curr)
960966
}
961967
raw_spin_unlock_irq(&curr->pi_lock);
962968
}
963-
969+
#else
970+
static inline void exit_pi_state_list(struct task_struct *curr) { }
964971
#endif
965972

966973
/*
@@ -3588,7 +3595,7 @@ static inline int fetch_robust_entry(struct robust_list __user **entry,
35883595
*
35893596
* We silently return on any sign of list-walking problem.
35903597
*/
3591-
void exit_robust_list(struct task_struct *curr)
3598+
static void exit_robust_list(struct task_struct *curr)
35923599
{
35933600
struct robust_list_head __user *head = curr->robust_list;
35943601
struct robust_list __user *entry, *next_entry, *pending;
@@ -3653,6 +3660,24 @@ void exit_robust_list(struct task_struct *curr)
36533660
}
36543661
}
36553662

3663+
void futex_mm_release(struct task_struct *tsk)
3664+
{
3665+
if (unlikely(tsk->robust_list)) {
3666+
exit_robust_list(tsk);
3667+
tsk->robust_list = NULL;
3668+
}
3669+
3670+
#ifdef CONFIG_COMPAT
3671+
if (unlikely(tsk->compat_robust_list)) {
3672+
compat_exit_robust_list(tsk);
3673+
tsk->compat_robust_list = NULL;
3674+
}
3675+
#endif
3676+
3677+
if (unlikely(!list_empty(&tsk->pi_state_list)))
3678+
exit_pi_state_list(tsk);
3679+
}
3680+
36563681
long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
36573682
u32 __user *uaddr2, u32 val2, u32 val3)
36583683
{
@@ -3780,7 +3805,7 @@ static void __user *futex_uaddr(struct robust_list __user *entry,
37803805
*
37813806
* We silently return on any sign of list-walking problem.
37823807
*/
3783-
void compat_exit_robust_list(struct task_struct *curr)
3808+
static void compat_exit_robust_list(struct task_struct *curr)
37843809
{
37853810
struct compat_robust_list_head __user *head = curr->compat_robust_list;
37863811
struct robust_list __user *entry, *next_entry, *pending;

0 commit comments

Comments
 (0)