Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp2302699ybv; Fri, 14 Feb 2020 15:58:12 -0800 (PST) X-Google-Smtp-Source: APXvYqymGLYjQEKwp7FEhfheqPr75ikDzwNTyAwOew30RZssBAMMCgMewEuljWSVgPYK3Xb5spCN X-Received: by 2002:a05:6830:1d4c:: with SMTP id p12mr4474653oth.198.1581724692186; Fri, 14 Feb 2020 15:58:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1581724692; cv=none; d=google.com; s=arc-20160816; b=Tn2uyr3ZQcCo2Tbf1uIv7ZOezQRiJO+GztcXi43bgVilNqKddU+kr9ZP1lYLsPx1r0 EeHYj1hufT9Gs4ntr1Vz9aps6M/Hbme0nbmzFyIBccFEti93mj+oE2vjWW87gGEX7Jtt bcMt511nGFjidD4zGWWjDTZS2qJfw+jLONjhgEi3tPD/9L9zN/AKrKaywAHqVsiiDwhN b79T1PiGygXvs2i2p1ye/iYGsgkS1ErYS8WKNomhVBYxcHC443YN6yrgk0BmEakAjiWD XCXk59zGx5QRoMTS9gnQKCdZ3MR3VaZs32imFUFzGLKE7u1gzwSxPbOtQkpuylSpxMLw IKAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=ypJfLyp/TBhWGBDcjqETRELeImaHYOMfJS2keoYIHFU=; b=stVZ/IjvzK76WKIj3XraM8HlEep4AjVjg/bob6Jel9MMskNBUYWHN+4lwiFZ3O8ytd lk2cUhLnKRhBAl1A1VK/0L1lUqLRbPf+jPDsgszTM/4NyZn7zqoPhwx+M5yN2n4X/v8d 9OuiEzVryXZUO0mnxXJE2aFo0vzUxNkBJG0Wq6CUxAgjDb5bMIIoK/I+/aq5kFCkrY7P p7z+oEMxBItfyS90CdCgbD/GINOol9ZXn/VQKOaC1NyUCs2qy1g9DOaHrXC5aZacuUwp vUfzpGwSggFTkkFVfVS5Blg0aRbZ64C3BhKDjntpA80lrInkg+MrO0od+DIvhIBrNGp3 Uf2w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=EVIoemD2; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v25si3832741ote.90.2020.02.14.15.58.00; Fri, 14 Feb 2020 15:58:12 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=EVIoemD2; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728637AbgBNX5Z (ORCPT + 99 others); Fri, 14 Feb 2020 18:57:25 -0500 Received: from mail.kernel.org ([198.145.29.99]:37252 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728202AbgBNX5Y (ORCPT ); Fri, 14 Feb 2020 18:57:24 -0500 Received: from paulmck-ThinkPad-P72.c.hoisthospitality.com (unknown [62.84.152.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 58CD82467B; Fri, 14 Feb 2020 23:57:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1581724643; bh=nZvacCHrP3x9jXc1xmLGNfnhtdirujNkmaBc1LB6elU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EVIoemD2tq0SSnRnE5ckSMYQQDFIfz4X+sdti/mg8pR5gnnfhUYalw19Rmw/NlZmy jHRj7RD3FSjGq+ctzgXPl5if3YuNqYLmRI+AIapiQayH8NjKWJQL3AqaBxJDsNsZ0m xAr9M+bReOq75Lc29uvAu9zkY12htZgdHPfaoi/A= From: paulmck@kernel.org To: rcu@vger.kernel.org Cc: linux-kernel@vger.kernel.org, kernel-team@fb.com, mingo@kernel.org, jiangshanlai@gmail.com, dipankar@in.ibm.com, akpm@linux-foundation.org, mathieu.desnoyers@efficios.com, josh@joshtriplett.org, tglx@linutronix.de, peterz@infradead.org, rostedt@goodmis.org, dhowells@redhat.com, edumazet@google.com, fweisbec@gmail.com, oleg@redhat.com, joel@joelfernandes.org, "Paul E. McKenney" Subject: [PATCH tip/core/rcu 20/30] rcu: Fix rcu_barrier_callback() race condition Date: Fri, 14 Feb 2020 15:55:57 -0800 Message-Id: <20200214235607.13749-20-paulmck@kernel.org> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20200214235536.GA13364@paulmck-ThinkPad-P72> References: <20200214235536.GA13364@paulmck-ThinkPad-P72> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: "Paul E. McKenney" The rcu_barrier_callback() function does an atomic_dec_and_test(), and if it is the last CPU to check in, does the required wakeup. Either way, it does an event trace. Unfortunately, this is susceptible to the following sequence of events: o CPU 0 invokes rcu_barrier_callback(), but atomic_dec_and_test() says that it is not last. But at this point, CPU 0 is delayed, perhaps due to an NMI, SMI, or vCPU preemption. o CPU 1 invokes rcu_barrier_callback(), and atomic_dec_and_test() says that it is last. So CPU 1 traces completion and does the needed wakeup. o The awakened rcu_barrier() function does cleanup and releases rcu_state.barrier_mutex. o Another CPU now acquires rcu_state.barrier_mutex and starts another round of rcu_barrier() processing, including updating rcu_state.barrier_sequence. o CPU 0 gets its act back together and does its tracing. Except that rcu_state.barrier_sequence has already been updated, so its tracing is incorrect and probably quite confusing. (Wait! Why did this CPU check in twice for one rcu_barrier() invocation???) This commit therefore causes rcu_barrier_callback() to take a snapshot of the value of rcu_state.barrier_sequence before invoking atomic_dec_and_test(), thus guaranteeing that the event-trace output is sensible, even if the timing of the event-trace output might still be confusing. (Wait! Why did the old rcu_barrier() complete before all of its CPUs checked in???) But being that this is RCU, only so much confusion can reasonably be eliminated. This data race was reported by KCSAN. Not appropriate for backporting due to failure being unlikely and due to the mild consequences of the failure, namely a confusing event trace. Signed-off-by: Paul E. McKenney --- kernel/rcu/tree.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index be59a5d..62383ce 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -3077,15 +3077,22 @@ static void rcu_barrier_trace(const char *s, int cpu, unsigned long done) /* * RCU callback function for rcu_barrier(). If we are last, wake * up the task executing rcu_barrier(). + * + * Note that the value of rcu_state.barrier_sequence must be captured + * before the atomic_dec_and_test(). Otherwise, if this CPU is not last, + * other CPUs might count the value down to zero before this CPU gets + * around to invoking rcu_barrier_trace(), which might result in bogus + * data from the next instance of rcu_barrier(). */ static void rcu_barrier_callback(struct rcu_head *rhp) { + unsigned long __maybe_unused s = rcu_state.barrier_sequence; + if (atomic_dec_and_test(&rcu_state.barrier_cpu_count)) { - rcu_barrier_trace(TPS("LastCB"), -1, - rcu_state.barrier_sequence); + rcu_barrier_trace(TPS("LastCB"), -1, s); complete(&rcu_state.barrier_completion); } else { - rcu_barrier_trace(TPS("CB"), -1, rcu_state.barrier_sequence); + rcu_barrier_trace(TPS("CB"), -1, s); } } -- 2.9.5