From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1426036AbcFHO0R (ORCPT ); Wed, 8 Jun 2016 10:26:17 -0400 Received: from terminus.zytor.com ([198.137.202.10]:34588 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1426008AbcFHO0N (ORCPT ); Wed, 8 Jun 2016 10:26:13 -0400 Date: Wed, 8 Jun 2016 07:25:29 -0700 From: tip-bot for Waiman Long Message-ID: Cc: mingo@kernel.org, tglx@linutronix.de, jason.low2@hp.com, linux-kernel@vger.kernel.org, doug.hatch@hpe.com, david@fromorbit.com, Waiman.Long@hpe.com, peter@hurleysoftware.com, torvalds@linux-foundation.org, peterz@infradead.org, dave@stgolabs.net, akpm@linux-foundation.org, paulmck@linux.vnet.ibm.com, scott.norton@hpe.com, hpa@zytor.com Reply-To: peterz@infradead.org, torvalds@linux-foundation.org, peter@hurleysoftware.com, hpa@zytor.com, paulmck@linux.vnet.ibm.com, scott.norton@hpe.com, dave@stgolabs.net, akpm@linux-foundation.org, jason.low2@hp.com, tglx@linutronix.de, mingo@kernel.org, doug.hatch@hpe.com, Waiman.Long@hpe.com, david@fromorbit.com, linux-kernel@vger.kernel.org In-Reply-To: <1463534783-38814-3-git-send-email-Waiman.Long@hpe.com> References: <1463534783-38814-3-git-send-email-Waiman.Long@hpe.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:locking/core] locking/rwsem: Protect all writes to owner by WRITE_ONCE() Git-Commit-ID: fb6a44f33be542fd81575ff93a4e8118d6a58592 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: fb6a44f33be542fd81575ff93a4e8118d6a58592 Gitweb: http://git.kernel.org/tip/fb6a44f33be542fd81575ff93a4e8118d6a58592 Author: Waiman Long AuthorDate: Tue, 17 May 2016 21:26:20 -0400 Committer: Ingo Molnar CommitDate: Wed, 8 Jun 2016 15:16:59 +0200 locking/rwsem: Protect all writes to owner by WRITE_ONCE() Without using WRITE_ONCE(), the compiler can potentially break a write into multiple smaller ones (store tearing). So a read from the same data by another task concurrently may return a partial result. This can result in a kernel crash if the data is a memory address that is being dereferenced. This patch changes all write to rwsem->owner to use WRITE_ONCE() to make sure that store tearing will not happen. READ_ONCE() may not be needed for rwsem->owner as long as the value is only used for comparison and not dereferencing. Signed-off-by: Waiman Long Signed-off-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Dave Chinner Cc: Davidlohr Bueso Cc: Douglas Hatch Cc: Jason Low Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Hurley Cc: Peter Zijlstra Cc: Scott J Norton Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1463534783-38814-3-git-send-email-Waiman.Long@hpe.com Signed-off-by: Ingo Molnar --- kernel/locking/rwsem.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h index 8f43ba2..a699f40 100644 --- a/kernel/locking/rwsem.h +++ b/kernel/locking/rwsem.h @@ -16,14 +16,21 @@ #define RWSEM_READER_OWNED ((struct task_struct *)1UL) #ifdef CONFIG_RWSEM_SPIN_ON_OWNER +/* + * All writes to owner are protected by WRITE_ONCE() to make sure that + * store tearing can't happen as optimistic spinners may read and use + * the owner value concurrently without lock. Read from owner, however, + * may not need READ_ONCE() as long as the pointer value is only used + * for comparison and isn't being dereferenced. + */ static inline void rwsem_set_owner(struct rw_semaphore *sem) { - sem->owner = current; + WRITE_ONCE(sem->owner, current); } static inline void rwsem_clear_owner(struct rw_semaphore *sem) { - sem->owner = NULL; + WRITE_ONCE(sem->owner, NULL); } static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) @@ -34,7 +41,7 @@ static inline void rwsem_set_reader_owned(struct rw_semaphore *sem) * to minimize cacheline contention. */ if (sem->owner != RWSEM_READER_OWNED) - sem->owner = RWSEM_READER_OWNED; + WRITE_ONCE(sem->owner, RWSEM_READER_OWNED); } static inline bool rwsem_owner_is_writer(struct task_struct *owner)