]>
Commit | Line | Data |
---|---|---|
66966263 GKH |
1 | From 7a0ea09ad5352efce8fe79ed853150449903b9f5 Mon Sep 17 00:00:00 2001 |
2 | From: Michal Hocko <mhocko@suse.cz> | |
3 | Date: Wed, 30 Jun 2010 09:51:19 +0200 | |
4 | Subject: futex: futex_find_get_task remove credentails check | |
5 | ||
6 | From: Michal Hocko <mhocko@suse.cz> | |
7 | ||
8 | commit 7a0ea09ad5352efce8fe79ed853150449903b9f5 upstream. | |
9 | ||
10 | futex_find_get_task is currently used (through lookup_pi_state) from two | |
11 | contexts, futex_requeue and futex_lock_pi_atomic. None of the paths | |
12 | looks it needs the credentials check, though. Different (e)uids | |
13 | shouldn't matter at all because the only thing that is important for | |
14 | shared futex is the accessibility of the shared memory. | |
15 | ||
16 | The credentail check results in glibc assert failure or process hang (if | |
17 | glibc is compiled without assert support) for shared robust pthread | |
18 | mutex with priority inheritance if a process tries to lock already held | |
19 | lock owned by a process with a different euid: | |
20 | ||
21 | pthread_mutex_lock.c:312: __pthread_mutex_lock_full: Assertion `(-(e)) != 3 || !robust' failed. | |
22 | ||
23 | The problem is that futex_lock_pi_atomic which is called when we try to | |
24 | lock already held lock checks the current holder (tid is stored in the | |
25 | futex value) to get the PI state. It uses lookup_pi_state which in turn | |
26 | gets task struct from futex_find_get_task. ESRCH is returned either | |
27 | when the task is not found or if credentials check fails. | |
28 | ||
29 | futex_lock_pi_atomic simply returns if it gets ESRCH. glibc code, | |
30 | however, doesn't expect that robust lock returns with ESRCH because it | |
31 | should get either success or owner died. | |
32 | ||
33 | Signed-off-by: Michal Hocko <mhocko@suse.cz> | |
34 | Acked-by: Darren Hart <dvhltc@us.ibm.com> | |
35 | Cc: Ingo Molnar <mingo@elte.hu> | |
36 | Cc: Thomas Gleixner <tglx@linutronix.de> | |
37 | Cc: Nick Piggin <npiggin@suse.de> | |
38 | Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | |
39 | Cc: Peter Zijlstra <peterz@infradead.org> | |
40 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
41 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
42 | ||
43 | --- | |
44 | kernel/futex.c | 17 ++++------------- | |
45 | 1 file changed, 4 insertions(+), 13 deletions(-) | |
46 | ||
47 | --- a/kernel/futex.c | |
48 | +++ b/kernel/futex.c | |
49 | @@ -429,20 +429,11 @@ static void free_pi_state(struct futex_p | |
50 | static struct task_struct * futex_find_get_task(pid_t pid) | |
51 | { | |
52 | struct task_struct *p; | |
53 | - const struct cred *cred = current_cred(), *pcred; | |
54 | ||
55 | rcu_read_lock(); | |
56 | p = find_task_by_vpid(pid); | |
57 | - if (!p) { | |
58 | - p = ERR_PTR(-ESRCH); | |
59 | - } else { | |
60 | - pcred = __task_cred(p); | |
61 | - if (cred->euid != pcred->euid && | |
62 | - cred->euid != pcred->uid) | |
63 | - p = ERR_PTR(-ESRCH); | |
64 | - else | |
65 | - get_task_struct(p); | |
66 | - } | |
67 | + if (p) | |
68 | + get_task_struct(p); | |
69 | ||
70 | rcu_read_unlock(); | |
71 | ||
72 | @@ -564,8 +555,8 @@ lookup_pi_state(u32 uval, struct futex_h | |
73 | if (!pid) | |
74 | return -ESRCH; | |
75 | p = futex_find_get_task(pid); | |
76 | - if (IS_ERR(p)) | |
77 | - return PTR_ERR(p); | |
78 | + if (!p) | |
79 | + return -ESRCH; | |
80 | ||
81 | /* | |
82 | * We need to look at the task state flags to figure out, |