Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751650AbdF1NUe (ORCPT ); Wed, 28 Jun 2017 09:20:34 -0400 Received: from bes.se.axis.com ([195.60.68.10]:51554 "EHLO bes.se.axis.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751087AbdF1NU3 (ORCPT ); Wed, 28 Jun 2017 09:20:29 -0400 Subject: Re: [PATCH] rwsem-spinlock: Fix EINTR branch in __down_write_common() To: Kirill Tkhai , , , References: <149762063282.19811.9129615532201147826.stgit@localhost.localdomain> From: Niklas Cassel Message-ID: <76aba539-a6c7-66e8-2088-d0f5938535dc@axis.com> Date: Wed, 28 Jun 2017 15:20:20 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: <149762063282.19811.9129615532201147826.stgit@localhost.localdomain> Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 7bit X-Originating-IP: [10.0.5.60] X-ClientProxiedBy: XBOX03.axis.com (10.0.5.17) To XBOX02.axis.com (10.0.5.16) X-TM-AS-GCONF: 00 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2096 Lines: 68 Good catch! This should go to -stable as well. Perhaps if (!list_empty(&sem->wait_list) && sem->count > 0) __rwsem_do_wake(sem, 0); Rather than if (!list_empty(&sem->wait_list) && sem->count >= 0) __rwsem_do_wake(sem, 0); Since we have the spinlock, and since we just checked if sem->count == 0, we still know that it can't be 0. Either way: Acked-by: Niklas Cassel On 06/16/2017 03:44 PM, Kirill Tkhai wrote: > 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. > > Fixes: 17fcbd590d0c "locking/rwsem: Fix down_write_killable() for CONFIG_RWSEM_GENERIC_SPINLOCK=y" > Signed-off-by: Kirill Tkhai > CC: Niklas Cassel > CC: Peter Zijlstra (Intel) > CC: Ingo Molnar > --- > 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 c65f7989f850..20819df98125 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; >