From: Yang Yingliang yangyingliang@huawei.com
hulk inclusion category: bugfix bugzilla: NA CVE: NA
-------------------------------------------------
Fix kabi broken introduced by c5f21df94d82 ("futex: Replace PF_EXITPIDONE with a state") 5c7385e6eb43 ("futex: Add mutex around futex exit")
Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Jian Cheng cj.chengjian@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- include/linux/futex.h | 1 - include/linux/sched.h | 6 +++--- kernel/fork.c | 11 ++++++++++- kernel/futex.c | 10 +++++----- 4 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/include/linux/futex.h b/include/linux/futex.h index b70df27d7e85..1db16694ea16 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -68,7 +68,6 @@ static inline void futex_init_task(struct task_struct *tsk) INIT_LIST_HEAD(&tsk->pi_state_list); tsk->pi_state_cache = NULL; tsk->futex_state = FUTEX_STATE_OK; - mutex_init(&tsk->futex_exit_mutex); }
void futex_exit_recursive(struct task_struct *tsk); diff --git a/include/linux/sched.h b/include/linux/sched.h index 5f77e3b546db..9dc064305c13 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1002,8 +1002,6 @@ struct task_struct { #endif struct list_head pi_state_list; struct futex_pi_state *pi_state_cache; - struct mutex futex_exit_mutex; - unsigned int futex_state; #endif #ifdef CONFIG_PERF_EVENTS struct perf_event_context *perf_event_ctxp[perf_nr_task_contexts]; @@ -1218,12 +1216,14 @@ struct task_struct { #ifndef __GENKSYMS__ u64 parent_exec_id_u64; u64 self_exec_id_u64; + struct mutex *futex_exit_mutex; + unsigned long futex_state; #else KABI_RESERVE(1) KABI_RESERVE(2) -#endif KABI_RESERVE(3) KABI_RESERVE(4) +#endif KABI_RESERVE(5) KABI_RESERVE(6) KABI_RESERVE(7) diff --git a/kernel/fork.c b/kernel/fork.c index 5ee7ed5151d1..36d3edeff7ac 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -458,6 +458,8 @@ void free_task(struct task_struct *tsk) arch_release_task_struct(tsk); if (tsk->flags & PF_KTHREAD) free_kthread_struct(tsk); + kfree(tsk->futex_exit_mutex); + tsk->futex_exit_mutex = NULL; free_task_struct(tsk); } EXPORT_SYMBOL(free_task); @@ -1995,6 +1997,10 @@ static __latent_entropy struct task_struct *copy_process( p->plug = NULL; #endif futex_init_task(p); + p->futex_exit_mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL); + if (!p->futex_exit_mutex) + goto bad_fork_free_pid; + mutex_init(p->futex_exit_mutex);
/* * sigaltstack should be cleared when sharing the same VM @@ -2040,7 +2046,7 @@ static __latent_entropy struct task_struct *copy_process( */ retval = cgroup_can_fork(p); if (retval) - goto bad_fork_free_pid; + goto bad_fork_free_futex_mutex;
/* * From this point on we must avoid any synchronous user-space @@ -2164,6 +2170,9 @@ static __latent_entropy struct task_struct *copy_process( spin_unlock(¤t->sighand->siglock); write_unlock_irq(&tasklist_lock); cgroup_cancel_fork(p); +bad_fork_free_futex_mutex: + kfree(p->futex_exit_mutex); + p->futex_exit_mutex = NULL; bad_fork_free_pid: cgroup_threadgroup_change_end(current); if (pid != &init_struct_pid) diff --git a/kernel/futex.c b/kernel/futex.c index 7ece653364d2..fc56076a2cc2 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1215,7 +1215,7 @@ static void wait_for_owner_exiting(int ret, struct task_struct *exiting) if (WARN_ON_ONCE(ret == -EBUSY && !exiting)) return;
- mutex_lock(&exiting->futex_exit_mutex); + mutex_lock(exiting->futex_exit_mutex); /* * No point in doing state checking here. If the waiter got here * while the task was in exec()->exec_futex_release() then it can @@ -1224,7 +1224,7 @@ static void wait_for_owner_exiting(int ret, struct task_struct *exiting) * already. Highly unlikely and not a problem. Just one more round * through the futex maze. */ - mutex_unlock(&exiting->futex_exit_mutex); + mutex_unlock(exiting->futex_exit_mutex);
put_task_struct(exiting); } @@ -3793,7 +3793,7 @@ void futex_exit_recursive(struct task_struct *tsk) { /* If the state is FUTEX_STATE_EXITING then futex_exit_mutex is held */ if (tsk->futex_state == FUTEX_STATE_EXITING) - mutex_unlock(&tsk->futex_exit_mutex); + mutex_unlock(tsk->futex_exit_mutex); tsk->futex_state = FUTEX_STATE_DEAD; }
@@ -3805,7 +3805,7 @@ static void futex_cleanup_begin(struct task_struct *tsk) * tsk->futex_exit_mutex when it observes FUTEX_STATE_EXITING in * attach_to_pi_owner(). */ - mutex_lock(&tsk->futex_exit_mutex); + mutex_lock(tsk->futex_exit_mutex);
/* * Switch the state to FUTEX_STATE_EXITING under tsk->pi_lock. @@ -3834,7 +3834,7 @@ static void futex_cleanup_end(struct task_struct *tsk, int state) * Drop the exit protection. This unblocks waiters which observed * FUTEX_STATE_EXITING to reevaluate the state. */ - mutex_unlock(&tsk->futex_exit_mutex); + mutex_unlock(tsk->futex_exit_mutex); }
void futex_exec_release(struct task_struct *tsk)