From: Bradley Morgan <include@grrlz.net>
To: Karl Mehltretter <kmehltretter@gmail.com>,
Andrey Konovalov <andreyknvl@gmail.com>
Cc: Alexander Potapenko <glider@google.com>,
Dmitry Vyukov <dvyukov@google.com>,
Marco Elver <elver@google.com>,
kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] kcov: report the first spurious PC in the interrupt selftest
Date: Fri, 24 Jul 2026 20:27:07 +0100 [thread overview]
Message-ID: <CF4DFABB-7078-4EA7-AA84-9EEF0A77D9F1@grrlz.net> (raw)
In-Reply-To: <20260724192122.73080-1-kmehltretter@gmail.com>
On 24 July 2026 20:21:22 BST, Karl Mehltretter <kmehltretter@gmail.com>
wrote:
>The KCOV interrupt selftest enables KCOV_MODE_TRACE_PC without a
>coverage area so that spurious coverage causes a fault. If the fault
>path is instrumented, the coverage callback faults recursively.
>Observed failure modes include a stack overflow on x86_64 and arm32
>getting stuck in abort handling, neither of which identifies the
>original coverage event.
>
>The recursive failure is not new, but commit 9a79524d1420 ("kcov: use
>WRITE_ONCE() for selftest mode stores") made the selftest effective on
>configurations where the compiler had previously removed the mode
>store, exposing it more broadly.
>
>Use a two-word buffer to record the first spurious PC. Once one is
>recorded, disable KCOV, report the PC, and panic. This preserves the
>selftest's hard failure while avoiding the recursive fault path.
>
>Add decanonicalize_ip() as the inverse of canonicalize_ip(), which
>subtracts kaslr_offset() from recorded PCs, and use it before printing
>the PC with %pS.
>
>Fixes: 6cd0dd934b03 ("kcov: Add interrupt handling self test")
>Assisted-by: Claude:claude-opus-4-8
>Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
the selftest keeps its hard failure but now names the offending PC
instead of recursing into an undebuggable fault, and the enable
ordering lives in kcov_start()/kcov_stop() instead of a second open
coded copy. LGTM,
Reviewed-by: Bradley Morgan <include@grrlz.net>
>---
>Changes in v2:
>- Use kcov_start() and kcov_stop() instead of open-coding their logic.
>- Add decanonicalize_ip() next to canonicalize_ip() and use it when
> reporting the recorded PC.
>- Retest under QEMU on arm64, mips64le, and x86_64.
>
>This patch improves the failure diagnostics.
>
>With CONFIG_KCOV_SELFTEST, I observed failures under QEMU on arm,
>arm64, riscv64, s390x, ppc64le, mips64le, loongarch, and x86_64. The
>reported PCs indicate that this likely needs a global KCOV fix rather
>than separate exclusions for each architecture.
>
>For example, arm64 defconfig with KCOV and KCOV_SELFTEST reports:
>
> [ 2.741175] kcov: running self test
> [ 2.748637] kcov: spurious coverage detected during interrupt selftest: return_address+0x28/0xa8
> [ 2.750623] Kernel panic - not syncing: kcov: interrupt selftest detected spurious coverage
> [ 2.752147] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.2.0-rc3-...-dirty #25 PREEMPT(full)
>
> kernel/kcov.c | 40 ++++++++++++++++++++++++++++++++--------
> 1 file changed, 32 insertions(+), 8 deletions(-)
>
>diff --git a/kernel/kcov.c b/kernel/kcov.c
>index 1df373fb562b..7ddfd01ccd8a 100644
>--- a/kernel/kcov.c
>+++ b/kernel/kcov.c
>@@ -202,6 +202,16 @@ static notrace unsigned long canonicalize_ip(unsigned long ip)
> return ip;
> }
>
>+#ifdef CONFIG_KCOV_SELFTEST
>+static unsigned long decanonicalize_ip(unsigned long ip)
>+{
>+#ifdef CONFIG_RANDOMIZE_BASE
>+ ip += kaslr_offset();
>+#endif
>+ return ip;
>+}
>+#endif
>+
> /*
> * Entry point from instrumented code.
> * This is called once per basic-block/edge.
>@@ -1102,9 +1112,11 @@ struct kcov_common_handle_id kcov_common_handle(void)
> EXPORT_SYMBOL(kcov_common_handle);
>
> #ifdef CONFIG_KCOV_SELFTEST
>+static unsigned long selftest_area[2] __initdata;
>+
> static void __init selftest(void)
> {
>- unsigned long start;
>+ unsigned long start, ip;
>
> pr_err("running self test\n");
> /*
>@@ -1114,15 +1126,27 @@ static void __init selftest(void)
> * leaks out of that section and leads to spurious coverage.
> * It's hard to call the actual interrupt handler directly,
> * so we just loop here for a bit waiting for a timer interrupt.
>- * We set kcov_mode to enable tracing, but don't setup the area,
>- * so any attempt to trace will crash. Note: we must not call any
>- * potentially traced functions in this region.
>+ * We set up a two-word coverage area rather than leaving it NULL:
>+ * a leak then records its PC instead of crashing on a NULL
>+ * dereference, and we can report the offending PC. Note: we
>+ * must not call any potentially traced functions in this region.
> */
>+ kcov_start(current, NULL, ARRAY_SIZE(selftest_area),
>+ selftest_area, KCOV_MODE_TRACE_PC, 0);
> start = jiffies;
>- WRITE_ONCE(current->kcov_mode, KCOV_MODE_TRACE_PC);
>- while ((jiffies - start) * MSEC_PER_SEC / HZ < 300)
>- ;
>- WRITE_ONCE(current->kcov_mode, 0);
>+ while ((jiffies - start) * MSEC_PER_SEC / HZ < 300) {
>+ if (READ_ONCE(selftest_area[0]))
>+ break;
>+ cpu_relax();
>+ }
>+ kcov_stop(current);
>+
>+ if (selftest_area[0]) {
>+ ip = decanonicalize_ip(selftest_area[1]);
>+ pr_err("spurious coverage detected during interrupt selftest: %pS\n",
>+ (void *)ip);
>+ panic("kcov: interrupt selftest detected spurious coverage");
>+ }
> pr_err("done running self test\n");
> }
> #endif
>
Thanks!
next prev parent reply other threads:[~2026-07-24 19:27 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-24 19:21 Karl Mehltretter
2026-07-24 19:27 ` Bradley Morgan [this message]
2026-09-12 9:28 ` Karl Mehltretter
2026-09-14 10:21 ` Alexander Potapenko
2026-09-19 8:00 ` Karl Mehltretter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CF4DFABB-7078-4EA7-AA84-9EEF0A77D9F1@grrlz.net \
--to=include@grrlz.net \
--cc=andreyknvl@gmail.com \
--cc=dvyukov@google.com \
--cc=elver@google.com \
--cc=glider@google.com \
--cc=kasan-dev@googlegroups.com \
--cc=kmehltretter@gmail.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®