2006-11-01 05:46:53

by Chris Wright

[permalink] [raw]
Subject: [PATCH 56/61] fill_tgid: fix task_struct leak and possible oops

-stable review patch. If anyone has any objections, please let us know.
------------------

From: Oleg Nesterov <[email protected]>

1. fill_tgid() forgets to do put_task_struct(first).

2. release_task(first) can happen after fill_tgid() drops tasklist_lock,
it is unsafe to dereference first->signal.

This is a temporary fix, imho the locking should be reworked.

Signed-off-by: Oleg Nesterov <[email protected]>
Cc: Shailabh Nagar <[email protected]>
Cc: Balbir Singh <[email protected]>
Cc: Jay Lan <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Chris Wright <[email protected]>
---
kernel/taskstats.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)

--- linux-2.6.18.1.orig/kernel/taskstats.c
+++ linux-2.6.18.1/kernel/taskstats.c
@@ -229,14 +229,17 @@ static int fill_tgid(pid_t tgid, struct
} else
get_task_struct(first);

- /* Start with stats from dead tasks */
- spin_lock_irqsave(&first->signal->stats_lock, flags);
- if (first->signal->stats)
- memcpy(stats, first->signal->stats, sizeof(*stats));
- spin_unlock_irqrestore(&first->signal->stats_lock, flags);

tsk = first;
read_lock(&tasklist_lock);
+ /* Start with stats from dead tasks */
+ if (first->signal) {
+ spin_lock_irqsave(&first->signal->stats_lock, flags);
+ if (first->signal->stats)
+ memcpy(stats, first->signal->stats, sizeof(*stats));
+ spin_unlock_irqrestore(&first->signal->stats_lock, flags);
+ }
+
do {
if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk))
continue;
@@ -256,7 +259,7 @@ static int fill_tgid(pid_t tgid, struct
* Accounting subsytems can also add calls here to modify
* fields of taskstats.
*/
-
+ put_task_struct(first);
return 0;
}


--