Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1681565 > unrolled thread

[tip:locking/urgent] locking/rwsem-spinlock: Fix EINTR branch in __down_write_common()

Started bytip-bot for Kirill Tkhai <tipbot@zytor.com>
First post2017-07-05 16:40 +0200
Last post2017-07-06 09:50 +0200
Articles 4 — 4 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [tip:locking/urgent] locking/rwsem-spinlock: Fix EINTR branch in  __down_write_common() tip-bot for Kirill Tkhai <tipbot@zytor.com> - 2017-07-05 16:40 +0200
    Re: [tip:locking/urgent] locking/rwsem-spinlock: Fix EINTR branch in  __down_write_common() Niklas Cassel <niklas.cassel@axis.com> - 2017-07-05 16:50 +0200
      Re: [tip:locking/urgent] locking/rwsem-spinlock: Fix EINTR branch in  __down_write_common() Ingo Molnar <mingo@kernel.org> - 2017-07-06 09:30 +0200
        Re: [tip:locking/urgent] locking/rwsem-spinlock: Fix EINTR branch in  __down_write_common() Peter Zijlstra <peterz@infradead.org> - 2017-07-06 09:50 +0200

#1681565 — [tip:locking/urgent] locking/rwsem-spinlock: Fix EINTR branch in __down_write_common()

Fromtip-bot for Kirill Tkhai <tipbot@zytor.com>
Date2017-07-05 16:40 +0200
Subject[tip:locking/urgent] locking/rwsem-spinlock: Fix EINTR branch in __down_write_common()
Message-ID<tZTDc-7v9-19@gated-at.bofh.it>
Commit-ID:  a0c4acd2c220376b4e9690e75782d0c0afdaab9f
Gitweb:     http://git.kernel.org/tip/a0c4acd2c220376b4e9690e75782d0c0afdaab9f
Author:     Kirill Tkhai <ktkhai@virtuozzo.com>
AuthorDate: Fri, 16 Jun 2017 16:44:34 +0300
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 5 Jul 2017 12:26:29 +0200

locking/rwsem-spinlock: Fix EINTR branch in __down_write_common()

If a writer could been woken up, the above branch

	if (sem->count == 0)
		break;

would have moved us to taking the sem. So, it's
not the time to wake a writer now, and only readers
are allowed now. Thus, 0 must be passed to __rwsem_do_wake().

Next, __rwsem_do_wake() wakes readers unconditionally.
But we mustn't do that if the sem is owned by writer
in the moment. Otherwise, writer and reader own the sem
the same time, which leads to memory corruption in
callers.

rwsem-xadd.c does not need that, as:

  1) the similar check is made lockless there,
  2) in __rwsem_mark_wake::try_reader_grant we test,

that sem is not owned by writer.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: <stable@vger.kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Niklas Cassel <niklas.cassel@axis.com>
Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 17fcbd590d0c "locking/rwsem: Fix down_write_killable() for CONFIG_RWSEM_GENERIC_SPINLOCK=y"
Link: http://lkml.kernel.org/r/149762063282.19811.9129615532201147826.stgit@localhost.localdomain
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 kernel/locking/rwsem-spinlock.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c
index c65f798..20819df 100644
--- a/kernel/locking/rwsem-spinlock.c
+++ b/kernel/locking/rwsem-spinlock.c
@@ -231,8 +231,8 @@ int __sched __down_write_common(struct rw_semaphore *sem, int state)
 
 out_nolock:
 	list_del(&waiter.list);
-	if (!list_empty(&sem->wait_list))
-		__rwsem_do_wake(sem, 1);
+	if (!list_empty(&sem->wait_list) && sem->count >= 0)
+		__rwsem_do_wake(sem, 0);
 	raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	return -EINTR;

[toc] | [next] | [standalone]


#1681568

FromNiklas Cassel <niklas.cassel@axis.com>
Date2017-07-05 16:50 +0200
Message-ID<tZTMR-7yB-1@gated-at.bofh.it>
In reply to#1681565
On 07/05/2017 04:27 PM, tip-bot for Kirill Tkhai wrote:
> Commit-ID:  a0c4acd2c220376b4e9690e75782d0c0afdaab9f
> Gitweb:     http://git.kernel.org/tip/a0c4acd2c220376b4e9690e75782d0c0afdaab9f
> Author:     Kirill Tkhai <ktkhai@virtuozzo.com>
> AuthorDate: Fri, 16 Jun 2017 16:44:34 +0300
> Committer:  Ingo Molnar <mingo@kernel.org>
> CommitDate: Wed, 5 Jul 2017 12:26:29 +0200
> 
> locking/rwsem-spinlock: Fix EINTR branch in __down_write_common()
> 
> If a writer could been woken up, the above branch
> 
> 	if (sem->count == 0)
> 		break;
> 
> would have moved us to taking the sem. So, it's
> not the time to wake a writer now, and only readers
> are allowed now. Thus, 0 must be passed to __rwsem_do_wake().
> 
> Next, __rwsem_do_wake() wakes readers unconditionally.
> But we mustn't do that if the sem is owned by writer
> in the moment. Otherwise, writer and reader own the sem
> the same time, which leads to memory corruption in
> callers.
> 
> rwsem-xadd.c does not need that, as:
> 
>   1) the similar check is made lockless there,
>   2) in __rwsem_mark_wake::try_reader_grant we test,
> 
> that sem is not owned by writer.
> 
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Cc: <stable@vger.kernel.org>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Cc: Niklas Cassel <niklas.cassel@axis.com>
> Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Fixes: 17fcbd590d0c "locking/rwsem: Fix down_write_killable() for CONFIG_RWSEM_GENERIC_SPINLOCK=y"
> Link: http://lkml.kernel.org/r/149762063282.19811.9129615532201147826.stgit@localhost.localdomain
> Signed-off-by: Ingo Molnar <mingo@kernel.org>
> ---
>  kernel/locking/rwsem-spinlock.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c
> index c65f798..20819df 100644
> --- a/kernel/locking/rwsem-spinlock.c
> +++ b/kernel/locking/rwsem-spinlock.c
> @@ -231,8 +231,8 @@ int __sched __down_write_common(struct rw_semaphore *sem, int state)
>  
>  out_nolock:
>  	list_del(&waiter.list);
> -	if (!list_empty(&sem->wait_list))
> -		__rwsem_do_wake(sem, 1);
> +	if (!list_empty(&sem->wait_list) && sem->count >= 0)
> +		__rwsem_do_wake(sem, 0);
>  	raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
>  
>  	return -EINTR;
> 

For the record, there is actually a v2 of this:

http://marc.info/?l=linux-kernel&m=149866422128912


Regards,
Niklas

[toc] | [prev] | [next] | [standalone]


#1682123

FromIngo Molnar <mingo@kernel.org>
Date2017-07-06 09:30 +0200
Message-ID<u09oD-1hk-35@gated-at.bofh.it>
In reply to#1681568
* Niklas Cassel <niklas.cassel@axis.com> wrote:

> On 07/05/2017 04:27 PM, tip-bot for Kirill Tkhai wrote:
> > Commit-ID:  a0c4acd2c220376b4e9690e75782d0c0afdaab9f
> > Gitweb:     http://git.kernel.org/tip/a0c4acd2c220376b4e9690e75782d0c0afdaab9f
> > Author:     Kirill Tkhai <ktkhai@virtuozzo.com>
> > AuthorDate: Fri, 16 Jun 2017 16:44:34 +0300
> > Committer:  Ingo Molnar <mingo@kernel.org>
> > CommitDate: Wed, 5 Jul 2017 12:26:29 +0200
> > 
> > locking/rwsem-spinlock: Fix EINTR branch in __down_write_common()
> > 
> > If a writer could been woken up, the above branch
> > 
> > 	if (sem->count == 0)
> > 		break;
> > 
> > would have moved us to taking the sem. So, it's
> > not the time to wake a writer now, and only readers
> > are allowed now. Thus, 0 must be passed to __rwsem_do_wake().
> > 
> > Next, __rwsem_do_wake() wakes readers unconditionally.
> > But we mustn't do that if the sem is owned by writer
> > in the moment. Otherwise, writer and reader own the sem
> > the same time, which leads to memory corruption in
> > callers.
> > 
> > rwsem-xadd.c does not need that, as:
> > 
> >   1) the similar check is made lockless there,
> >   2) in __rwsem_mark_wake::try_reader_grant we test,
> > 
> > that sem is not owned by writer.
> > 
> > Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
> > Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> > Cc: <stable@vger.kernel.org>
> > Cc: Linus Torvalds <torvalds@linux-foundation.org>
> > Cc: Niklas Cassel <niklas.cassel@axis.com>
> > Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
> > Cc: Peter Zijlstra <peterz@infradead.org>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Fixes: 17fcbd590d0c "locking/rwsem: Fix down_write_killable() for CONFIG_RWSEM_GENERIC_SPINLOCK=y"
> > Link: http://lkml.kernel.org/r/149762063282.19811.9129615532201147826.stgit@localhost.localdomain
> > Signed-off-by: Ingo Molnar <mingo@kernel.org>
> > ---
> >  kernel/locking/rwsem-spinlock.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/kernel/locking/rwsem-spinlock.c b/kernel/locking/rwsem-spinlock.c
> > index c65f798..20819df 100644
> > --- a/kernel/locking/rwsem-spinlock.c
> > +++ b/kernel/locking/rwsem-spinlock.c
> > @@ -231,8 +231,8 @@ int __sched __down_write_common(struct rw_semaphore *sem, int state)
> >  
> >  out_nolock:
> >  	list_del(&waiter.list);
> > -	if (!list_empty(&sem->wait_list))
> > -		__rwsem_do_wake(sem, 1);
> > +	if (!list_empty(&sem->wait_list) && sem->count >= 0)
> > +		__rwsem_do_wake(sem, 0);
> >  	raw_spin_unlock_irqrestore(&sem->wait_lock, flags);
> >  
> >  	return -EINTR;
> > 
> 
> For the record, there is actually a v2 of this:
> 
> http://marc.info/?l=linux-kernel&m=149866422128912

Hm, so I missed that because it was within the discussion - please post v2 patches 
with a new subject line next time around.

But I also disagree with -v2 mildly: in practice a >= test has the same CPU 
overhead as a > test, and if we rely on the earlier "sem->count == 0" test then we 
should also comment on that.

It's more straightforward to just do the canonical sem->count >= 0 test that we do 
elsewhere in the rwsem-spinlock code.

PeterZ, what's your preference?

Thanks,

	Ingo

[toc] | [prev] | [next] | [standalone]


#1682136

FromPeter Zijlstra <peterz@infradead.org>
Date2017-07-06 09:50 +0200
Message-ID<u09HX-1nl-9@gated-at.bofh.it>
In reply to#1682123
On Thu, Jul 06, 2017 at 09:28:58AM +0200, Ingo Molnar wrote:
> It's more straightforward to just do the canonical sem->count >= 0 test that we do 
> elsewhere in the rwsem-spinlock code.
> 
> PeterZ, what's your preference?

Leave it as is.. it doesn't matter (the 0 case shouldn't happen) and as
you say >= 0 is what most other code does.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web