]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
kcsan: Fix misreporting if concurrent races on same address
authorMarco Elver <elver@google.com>
Mon, 10 Feb 2020 14:56:39 +0000 (15:56 +0100)
committerIngo Molnar <mingo@kernel.org>
Sat, 21 Mar 2020 08:43:41 +0000 (09:43 +0100)
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 <elver@google.com>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
kernel/kcsan/report.c

index 3bc590e6be7e3fc69e7b0def1275f573a27c5bdd..abf6852dff72f420d1566526c964e00e119df413 100644 (file)
@@ -422,6 +422,44 @@ retry:
                        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;