Skip to content

Commit 3a5b45e

Browse files
melverIngo Molnar
authored andcommitted
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: Marco Elver <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]> Signed-off-by: Ingo Molnar <[email protected]>
1 parent 80d4c47 commit 3a5b45e

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

kernel/kcsan/report.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,44 @@ static bool prepare_report(unsigned long *flags, const volatile void *ptr,
422422
return false;
423423
}
424424

425+
access_type |= other_info.access_type;
426+
if ((access_type & KCSAN_ACCESS_WRITE) == 0) {
427+
/*
428+
* While the address matches, this is not the other_info
429+
* from the thread that consumed our watchpoint, since
430+
* neither this nor the access in other_info is a write.
431+
* It is invalid to continue with the report, since we
432+
* only have information about reads.
433+
*
434+
* This can happen due to concurrent races on the same
435+
* address, with at least 4 threads. To avoid locking up
436+
* other_info and all other threads, we have to consume
437+
* it regardless.
438+
*
439+
* A concrete case to illustrate why we might lock up if
440+
* we do not consume other_info:
441+
*
442+
* We have 4 threads, all accessing the same address
443+
* (or matching address ranges). Assume the following
444+
* watcher and watchpoint consumer pairs:
445+
* write1-read1, read2-write2. The first to populate
446+
* other_info is write2, however, write1 consumes it,
447+
* resulting in a report of write1-write2. This report
448+
* is valid, however, now read1 populates other_info;
449+
* read2-read1 is an invalid conflict, yet, no other
450+
* conflicting access is left. Therefore, we must
451+
* consume read1's other_info.
452+
*
453+
* Since this case is assumed to be rare, it is
454+
* reasonable to omit this report: one of the other
455+
* reports includes information about the same shared
456+
* data, and at this point the likelihood that we
457+
* re-report the same race again is high.
458+
*/
459+
release_report(flags, KCSAN_REPORT_RACE_SIGNAL);
460+
return false;
461+
}
462+
425463
/*
426464
* Matching & usable access in other_info: keep other_info_lock
427465
* locked, as this thread consumes it to print the full report;

0 commit comments

Comments
 (0)