Commit 7a0ea09a authored by Michal Hocko's avatar Michal Hocko Committed by Linus Torvalds

futex: futex_find_get_task remove credentails check

futex_find_get_task is currently used (through lookup_pi_state) from two
contexts, futex_requeue and futex_lock_pi_atomic.  None of the paths
looks it needs the credentials check, though.  Different (e)uids
shouldn't matter at all because the only thing that is important for
shared futex is the accessibility of the shared memory.

The credentail check results in glibc assert failure or process hang (if
glibc is compiled without assert support) for shared robust pthread
mutex with priority inheritance if a process tries to lock already held
lock owned by a process with a different euid:

pthread_mutex_lock.c:312: __pthread_mutex_lock_full: Assertion `(-(e)) != 3 || !robust' failed.

The problem is that futex_lock_pi_atomic which is called when we try to
lock already held lock checks the current holder (tid is stored in the
futex value) to get the PI state.  It uses lookup_pi_state which in turn
gets task struct from futex_find_get_task.  ESRCH is returned either
when the task is not found or if credentials check fails.

futex_lock_pi_atomic simply returns if it gets ESRCH.  glibc code,
however, doesn't expect that robust lock returns with ESRCH because it
should get either success or owner died.
Signed-off-by: default avatarMichal Hocko <mhocko@suse.cz>
Acked-by: default avatarDarren Hart <dvhltc@us.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f4985dc7
...@@ -429,20 +429,11 @@ static void free_pi_state(struct futex_pi_state *pi_state) ...@@ -429,20 +429,11 @@ static void free_pi_state(struct futex_pi_state *pi_state)
static struct task_struct * futex_find_get_task(pid_t pid) static struct task_struct * futex_find_get_task(pid_t pid)
{ {
struct task_struct *p; struct task_struct *p;
const struct cred *cred = current_cred(), *pcred;
rcu_read_lock(); rcu_read_lock();
p = find_task_by_vpid(pid); p = find_task_by_vpid(pid);
if (!p) { if (p)
p = ERR_PTR(-ESRCH);
} else {
pcred = __task_cred(p);
if (cred->euid != pcred->euid &&
cred->euid != pcred->uid)
p = ERR_PTR(-ESRCH);
else
get_task_struct(p); get_task_struct(p);
}
rcu_read_unlock(); rcu_read_unlock();
...@@ -564,8 +555,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, ...@@ -564,8 +555,8 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
if (!pid) if (!pid)
return -ESRCH; return -ESRCH;
p = futex_find_get_task(pid); p = futex_find_get_task(pid);
if (IS_ERR(p)) if (!p)
return PTR_ERR(p); return -ESRCH;
/* /*
* We need to look at the task state flags to figure out, * We need to look at the task state flags to figure out,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment