mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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 <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
This commit is contained in:
		
							parent
							
								
									ca16d5bee5
								
							
						
					
					
						commit
						ba31c1a485
					
				
					 4 changed files with 48 additions and 41 deletions
				
			
		| 
						 | 
				
			
			@ -410,8 +410,6 @@ struct compat_kexec_segment;
 | 
			
		|||
struct compat_mq_attr;
 | 
			
		||||
struct compat_msgbuf;
 | 
			
		||||
 | 
			
		||||
extern void compat_exit_robust_list(struct task_struct *curr);
 | 
			
		||||
 | 
			
		||||
#define BITS_PER_COMPAT_LONG    (8*sizeof(compat_long_t))
 | 
			
		||||
 | 
			
		||||
#define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			@ -48,15 +50,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);
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_robust_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) { }
 | 
			
		||||
static inline long do_futex(u32 __user *uaddr, int op, u32 val,
 | 
			
		||||
			    ktime_t *timeout, u32 __user *uaddr2,
 | 
			
		||||
			    u32 val2, u32 val3)
 | 
			
		||||
| 
						 | 
				
			
			@ -65,12 +76,4 @@ static inline long do_futex(u32 __user *uaddr, int op, u32 val,
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_FUTEX_PI
 | 
			
		||||
extern void exit_pi_state_list(struct task_struct *curr);
 | 
			
		||||
#else
 | 
			
		||||
static inline void exit_pi_state_list(struct task_struct *curr)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1286,20 +1286,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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2062,14 +2049,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
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -325,6 +325,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 void put_pi_state(struct futex_pi_state *pi_state)
 | 
			
		|||
 * 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
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -3588,7 +3595,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -3653,6 +3660,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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -3780,7 +3805,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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue