2010-11-25 01:10:00

by Dave Jones

[permalink] [raw]
Subject: rcu_read_lock/unlock protect find_task_by_vpid call in posix_cpu_timer_create

===================================================
[ INFO: suspicious rcu_dereference_check() usage. ]
---------------------------------------------------
kernel/pid.c:419 invoked rcu_dereference_check() without protection!

other info that might help us debug this:


rcu_scheduler_active = 1, debug_locks = 1
1 lock held by scrashme/20820:
#0: (tasklist_lock){.?.?..}, at: [<ffffffff8106e30f>] posix_cpu_timer_create+0x50/0xee

stack backtrace:
Pid: 20820, comm: scrashme Not tainted 2.6.37-rc3+ #7
Call Trace:
[<ffffffff8107cfd5>] lockdep_rcu_dereference+0x9d/0xa5
[<ffffffff81069d08>] find_task_by_pid_ns+0x44/0x5d
[<ffffffff81069d43>] find_task_by_vpid+0x22/0x24
[<ffffffff8106e32d>] posix_cpu_timer_create+0x6e/0xee
[<ffffffff8106eb88>] do_cpu_nanosleep+0x83/0x1ad
[<ffffffff8106f50a>] posix_cpu_nsleep+0x6d/0xf6
[<ffffffff810f9a64>] ? might_fault+0xa5/0xac
[<ffffffff810f9a1b>] ? might_fault+0x5c/0xac
[<ffffffff8106bf57>] sys_clock_nanosleep+0x7c/0xcb
[<ffffffff81009cb2>] system_call_fastpath+0x16/0x1b

Signed-off-by: Dave Jones <[email protected]>

diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 6842eeb..2658955 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -391,6 +391,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
INIT_LIST_HEAD(&new_timer->it.cpu.entry);

read_lock(&tasklist_lock);
+ rcu_read_lock();
if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
if (pid == 0) {
p = current;
@@ -414,6 +415,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
} else {
ret = -EINVAL;
}
+ rcu_read_unlock();
read_unlock(&tasklist_lock);

return ret;


2010-11-25 01:36:08

by Dave Jones

[permalink] [raw]
Subject: rcu_read_lock/unlock protect find_task_by_vpid call in check_clock

===================================================
[ INFO: suspicious rcu_dereference_check() usage. ]
---------------------------------------------------
kernel/pid.c:419 invoked rcu_dereference_check() without protection!

other info that might help us debug this:


rcu_scheduler_active = 1, debug_locks = 1
1 lock held by scrashme/13382:
#0: (tasklist_lock){.?.?..}, at: [<ffffffff8106ddea>] check_clock+0x46/0x9a

stack backtrace:
Pid: 13382, comm: scrashme Not tainted 2.6.37-rc3+ #8
Call Trace:
[<ffffffff8107cfe1>] lockdep_rcu_dereference+0x9d/0xa5
[<ffffffff81069d08>] find_task_by_pid_ns+0x44/0x5d
[<ffffffff81069d43>] find_task_by_vpid+0x22/0x24
[<ffffffff8106ddf2>] check_clock+0x4e/0x9a
[<ffffffff8106deac>] posix_cpu_clock_getres+0x16/0x41
[<ffffffff8106be74>] sys_clock_getres+0x39/0xa0
[<ffffffff81009cb2>] system_call_fastpath+0x16/0x1b

Signed-off-by: Dave Jones <[email protected]>

diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 6842eeb..4bef9aa 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -38,11 +38,13 @@ static int check_clock(const clockid_t which_clock)
return 0;

read_lock(&tasklist_lock);
+ rcu_read_lock();
p = find_task_by_vpid(pid);
if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ?
same_thread_group(p, current) : thread_group_leader(p))) {
error = -EINVAL;
}
+ rcu_read_unlock();
read_unlock(&tasklist_lock);

return error;

2010-11-25 08:40:22

by Peter Zijlstra

[permalink] [raw]
Subject: Re: rcu_read_lock/unlock protect find_task_by_vpid call in posix_cpu_timer_create

On Wed, 2010-11-24 at 20:09 -0500, Dave Jones wrote:
> ===================================================
> [ INFO: suspicious rcu_dereference_check() usage. ]
> ---------------------------------------------------
> kernel/pid.c:419 invoked rcu_dereference_check() without protection!
>
> other info that might help us debug this:
>
>
> rcu_scheduler_active = 1, debug_locks = 1
> 1 lock held by scrashme/20820:
> #0: (tasklist_lock){.?.?..}, at: [<ffffffff8106e30f>] posix_cpu_timer_create+0x50/0xee
>
> stack backtrace:
> Pid: 20820, comm: scrashme Not tainted 2.6.37-rc3+ #7
> Call Trace:
> [<ffffffff8107cfd5>] lockdep_rcu_dereference+0x9d/0xa5
> [<ffffffff81069d08>] find_task_by_pid_ns+0x44/0x5d
> [<ffffffff81069d43>] find_task_by_vpid+0x22/0x24
> [<ffffffff8106e32d>] posix_cpu_timer_create+0x6e/0xee
> [<ffffffff8106eb88>] do_cpu_nanosleep+0x83/0x1ad
> [<ffffffff8106f50a>] posix_cpu_nsleep+0x6d/0xf6
> [<ffffffff810f9a64>] ? might_fault+0xa5/0xac
> [<ffffffff810f9a1b>] ? might_fault+0x5c/0xac
> [<ffffffff8106bf57>] sys_clock_nanosleep+0x7c/0xcb
> [<ffffffff81009cb2>] system_call_fastpath+0x16/0x1b
>
> Signed-off-by: Dave Jones <[email protected]>
>
> diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
> index 6842eeb..2658955 100644
> --- a/kernel/posix-cpu-timers.c
> +++ b/kernel/posix-cpu-timers.c
> @@ -391,6 +391,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> INIT_LIST_HEAD(&new_timer->it.cpu.entry);
>
> read_lock(&tasklist_lock);
> + rcu_read_lock();
> if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
> if (pid == 0) {
> p = current;
> @@ -414,6 +415,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> } else {
> ret = -EINVAL;
> }
> + rcu_read_unlock();
> read_unlock(&tasklist_lock);
>
> return ret;

Do we still need the tasklist_lock in this case?

Also, why is that think complaining, surely the tasklist_lock pins any
and all PID objects?

2010-11-25 08:40:38

by Peter Zijlstra

[permalink] [raw]
Subject: Re: rcu_read_lock/unlock protect find_task_by_vpid call in check_clock

On Wed, 2010-11-24 at 20:35 -0500, Dave Jones wrote:
> ===================================================
> [ INFO: suspicious rcu_dereference_check() usage. ]
> ---------------------------------------------------
> kernel/pid.c:419 invoked rcu_dereference_check() without protection!
>
> other info that might help us debug this:
>
>
> rcu_scheduler_active = 1, debug_locks = 1
> 1 lock held by scrashme/13382:
> #0: (tasklist_lock){.?.?..}, at: [<ffffffff8106ddea>] check_clock+0x46/0x9a
>
> stack backtrace:
> Pid: 13382, comm: scrashme Not tainted 2.6.37-rc3+ #8
> Call Trace:
> [<ffffffff8107cfe1>] lockdep_rcu_dereference+0x9d/0xa5
> [<ffffffff81069d08>] find_task_by_pid_ns+0x44/0x5d
> [<ffffffff81069d43>] find_task_by_vpid+0x22/0x24
> [<ffffffff8106ddf2>] check_clock+0x4e/0x9a
> [<ffffffff8106deac>] posix_cpu_clock_getres+0x16/0x41
> [<ffffffff8106be74>] sys_clock_getres+0x39/0xa0
> [<ffffffff81009cb2>] system_call_fastpath+0x16/0x1b
>
> Signed-off-by: Dave Jones <[email protected]>
>
> diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
> index 6842eeb..4bef9aa 100644
> --- a/kernel/posix-cpu-timers.c
> +++ b/kernel/posix-cpu-timers.c
> @@ -38,11 +38,13 @@ static int check_clock(const clockid_t which_clock)
> return 0;
>
> read_lock(&tasklist_lock);
> + rcu_read_lock();
> p = find_task_by_vpid(pid);
> if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ?
> same_thread_group(p, current) : thread_group_leader(p))) {
> error = -EINVAL;
> }
> + rcu_read_unlock();
> read_unlock(&tasklist_lock);
>
> return error;


Pretty much the same comment as the other patch..

<copy/paste>

Do we still need the tasklist_lock in this case?

Also, why is that think complaining, surely the tasklist_lock pins any
and all PID objects?

2010-11-25 11:07:16

by Oleg Nesterov

[permalink] [raw]
Subject: Re: rcu_read_lock/unlock protect find_task_by_vpid call in posix_cpu_timer_create

(add Sergey)

On 11/25, Peter Zijlstra wrote:
>
> On Wed, 2010-11-24 at 20:09 -0500, Dave Jones wrote:
> > --- a/kernel/posix-cpu-timers.c
> > +++ b/kernel/posix-cpu-timers.c
> > @@ -391,6 +391,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> > INIT_LIST_HEAD(&new_timer->it.cpu.entry);
> >
> > read_lock(&tasklist_lock);
> > + rcu_read_lock();
> > if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
> > if (pid == 0) {
> > p = current;
> > @@ -414,6 +415,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> > } else {
> > ret = -EINVAL;
> > }
> > + rcu_read_unlock();
> > read_unlock(&tasklist_lock);
> >
> > return ret;
>
> Do we still need the tasklist_lock in this case?

No. posix-cpu-timer.c shouldn't use tasklist at all. But it is not
completely trivial to remove it.

In particular, this patch is not exactly right, we can't trust
thread_group_leader() without tasklist.

Sergey already sent the patch which removes tasklist from
posix_cpu_timer_create() and posix_cpu_timer_create(), and iirc
Thomas queued it.

> Also, why is that think complaining, surely the tasklist_lock pins any
> and all PID objects?

The only problem is: if copy_process() fails, it does free_pid()
lockless. This means, without rcu lock it is not safe to scan the
rcu-protected lists.

We can change copy_process() (in fact I sent the patch several
years ago), but everybody think that find_pid/etc should always
take rcu_read_lock() instead. I tend to agree.

Oleg.

2010-11-25 11:09:18

by Oleg Nesterov

[permalink] [raw]
Subject: Re: rcu_read_lock/unlock protect find_task_by_vpid call in posix_cpu_timer_create

(another try, actually add Sergey)

On 11/25, Peter Zijlstra wrote:
>
> On Wed, 2010-11-24 at 20:09 -0500, Dave Jones wrote:
> > --- a/kernel/posix-cpu-timers.c
> > +++ b/kernel/posix-cpu-timers.c
> > @@ -391,6 +391,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> > INIT_LIST_HEAD(&new_timer->it.cpu.entry);
> >
> > read_lock(&tasklist_lock);
> > + rcu_read_lock();
> > if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
> > if (pid == 0) {
> > p = current;
> > @@ -414,6 +415,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> > } else {
> > ret = -EINVAL;
> > }
> > + rcu_read_unlock();
> > read_unlock(&tasklist_lock);
> >
> > return ret;
>
> Do we still need the tasklist_lock in this case?

No. posix-cpu-timer.c shouldn't use tasklist at all. But it is not
completely trivial to remove it.

In particular, this patch is not exactly right, we can't trust
thread_group_leader() without tasklist.

Sergey already sent the patch which removes tasklist from
posix_cpu_timer_create() and posix_cpu_timer_create(), and iirc
Thomas queued it.

> Also, why is that think complaining, surely the tasklist_lock pins any
> and all PID objects?

The only problem is: if copy_process() fails, it does free_pid()
lockless. This means, without rcu lock it is not safe to scan the
rcu-protected lists.

We can change copy_process() (in fact I sent the patch several
years ago), but everybody think that find_pid/etc should always
take rcu_read_lock() instead. I tend to agree.

Oleg.

2010-11-25 11:27:23

by Sergey Senozhatsky

[permalink] [raw]
Subject: Re: rcu_read_lock/unlock protect find_task_by_vpid call in posix_cpu_timer_create

Hello,

On (11/25/10 12:02), Oleg Nesterov wrote:
> (another try, actually add Sergey)
>
Thank you.

> On 11/25, Peter Zijlstra wrote:
> >
> > On Wed, 2010-11-24 at 20:09 -0500, Dave Jones wrote:
> > > --- a/kernel/posix-cpu-timers.c
> > > +++ b/kernel/posix-cpu-timers.c
> > > @@ -391,6 +391,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> > > INIT_LIST_HEAD(&new_timer->it.cpu.entry);
> > >
> > > read_lock(&tasklist_lock);
> > > + rcu_read_lock();
> > > if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
> > > if (pid == 0) {
> > > p = current;
> > > @@ -414,6 +415,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
> > > } else {
> > > ret = -EINVAL;
> > > }
> > > + rcu_read_unlock();
> > > read_unlock(&tasklist_lock);
> > >
> > > return ret;
> >
> > Do we still need the tasklist_lock in this case?
>
> No. posix-cpu-timer.c shouldn't use tasklist at all. But it is not
> completely trivial to remove it.
>
> In particular, this patch is not exactly right, we can't trust
> thread_group_leader() without tasklist.
>
> Sergey already sent the patch which removes tasklist from
> posix_cpu_timer_create() and posix_cpu_timer_create(), and iirc
> Thomas queued it.
>

You're right, Oleg.

Commit-ID: c0deae8c9587419ab13874b74425ce2eb2e18508
Gitweb: http://git.kernel.org/tip/c0deae8c9587419ab13874b74425ce2eb2e18508
Author: Sergey Senozhatsky <[email protected]>
AuthorDate: Wed, 3 Nov 2010 18:52:56 +0200
Committer: Thomas Gleixner <[email protected]>
CommitDate: Wed, 10 Nov 2010 13:07:06 +0100

posix-cpu-timers: Rcu_read_lock/unlock protect find_task_by_vpid call

queued (15 days so far).


> > Also, why is that think complaining, surely the tasklist_lock pins any
> > and all PID objects?
>
> The only problem is: if copy_process() fails, it does free_pid()
> lockless. This means, without rcu lock it is not safe to scan the
> rcu-protected lists.
>
> We can change copy_process() (in fact I sent the patch several
> years ago), but everybody think that find_pid/etc should always
> take rcu_read_lock() instead. I tend to agree.
>
> Oleg.
>

Sergey


Attachments:
(No filename) (2.09 kB)
(No filename) (316.00 B)
Download all attachments