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

rcutorture: Fix rcu_torture_one_read()/rcu_torture_writer() data race



The ->rtort_pipe_count field in the rcu_torture structure checks for
too-short grace periods, and is therefore read by rcutorture's readers
while being updated by rcutorture's writers.  This commit therefore
adds the needed READ_ONCE() and WRITE_ONCE() invocations.

This data race was reported by KCSAN.  Not appropriate for backporting
due to failure being unlikely and due to this being rcutorture.

Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
parent beabc806
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -375,11 +375,12 @@ rcu_torture_pipe_update_one(struct rcu_torture *rp)
{
	int i;

	i = rp->rtort_pipe_count;
	i = READ_ONCE(rp->rtort_pipe_count);
	if (i > RCU_TORTURE_PIPE_LEN)
		i = RCU_TORTURE_PIPE_LEN;
	atomic_inc(&rcu_torture_wcount[i]);
	if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
	WRITE_ONCE(rp->rtort_pipe_count, i + 1);
	if (rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
		rp->rtort_mbtest = 0;
		return true;
	}
@@ -1015,7 +1016,8 @@ rcu_torture_writer(void *arg)
			if (i > RCU_TORTURE_PIPE_LEN)
				i = RCU_TORTURE_PIPE_LEN;
			atomic_inc(&rcu_torture_wcount[i]);
			old_rp->rtort_pipe_count++;
			WRITE_ONCE(old_rp->rtort_pipe_count,
				   old_rp->rtort_pipe_count + 1);
			switch (synctype[torture_random(&rand) % nsynctypes]) {
			case RTWS_DEF_FREE:
				rcu_torture_writer_state = RTWS_DEF_FREE;
@@ -1291,7 +1293,7 @@ static bool rcu_torture_one_read(struct torture_random_state *trsp)
		atomic_inc(&n_rcu_torture_mberror);
	rtrsp = rcutorture_loop_extend(&readstate, trsp, rtrsp);
	preempt_disable();
	pipe_count = p->rtort_pipe_count;
	pipe_count = READ_ONCE(p->rtort_pipe_count);
	if (pipe_count > RCU_TORTURE_PIPE_LEN) {
		/* Should not happen, but... */
		pipe_count = RCU_TORTURE_PIPE_LEN;