* [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
@ 2013-12-24 11:50 Tetsuo Handa
2013-12-25 21:52 ` Chris Wilson
0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2013-12-24 11:50 UTC (permalink / raw)
To: chris, ben, daniel.vetter; +Cc: linux-kernel
>From 482be6384379072eb4c0d45d0ab8a25df4f59ed7 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Date: Tue, 24 Dec 2013 18:04:14 +0900
Subject: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
Since get_pid_task() grabs a reference on the task_struct, we have to drop the
refcount after reading that task's comm name. Also, directly reading like
get_pid_task()->comm can trigger an oops when get_pid_task() returned NULL.
This patch fixes both problems.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
drivers/gpu/drm/i915/i915_debugfs.c | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 6ed45a9..d0a8e0a 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -406,11 +406,20 @@ 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;
+ char name[TASK_COMM_LEN];
memset(&stats, 0, sizeof(stats));
idr_for_each(&file->object_idr, per_file_stats, &stats);
+ task = get_pid_task(file->pid, PIDTYPE_PID);
+ if (task) {
+ get_task_comm(name, task);
+ put_task_struct(task);
+ } else {
+ strlcpy(name, "<unknown>", sizeof(name));
+ }
seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu unbound)\n",
- get_pid_task(file->pid, PIDTYPE_PID)->comm,
+ name,
stats.count,
stats.total,
stats.active,
--
1.7.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
2013-12-24 11:50 [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference Tetsuo Handa
@ 2013-12-25 21:52 ` Chris Wilson
2013-12-26 0:45 ` Tetsuo Handa
2014-01-03 11:42 ` [PATCH] drm/i915: Fix refcount leak and possible NULL pointerdereference Tetsuo Handa
0 siblings, 2 replies; 7+ messages in thread
From: Chris Wilson @ 2013-12-25 21:52 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: ben, daniel.vetter, linux-kernel
On Tue, Dec 24, 2013 at 08:50:23PM +0900, Tetsuo Handa wrote:
> >From 482be6384379072eb4c0d45d0ab8a25df4f59ed7 Mon Sep 17 00:00:00 2001
> From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> Date: Tue, 24 Dec 2013 18:04:14 +0900
> Subject: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
>
> Since get_pid_task() grabs a reference on the task_struct, we have to drop the
> refcount after reading that task's comm name. Also, directly reading like
> get_pid_task()->comm can trigger an oops when get_pid_task() returned NULL.
The second issue is moot as file itself cannot exist if the task_struct
is NULL, and the task_struct cannot be destroyed until we finish the
function. The simpler fix would appear to be s/get_pid_task/pid_task/
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
2013-12-25 21:52 ` Chris Wilson
@ 2013-12-26 0:45 ` Tetsuo Handa
2014-01-03 11:42 ` [PATCH] drm/i915: Fix refcount leak and possible NULL pointerdereference Tetsuo Handa
1 sibling, 0 replies; 7+ messages in thread
From: Tetsuo Handa @ 2013-12-26 0:45 UTC (permalink / raw)
To: chris; +Cc: ben, daniel.vetter, linux-kernel
Hello.
Chris Wilson wrote:
> > Since get_pid_task() grabs a reference on the task_struct, we have to drop the
> > refcount after reading that task\'s comm name. Also, directly reading like
> > get_pid_task()->comm can trigger an oops when get_pid_task() returned NULL.
>
> The second issue is moot as file itself cannot exist if the task_struct
> is NULL, and the task_struct cannot be destroyed until we finish the
> function. The simpler fix would appear to be s/get_pid_task/pid_task/
I didn\'t catch. Please see below sample module.
pid_task() will return NULL if the target task has already died.
The target task could be killed (e.g. by the OOM killer) at any time, and
whether the target task\'s task_struct is not yet destroyed is irrelevant
for pid_task().
get_pid_task(file->pid, PIDTYPE_PID)->comm by chance didn\'t trigger
oops because offsetof(struct task_struct, comm) < PAGE_SIZE is true.
---------- sample start ----------
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/kthread.h>
static int test_thread(void *unused)
{
return 0;
}
static int __init test_init(void)
{
struct task_struct *task = kthread_create(test_thread, NULL, \"test\");
if (!IS_ERR(task)) {
struct pid *pid;
struct task_struct *t;
get_task_struct(task);
pid = get_pid(task->pids[PIDTYPE_PID].pid);
rcu_read_lock();
t = pid_task(pid, PIDTYPE_PID);
rcu_read_unlock();
printk(\"pid_task(%p)=%p\\n\", pid, t);
wake_up_process(task);
ssleep(1);
rcu_read_lock();
t = pid_task(pid, PIDTYPE_PID);
rcu_read_unlock();
printk(\"pid_task(%p)=%p\\n\", pid, t);
put_task_struct(task);
put_pid(pid);
}
return -EINVAL;
}
module_init(test_init);
MODULE_LICENSE(\"GPL\");
---------- sample end ----------
---------- output start ----------
pid_task(ffff8800474bff80)=ffff8800435b0e10
pid_task(ffff8800474bff80)= (null)
---------- output end ----------
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] drm/i915: Fix refcount leak and possible NULL pointerdereference.
2013-12-25 21:52 ` Chris Wilson
2013-12-26 0:45 ` Tetsuo Handa
@ 2014-01-03 11:42 ` Tetsuo Handa
2014-01-03 12:51 ` Chris Wilson
1 sibling, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2014-01-03 11:42 UTC (permalink / raw)
To: chris; +Cc: ben, daniel.vetter, linux-kernel
Chris Wilson wrote:
> On Tue, Dec 24, 2013 at 08:50:23PM +0900, Tetsuo Handa wrote:
> > >From 482be6384379072eb4c0d45d0ab8a25df4f59ed7 Mon Sep 17 00:00:00 2001
> > From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > Date: Tue, 24 Dec 2013 18:04:14 +0900
> > Subject: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
> >
> > Since get_pid_task() grabs a reference on the task_struct, we have to drop the
> > refcount after reading that task's comm name. Also, directly reading like
> > get_pid_task()->comm can trigger an oops when get_pid_task() returned NULL.
>
> The second issue is moot as file itself cannot exist if the task_struct
> is NULL, and the task_struct cannot be destroyed until we finish the
> function. The simpler fix would appear to be s/get_pid_task/pid_task/
If I understand correctly, priv->pid = get_pid(task_pid(current)); in
drm_open_helper() grabs a reference on "struct pid" before adding to
&dev->filelist, and put_pid(file_priv->pid); in drm_release() releases that
reference after removing from &dev->filelist.
So, you meant that mutex_lock_interruptible(&dev->struct_mutex); in
i915_gem_object_info() prevents drm_release() from calling put_pid() ?
Then, this file->pid in &dev->filelist keeps at least one reference.
OK. Updated patch follows.
----------
>From 5ea824bc84f65d2265addc81e1adacc8baf82d48 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Date: Fri, 3 Jan 2014 20:30:41 +0900
Subject: [PATCH v2] drm/i915: Fix refcount leak and possible NULL pointer dereference.
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>
---
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 6ed45a9..91c26b6 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -406,16 +406,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);
--
1.7.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] drm/i915: Fix refcount leak and possible NULL pointerdereference.
2014-01-03 11:42 ` [PATCH] drm/i915: Fix refcount leak and possible NULL pointerdereference Tetsuo Handa
@ 2014-01-03 12:51 ` Chris Wilson
2014-01-05 1:08 ` [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference Tetsuo Handa
0 siblings, 1 reply; 7+ messages in thread
From: Chris Wilson @ 2014-01-03 12:51 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: ben, daniel.vetter, linux-kernel
On Fri, Jan 03, 2014 at 08:42:18PM +0900, Tetsuo Handa wrote:
> Chris Wilson wrote:
> > On Tue, Dec 24, 2013 at 08:50:23PM +0900, Tetsuo Handa wrote:
> > > >From 482be6384379072eb4c0d45d0ab8a25df4f59ed7 Mon Sep 17 00:00:00 2001
> > > From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> > > Date: Tue, 24 Dec 2013 18:04:14 +0900
> > > Subject: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
> > >
> > > Since get_pid_task() grabs a reference on the task_struct, we have to drop the
> > > refcount after reading that task's comm name. Also, directly reading like
> > > get_pid_task()->comm can trigger an oops when get_pid_task() returned NULL.
> >
> > The second issue is moot as file itself cannot exist if the task_struct
> > is NULL, and the task_struct cannot be destroyed until we finish the
> > function. The simpler fix would appear to be s/get_pid_task/pid_task/
>
> If I understand correctly, priv->pid = get_pid(task_pid(current)); in
> drm_open_helper() grabs a reference on "struct pid" before adding to
> &dev->filelist, and put_pid(file_priv->pid); in drm_release() releases that
> reference after removing from &dev->filelist.
>
> So, you meant that mutex_lock_interruptible(&dev->struct_mutex); in
> i915_gem_object_info() prevents drm_release() from calling put_pid() ?
Right, my understanding is that since we take the struct_mutex during
release of the filp (and across this list walker) that is sufficient
serialisation to prevent the task struct from disappearing from
underneath us.
> Then, this file->pid in &dev->filelist keeps at least one reference.
> OK. Updated patch follows.
Looks good to me, and the comment is great.
-Chris
--
Chris Wilson, Intel Open Source Technology Centre
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
2014-01-03 12:51 ` Chris Wilson
@ 2014-01-05 1:08 ` Tetsuo Handa
2014-01-06 9:57 ` Daniel Vetter
0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2014-01-05 1:08 UTC (permalink / raw)
To: chris; +Cc: ben, daniel.vetter, linux-kernel
Chris Wilson wrote:
> > Then, this file->pid in &dev->filelist keeps at least one reference.
> > OK. Updated patch follows.
>
> Looks good to me, and the comment is great.
> -Chris
Please pick up this patch via your git tree.
Also, please change from "<unknown>" to whatever you like. For example,
dump_holder() in fs/gfs2/glock.c uses "(ended)" if comm is not available.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference.
2014-01-05 1:08 ` [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference Tetsuo Handa
@ 2014-01-06 9:57 ` Daniel Vetter
0 siblings, 0 replies; 7+ messages in thread
From: Daniel Vetter @ 2014-01-06 9:57 UTC (permalink / raw)
To: Tetsuo Handa
Cc: chris, ben, daniel.vetter, linux-kernel, Intel Graphics Development
On Sun, Jan 05, 2014 at 10:08:42AM +0900, Tetsuo Handa wrote:
> Chris Wilson wrote:
> > > Then, this file->pid in &dev->filelist keeps at least one reference.
> > > OK. Updated patch follows.
> >
> > Looks good to me, and the comment is great.
> > -Chris
>
> Please pick up this patch via your git tree.
>
> Also, please change from "<unknown>" to whatever you like. For example,
> dump_holder() in fs/gfs2/glock.c uses "(ended)" if comm is not available.
Queued for -next, thanks for the patch.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2014-01-06 9:55 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-24 11:50 [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference Tetsuo Handa
2013-12-25 21:52 ` Chris Wilson
2013-12-26 0:45 ` Tetsuo Handa
2014-01-03 11:42 ` [PATCH] drm/i915: Fix refcount leak and possible NULL pointerdereference Tetsuo Handa
2014-01-03 12:51 ` Chris Wilson
2014-01-05 1:08 ` [PATCH] drm/i915: Fix refcount leak and possible NULL pointer dereference Tetsuo Handa
2014-01-06 9:57 ` Daniel Vetter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome