diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2014-01-03 20:42:18 +0900 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-01-06 10:56:36 +0100 |
commit | 3ec2f427e6f82b9b8f9b18dd2c758b864385df39 (patch) | |
tree | af3cabbed351bc396ac4ff44fbd725e4d8f9b4d6 /drivers/gpu/drm/i915/i915_debugfs.c | |
parent | d8ccba866356e5b8989ff9081df66cf300b1f834 (diff) |
drm/i915: Fix refcount leak and possible NULL pointerdereference.
Since get_pid_task() grabs a reference on the task_struct, we have to drop the
refcount after reading that task's comm name. Use pid_task() with RCU instead.
Also, avoid directly reading like pid_task()->comm because
pid_task() will return NULL if the task have already exit()ed.
This patch fixes both problems.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_debugfs.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6294ffdcc0a..6fe7934b289 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -404,16 +404,26 @@ static int i915_gem_object_info(struct seq_file *m, void* data) seq_putc(m, '\n'); list_for_each_entry_reverse(file, &dev->filelist, lhead) { struct file_stats stats; + struct task_struct *task; memset(&stats, 0, sizeof(stats)); idr_for_each(&file->object_idr, per_file_stats, &stats); + /* + * Although we have a valid reference on file->pid, that does + * not guarantee that the task_struct who called get_pid() is + * still alive (e.g. get_pid(current) => fork() => exit()). + * Therefore, we need to protect this ->comm access using RCU. + */ + rcu_read_lock(); + task = pid_task(file->pid, PIDTYPE_PID); seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu unbound)\n", - get_pid_task(file->pid, PIDTYPE_PID)->comm, + task ? task->comm : "<unknown>", stats.count, stats.total, stats.active, stats.inactive, stats.unbound); + rcu_read_unlock(); } mutex_unlock(&dev->struct_mutex); |