mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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!

  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®