diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-10-28 13:38:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-28 14:30:54 -0400 |
commit | 05d5bcd60e8202e5c7b28cf61186043a4d612623 (patch) | |
tree | 7dccbeeb9d0b41103d70f89aae5eb6850f2f788c /kernel/tsacct.c | |
parent | fca178c0c6e8d52a1875be36b070f30884ebfae9 (diff) |
[PATCH] bacct_add_tsk: fix unsafe and wrong parent/group_leader dereference
1. ts = timespec_sub(uptime, current->group_leader->start_time);
It is possible that current != tsk. Probably it was supposed
to be 'tsk->group_leader->start_time. But why we are reading
group_leader's start_time ? This accounting is per thread,
not per procees, I changed this to 'tsk->start_time.
Please corect me.
2. stats->ac_ppid = (tsk->parent) ? tsk->parent->pid : 0;
tsk->parent never == NULL, and it is unsafe to dereference it.
Both the task and it's parent may exit after the caller unlocks
tasklist_lock, the memory could be unmapped (DEBUG_SLAB).
(And we should use ->real_parent->tgid in fact).
Q: I don't understand the 'if (thread_group_leader(tsk))' check.
Why it is needed ?
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Shailabh Nagar <nagar@watson.ibm.com>
Cc: Balbir Singh <balbir@in.ibm.com>
Acked-by: Jay Lan <jlan@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/tsacct.c')
-rw-r--r-- | kernel/tsacct.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/kernel/tsacct.c b/kernel/tsacct.c index db443221ba5b..65a5036a3d95 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c | |||
@@ -36,7 +36,7 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) | |||
36 | 36 | ||
37 | /* calculate task elapsed time in timespec */ | 37 | /* calculate task elapsed time in timespec */ |
38 | do_posix_clock_monotonic_gettime(&uptime); | 38 | do_posix_clock_monotonic_gettime(&uptime); |
39 | ts = timespec_sub(uptime, current->group_leader->start_time); | 39 | ts = timespec_sub(uptime, tsk->start_time); |
40 | /* rebase elapsed time to usec */ | 40 | /* rebase elapsed time to usec */ |
41 | ac_etime = timespec_to_ns(&ts); | 41 | ac_etime = timespec_to_ns(&ts); |
42 | do_div(ac_etime, NSEC_PER_USEC); | 42 | do_div(ac_etime, NSEC_PER_USEC); |
@@ -58,7 +58,10 @@ void bacct_add_tsk(struct taskstats *stats, struct task_struct *tsk) | |||
58 | stats->ac_uid = tsk->uid; | 58 | stats->ac_uid = tsk->uid; |
59 | stats->ac_gid = tsk->gid; | 59 | stats->ac_gid = tsk->gid; |
60 | stats->ac_pid = tsk->pid; | 60 | stats->ac_pid = tsk->pid; |
61 | stats->ac_ppid = (tsk->parent) ? tsk->parent->pid : 0; | 61 | rcu_read_lock(); |
62 | stats->ac_ppid = pid_alive(tsk) ? | ||
63 | rcu_dereference(tsk->real_parent)->tgid : 0; | ||
64 | rcu_read_unlock(); | ||
62 | stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC; | 65 | stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC; |
63 | stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC; | 66 | stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC; |
64 | stats->ac_minflt = tsk->min_flt; | 67 | stats->ac_minflt = tsk->min_flt; |