]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.17.11/sys_getppid-oopses-on-debug-kernel.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.17.11 / sys_getppid-oopses-on-debug-kernel.patch
1 From stable-bounces@linux.kernel.org Sun Aug 13 23:25:48 2006
2 Message-Id: <200608140624.k7E6ONGE007003@shell0.pdx.osdl.net>
3 To: greg@kroah.com
4 From: akpm@osdl.org
5 Date: Sun, 13 Aug 2006 23:24:23 -0700
6 Cc: akpm@osdl.org, dev@openvz.org, stable@kernel.org, haveblue@us.ibm.com, dev@sw.ru, torvalds@osdl.org, oleg@tv-sign.ru
7 Subject: sys_getppid oopses on debug kernel
8
9 From: Kirill Korotaev <dev@sw.ru>
10
11 sys_getppid() optimization can access a freed memory. On kernels with
12 DEBUG_SLAB turned ON, this results in Oops. As Dave Hansen noted, this
13 optimization is also unsafe for memory hotplug.
14
15 So this patch always takes the lock to be safe.
16
17 [oleg@tv-sign.ru: simplifications]
18
19 Signed-off-by: Kirill Korotaev <dev@openvz.org>
20 Cc: Dave Hansen <haveblue@us.ibm.com>
21 Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
22 Signed-off-by: Andrew Morton <akpm@osdl.org>
23 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
24
25 ---
26 kernel/timer.c | 41 +++++++----------------------------------
27 1 file changed, 7 insertions(+), 34 deletions(-)
28
29 --- linux-2.6.17.9.orig/kernel/timer.c
30 +++ linux-2.6.17.9/kernel/timer.c
31 @@ -975,46 +975,19 @@ asmlinkage long sys_getpid(void)
32 }
33
34 /*
35 - * Accessing ->group_leader->real_parent is not SMP-safe, it could
36 - * change from under us. However, rather than getting any lock
37 - * we can use an optimistic algorithm: get the parent
38 - * pid, and go back and check that the parent is still
39 - * the same. If it has changed (which is extremely unlikely
40 - * indeed), we just try again..
41 - *
42 - * NOTE! This depends on the fact that even if we _do_
43 - * get an old value of "parent", we can happily dereference
44 - * the pointer (it was and remains a dereferencable kernel pointer
45 - * no matter what): we just can't necessarily trust the result
46 - * until we know that the parent pointer is valid.
47 - *
48 - * NOTE2: ->group_leader never changes from under us.
49 + * Accessing ->real_parent is not SMP-safe, it could
50 + * change from under us. However, we can use a stale
51 + * value of ->real_parent under rcu_read_lock(), see
52 + * release_task()->call_rcu(delayed_put_task_struct).
53 */
54 asmlinkage long sys_getppid(void)
55 {
56 int pid;
57 - struct task_struct *me = current;
58 - struct task_struct *parent;
59
60 - parent = me->group_leader->real_parent;
61 - for (;;) {
62 - pid = parent->tgid;
63 -#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
64 -{
65 - struct task_struct *old = parent;
66 + rcu_read_lock();
67 + pid = rcu_dereference(current->real_parent)->tgid;
68 + rcu_read_unlock();
69
70 - /*
71 - * Make sure we read the pid before re-reading the
72 - * parent pointer:
73 - */
74 - smp_rmb();
75 - parent = me->group_leader->real_parent;
76 - if (old != parent)
77 - continue;
78 -}
79 -#endif
80 - break;
81 - }
82 return pid;
83 }
84