]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
kcov: use WRITE_ONCE() for selftest mode stores
authorKarl Mehltretter <kmehltretter@gmail.com>
Tue, 26 May 2026 11:47:15 +0000 (13:47 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Thu, 4 Jun 2026 21:49:26 +0000 (14:49 -0700)
The KCOV selftest enables coverage by setting current->kcov_mode to
KCOV_MODE_TRACE_PC without installing a coverage area.  If an interrupt
records coverage in that window, the access should fault and expose the
bug.

When building for QEMU raspi0 (Raspberry Pi Zero, ARMv6, CONFIG_CPU_V6K=y,
CONFIG_CURRENT_POINTER_IN_TPIDRURO=y) with GCC 13.3.0, the store that
enables the mode is removed.  The generated kcov_init() code only stores
zero after the wait loop:

  mrc 15, 0, r3, cr13, cr0, {3}
  str r4, [r3, #2028]

where r4 is zero.  There is no store of KCOV_MODE_TRACE_PC before the
loop, so the selftest reports success without exercising coverage.

Use WRITE_ONCE() for the temporary mode stores.  With the same compiler
and config, kcov_init() contains the intended mode store:

  mov r3, #2
  mrc 15, 0, r2, cr13, cr0, {3}
  str r3, [r2, #2028]

Now that the KCOV selftest is actually executed, it may expose KCOV
instrumentation issues depending on the kernel config.  That is expected
for a selftest that was intended to catch coverage from interrupt paths.

Link: https://lore.kernel.org/20260526114715.38280-1-kmehltretter@gmail.com
Fixes: 6cd0dd934b03 ("kcov: Add interrupt handling self test")
Assisted-by: Codex:gpt-5
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
Reviewed-by: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Kees Cook <kees@kernel.org>
Cc: Marco Elver <elver@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
kernel/kcov.c

index fd25030307299cdb09f764531e4cf0a8267b353b..1df373fb562bc837776137144000bcc91c585d74 100644 (file)
@@ -1119,10 +1119,10 @@ static void __init selftest(void)
         * potentially traced functions in this region.
         */
        start = jiffies;
-       current->kcov_mode = KCOV_MODE_TRACE_PC;
+       WRITE_ONCE(current->kcov_mode, KCOV_MODE_TRACE_PC);
        while ((jiffies - start) * MSEC_PER_SEC / HZ < 300)
                ;
-       current->kcov_mode = 0;
+       WRITE_ONCE(current->kcov_mode, 0);
        pr_err("done running self test\n");
 }
 #endif