From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752004AbbIQNYf (ORCPT ); Thu, 17 Sep 2015 09:24:35 -0400 Received: from mail-wi0-f179.google.com ([209.85.212.179]:34501 "EHLO mail-wi0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751921AbbIQNYd (ORCPT ); Thu, 17 Sep 2015 09:24:33 -0400 From: Dmitry Vyukov To: ebiederm@xmission.com, viro@zeniv.linux.org.uk, akpm@linux-foundation.org, oleg@redhat.com, mingo@kernel.org, paulmck@linux.vnet.ibm.com, mhocko@suse.cz Cc: linux-kernel@vger.kernel.org, ktsan@googlegroups.com, kcc@google.com, andreyknvl@google.com, glider@google.com, hboehm@google.com, Dmitry Vyukov Subject: [PATCH] kernel: fix data race in put_pid Date: Thu, 17 Sep 2015 15:24:28 +0200 Message-Id: <1442496268-47803-1-git-send-email-dvyukov@google.com> X-Mailer: git-send-email 2.6.0.rc0.131.gf624c3d Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org put_pid checks whether the current thread has the only reference to the pid with atomic_read() which does not have any memory barriers, and if so proceeds directly to kmem_cache_free(). As the result memory accesses to the object in kmem_cache_free() or user accesses to the object after reallocation (again without any memory barriers on fast path) can hoist above the atomic_read() check and conflict with memory accesses to the pid object in other threads before they released their references. There is a control dependency between the atomic_read() check and kmem_cache_free(), but control dependencies are disregarded by some architectures. Documentation/memory-barriers.txt explicitly states: "A load-load control dependency requires a full read memory barrier. ... please note that READ_ONCE_CTRL() is not optional! [even for stores]" in the CONTROL DEPENDENCIES section. For example, if store to the first word of the object to build a freelist in kmem_cache_free() hoists above the check, stores to the first word in other threads can corrupt the memory allocator freelist. Use atomic_read_acquire() for the fast path check to hand off properly acquired object to memory allocator. The data race was found with KernelThreadSanitizer (KTSAN). Signed-off-by: Dmitry Vyukov --- kernel/pid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/pid.c b/kernel/pid.c index ca36879..3b0b13d 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -242,7 +242,7 @@ void put_pid(struct pid *pid) return; ns = pid->numbers[pid->level].ns; - if ((atomic_read(&pid->count) == 1) || + if ((atomic_read_acquire(&pid->count) == 1) || atomic_dec_and_test(&pid->count)) { kmem_cache_free(ns->pid_cachep, pid); put_pid_ns(ns); -- 2.6.0.rc0.131.gf624c3d