Commit 3d29aaf1 authored by Paul E. McKenney's avatar Paul E. McKenney
Browse files

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: default avatarPaul E. McKenney <paulmck@kernel.org>
parent 4e025f52
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -4152,6 +4152,15 @@
			This wake_up() will be accompanied by a
			WARN_ONCE() splat and an ftrace_dump().

	rcutree.rcu_unlock_delay= [KNL]
			In CONFIG_RCU_STRICT_GRACE_PERIOD=y kernels,
			this specifies an rcu_read_unlock()-time delay
			in microseconds.  This defaults to zero.
			Larger delays increase the probability of
			catching RCU pointer leaks, that is, buggy use
			of RCU-protected pointers after the relevant
			rcu_read_unlock() has completed.

	rcutree.sysrq_rcu= [KNL]
			Commandeer a sysrq key to dump out Tree RCU's
			rcu_node tree with an eye towards determining
+10 −2
Original line number Diff line number Diff line
@@ -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,11 +466,13 @@ 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();
		}
	}

	/*
	 * Respond to a request by an expedited grace period for a