Commit 3a5b45e5 authored by Marco Elver's avatar Marco Elver Committed by Ingo Molnar
Browse files

kcsan: Fix misreporting if concurrent races on same address



If there are at least 4 threads racing on the same address, it can
happen that one of the readers may observe another matching reader in
other_info. To avoid locking up, we have to consume 'other_info'
regardless, but skip the report. See the added comment for more details.

Signed-off-by: default avatarMarco Elver <elver@google.com>
Signed-off-by: default avatarPaul E. McKenney <paulmck@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 80d4c477
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -422,6 +422,44 @@ static bool prepare_report(unsigned long *flags, const volatile void *ptr,
			return false;
		}

		access_type |= other_info.access_type;
		if ((access_type & KCSAN_ACCESS_WRITE) == 0) {
			/*
			 * While the address matches, this is not the other_info
			 * from the thread that consumed our watchpoint, since
			 * neither this nor the access in other_info is a write.
			 * It is invalid to continue with the report, since we
			 * only have information about reads.
			 *
			 * This can happen due to concurrent races on the same
			 * address, with at least 4 threads. To avoid locking up
			 * other_info and all other threads, we have to consume
			 * it regardless.
			 *
			 * A concrete case to illustrate why we might lock up if
			 * we do not consume other_info:
			 *
			 *   We have 4 threads, all accessing the same address
			 *   (or matching address ranges). Assume the following
			 *   watcher and watchpoint consumer pairs:
			 *   write1-read1, read2-write2. The first to populate
			 *   other_info is write2, however, write1 consumes it,
			 *   resulting in a report of write1-write2. This report
			 *   is valid, however, now read1 populates other_info;
			 *   read2-read1 is an invalid conflict, yet, no other
			 *   conflicting access is left. Therefore, we must
			 *   consume read1's other_info.
			 *
			 * Since this case is assumed to be rare, it is
			 * reasonable to omit this report: one of the other
			 * reports includes information about the same shared
			 * data, and at this point the likelihood that we
			 * re-report the same race again is high.
			 */
			release_report(flags, KCSAN_REPORT_RACE_SIGNAL);
			return false;
		}

		/*
		 * Matching & usable access in other_info: keep other_info_lock
		 * locked, as this thread consumes it to print the full report;