summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@kernel.org>2020-08-07 13:44:10 -0700
committerPaul E. McKenney <paulmck@kernel.org>2020-08-24 18:40:27 -0700
commit3d29aaf1ef992b5b4612fe32b9e6f517f7bba904 (patch)
tree5ea92127640c2899da6805a887d25c9e249c5154 /kernel
parent4e025f52a1e0e8ff4e303fa0a80e2061ccfa27d6 (diff)
downloadlinux-stable-3d29aaf1ef992b5b4612fe32b9e6f517f7bba904.tar.gz
linux-stable-3d29aaf1ef992b5b4612fe32b9e6f517f7bba904.tar.bz2
linux-stable-3d29aaf1ef992b5b4612fe32b9e6f517f7bba904.zip
rcu: Provide optional RCU-reader exit delay for strict GPs
The goal of this series is to increase the probability of tools like KASAN detecting that an RCU-protected pointer was used outside of its RCU read-side critical section. Thus far, the approach has been to make grace periods and callback processing happen faster. Another approach is to delay the pointer leaker. This commit therefore allows a delay to be applied to exit from RCU read-side critical sections. This slowdown is specified by a new rcutree.rcu_unlock_delay kernel boot parameter that specifies this delay in microseconds, defaulting to zero. Reported-by Jann Horn <jannh@google.com> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcu/tree_plugin.h12
1 files changed, 10 insertions, 2 deletions
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index dfdb9020f136..3f3a4ffd4df2 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -430,6 +430,12 @@ static bool rcu_preempt_has_tasks(struct rcu_node *rnp)
return !list_empty(&rnp->blkd_tasks);
}
+// Add delay to rcu_read_unlock() for strict grace periods.
+static int rcu_unlock_delay;
+#ifdef CONFIG_RCU_STRICT_GRACE_PERIOD
+module_param(rcu_unlock_delay, int, 0444);
+#endif
+
/*
* Report deferred quiescent states. The deferral time can
* be quite short, for example, in the case of the call from
@@ -460,10 +466,12 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)
}
t->rcu_read_unlock_special.s = 0;
if (special.b.need_qs) {
- if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD))
+ if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD)) {
rcu_report_qs_rdp(rdp->cpu, rdp);
- else
+ udelay(rcu_unlock_delay);
+ } else {
rcu_qs();
+ }
}
/*