Received: by 2002:a25:e7d8:0:0:0:0:0 with SMTP id e207csp2743762ybh; Mon, 9 Mar 2020 12:06:10 -0700 (PDT) X-Google-Smtp-Source: ADFU+vu5dpZx9QGDl7C3snHEKXSluwZ7bNUHmICa5OqUdkzW9b8oqI+boi15sSfIWrwOmkTr3bnj X-Received: by 2002:a05:6830:3090:: with SMTP id f16mr6981693ots.211.1583780768760; Mon, 09 Mar 2020 12:06:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1583780768; cv=none; d=google.com; s=arc-20160816; b=soCZ+iWr0VP4nl/jnluTN4h2+507YHTnfj0nQjCEOBqHI8DLJmm7d03Y2SZmpGQ1uE KrsUm+LSIXisGo1HlCS3WxjqTQbqJweqLk/+ZFMCvKmCoiyrvzU9A+p7tlOO2NR705Iq mTIH1xQ2FFiTE8kkJh5668YDRzm+AagZCuffPO2Bw5hFHfrng2Cv3idrQ0sszxY/N55K VHjXIkK9NddpD48ea2bKsHK0IOZIvnm3IQa6C+33QaiYg516Ik3bT789mFFzJ9ByUOpB IkcBduouhYiBxJw+na9+u8/xPb8sGaz2yY56Sebv7XjRbuxuCBLYMQoy68eKdCn82l3v Uwmw== 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=eWGBcE001Nfqh1Kr9iZ9lJurjyZZWLCAUfrneNwABTI=; b=u5cOyeOkLBvP+HCaeHsKGm0taBPyosC88ORmX0k33Ee8KEp6JJz4q7zyVHWURyh13a cnNZ/uLBDbrTQO1fuzAJC0wZM8faUwGxOVtdd06pUJlR57fS6mEctSmNnwyLq+VHsmXL 5W4/dfNrxNoaw358y2UeRWReiymh/AZ94kvjg41gCMAfWU/CWfa4j1gvFMAYQrJzC9ww B3Y9rHRBN/xEV6hYsmAj525YiA40yo4oMCeznY3G6gSjp5B4ToI5xwXXIGHDuWHTtfwS tzIkiqMjJjBwNWlYnXGYFhlJnQUPH/UmLLzlOwizk2tuK0IjCRcykWktPtxj4vJw7ptI fK8g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=mKc4vzID; 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 b80si4252852oii.199.2020.03.09.12.05.56; Mon, 09 Mar 2020 12:06:08 -0700 (PDT) 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=mKc4vzID; 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 S1727641AbgCITEz (ORCPT + 99 others); Mon, 9 Mar 2020 15:04:55 -0400 Received: from mail.kernel.org ([198.145.29.99]:47920 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727639AbgCITEa (ORCPT ); Mon, 9 Mar 2020 15:04:30 -0400 Received: from paulmck-ThinkPad-P72.home (50-39-105-78.bvtn.or.frontiernet.net [50.39.105.78]) (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 D8D882465A; Mon, 9 Mar 2020 19:04:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1583780669; bh=MTokGZDzIGGhXc8vlKSJ3HxBIYpNzS6zJBjPY0lqXtk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mKc4vzIDsg+YdsCsl0hCCOjjR0yJ3FQFsdLPQmAb4v06TqqineehF1FXkpTRN2xdM nqOQSqEjG0HkcbEeFJzHEoQ5rYjlTqGzIp4h142ueAXHFnrQqwSRPl1DlqI77ypqvj h0IOuOu5N2ZpGXzwrhIf+ZQjWwJq60VFeGEQ6iMI= From: paulmck@kernel.org To: linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, kernel-team@fb.com, mingo@kernel.org Cc: elver@google.com, andreyknvl@google.com, glider@google.com, dvyukov@google.com, cai@lca.pw, boqun.feng@gmail.com, "Paul E . McKenney" Subject: [PATCH kcsan 27/32] kcsan: Add option to allow watcher interruptions Date: Mon, 9 Mar 2020 12:04:15 -0700 Message-Id: <20200309190420.6100-27-paulmck@kernel.org> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20200309190359.GA5822@paulmck-ThinkPad-P72> References: <20200309190359.GA5822@paulmck-ThinkPad-P72> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Marco Elver Add option to allow interrupts while a watchpoint is set up. This can be enabled either via CONFIG_KCSAN_INTERRUPT_WATCHER or via the boot parameter 'kcsan.interrupt_watcher=1'. Note that, currently not all safe per-CPU access primitives and patterns are accounted for, which could result in false positives. For example, asm-generic/percpu.h uses plain operations, which by default are instrumented. On interrupts and subsequent accesses to the same variable, KCSAN would currently report a data race with this option. Therefore, this option should currently remain disabled by default, but may be enabled for specific test scenarios. To avoid new warnings, changes all uses of smp_processor_id() to use the raw version (as already done in kcsan_found_watchpoint()). The exact SMP processor id is for informational purposes in the report, and correctness is not affected. Signed-off-by: Marco Elver Signed-off-by: Paul E. McKenney --- kernel/kcsan/core.c | 34 ++++++++++------------------------ lib/Kconfig.kcsan | 11 +++++++++++ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c index 589b1e7..e7387fe 100644 --- a/kernel/kcsan/core.c +++ b/kernel/kcsan/core.c @@ -21,6 +21,7 @@ static bool kcsan_early_enable = IS_ENABLED(CONFIG_KCSAN_EARLY_ENABLE); static unsigned int kcsan_udelay_task = CONFIG_KCSAN_UDELAY_TASK; static unsigned int kcsan_udelay_interrupt = CONFIG_KCSAN_UDELAY_INTERRUPT; static long kcsan_skip_watch = CONFIG_KCSAN_SKIP_WATCH; +static bool kcsan_interrupt_watcher = IS_ENABLED(CONFIG_KCSAN_INTERRUPT_WATCHER); #ifdef MODULE_PARAM_PREFIX #undef MODULE_PARAM_PREFIX @@ -30,6 +31,7 @@ module_param_named(early_enable, kcsan_early_enable, bool, 0); module_param_named(udelay_task, kcsan_udelay_task, uint, 0644); module_param_named(udelay_interrupt, kcsan_udelay_interrupt, uint, 0644); module_param_named(skip_watch, kcsan_skip_watch, long, 0644); +module_param_named(interrupt_watcher, kcsan_interrupt_watcher, bool, 0444); bool kcsan_enabled; @@ -354,7 +356,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) unsigned long access_mask; enum kcsan_value_change value_change = KCSAN_VALUE_CHANGE_MAYBE; unsigned long ua_flags = user_access_save(); - unsigned long irq_flags; + unsigned long irq_flags = 0; /* * Always reset kcsan_skip counter in slow-path to avoid underflow; see @@ -370,26 +372,9 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) goto out; } - /* - * Disable interrupts & preemptions to avoid another thread on the same - * CPU accessing memory locations for the set up watchpoint; this is to - * avoid reporting races to e.g. CPU-local data. - * - * An alternative would be adding the source CPU to the watchpoint - * encoding, and checking that watchpoint-CPU != this-CPU. There are - * several problems with this: - * 1. we should avoid stealing more bits from the watchpoint encoding - * as it would affect accuracy, as well as increase performance - * overhead in the fast-path; - * 2. if we are preempted, but there *is* a genuine data race, we - * would *not* report it -- since this is the common case (vs. - * CPU-local data accesses), it makes more sense (from a data race - * detection point of view) to simply disable preemptions to ensure - * as many tasks as possible run on other CPUs. - * - * Use raw versions, to avoid lockdep recursion via IRQ flags tracing. - */ - raw_local_irq_save(irq_flags); + if (!kcsan_interrupt_watcher) + /* Use raw to avoid lockdep recursion via IRQ flags tracing. */ + raw_local_irq_save(irq_flags); watchpoint = insert_watchpoint((unsigned long)ptr, size, is_write); if (watchpoint == NULL) { @@ -507,7 +492,7 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) if (is_assert && value_change == KCSAN_VALUE_CHANGE_TRUE) kcsan_counter_inc(KCSAN_COUNTER_ASSERT_FAILURES); - kcsan_report(ptr, size, type, value_change, smp_processor_id(), + kcsan_report(ptr, size, type, value_change, raw_smp_processor_id(), KCSAN_REPORT_RACE_SIGNAL); } else if (value_change == KCSAN_VALUE_CHANGE_TRUE) { /* Inferring a race, since the value should not have changed. */ @@ -518,13 +503,14 @@ kcsan_setup_watchpoint(const volatile void *ptr, size_t size, int type) if (IS_ENABLED(CONFIG_KCSAN_REPORT_RACE_UNKNOWN_ORIGIN) || is_assert) kcsan_report(ptr, size, type, KCSAN_VALUE_CHANGE_TRUE, - smp_processor_id(), + raw_smp_processor_id(), KCSAN_REPORT_RACE_UNKNOWN_ORIGIN); } kcsan_counter_dec(KCSAN_COUNTER_USED_WATCHPOINTS); out_unlock: - raw_local_irq_restore(irq_flags); + if (!kcsan_interrupt_watcher) + raw_local_irq_restore(irq_flags); out: user_access_restore(ua_flags); } diff --git a/lib/Kconfig.kcsan b/lib/Kconfig.kcsan index f0b7911..081ed2e 100644 --- a/lib/Kconfig.kcsan +++ b/lib/Kconfig.kcsan @@ -88,6 +88,17 @@ config KCSAN_SKIP_WATCH_RANDOMIZE KCSAN_WATCH_SKIP. If false, the chosen value is always KCSAN_WATCH_SKIP. +config KCSAN_INTERRUPT_WATCHER + bool "Interruptible watchers" + help + If enabled, a task that set up a watchpoint may be interrupted while + delayed. This option will allow KCSAN to detect races between + interrupted tasks and other threads of execution on the same CPU. + + Currently disabled by default, because not all safe per-CPU access + primitives and patterns may be accounted for, and therefore could + result in false positives. + config KCSAN_REPORT_ONCE_IN_MS int "Duration in milliseconds, in which any given race is only reported once" default 3000 -- 2.9.5