Commit 05d5bcd60e8202e5c7b28cf61186043a4d612623

Authored by Oleg Nesterov
Committed by Linus Torvalds
1 parent fca178c0c6

[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>

Showing 1 changed file with 5 additions and 2 deletions Side-by-side Diff

... ... @@ -36,7 +36,7 @@
36 36  
37 37 /* calculate task elapsed time in timespec */
38 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 40 /* rebase elapsed time to usec */
41 41 ac_etime = timespec_to_ns(&ts);
42 42 do_div(ac_etime, NSEC_PER_USEC);
... ... @@ -58,7 +58,10 @@
58 58 stats->ac_uid = tsk->uid;
59 59 stats->ac_gid = tsk->gid;
60 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 65 stats->ac_utime = cputime_to_msecs(tsk->utime) * USEC_PER_MSEC;
63 66 stats->ac_stime = cputime_to_msecs(tsk->stime) * USEC_PER_MSEC;
64 67 stats->ac_minflt = tsk->min_flt;