mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] kcov: update documentation on remote coverage collection
@ 2026-05-20 18:21 Jann Horn
  2026-05-21 23:18 ` Andrew Morton
  2026-06-05 13:46 ` Alexander Potapenko
  0 siblings, 2 replies; 4+ messages in thread
From: Jann Horn @ 2026-05-20 18:21 UTC (permalink / raw)
  To: Alexander Potapenko, Dmitry Vyukov, Andrey Konovalov, kasan-dev,
	Andrew Morton
  Cc: linux-kernel, Jann Horn

Adjust the docs on remote coverage collection to reflect the changes made
in "kcov: refactor common handle ID into kcov_common_handle_id" and
"kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".

Suggested-by: Alexander Potapenko <glider@google.com>
Signed-off-by: Jann Horn <jannh@google.com>
---
Changes in v2:
- move and reword sentence on simultaneous normal/remote collection (andreyknvl)
- Link to v1: https://lore.kernel.org/r/20260519-kcov-docs-v1-1-5bb22f4cb20c@google.com
---
 Documentation/dev-tools/kcov.rst | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
index 8127849d40f5..1a739290c8ec 100644
--- a/Documentation/dev-tools/kcov.rst
+++ b/Documentation/dev-tools/kcov.rst
@@ -237,6 +237,9 @@ Both ``kcov_remote_start`` and ``kcov_remote_stop`` annotations and the
 collection sections. The way a handle is used depends on the context where the
 matching code section executes.
 
+A thread can use two separate KCOV instances to collect remote coverage and
+normal coverage at the same time.
+
 KCOV supports collecting remote coverage from the following contexts:
 
 1. Global kernel background tasks. These are the tasks that are spawned during
@@ -262,6 +265,9 @@ gets saved to the ``kcov_handle`` field in the current ``task_struct`` and
 needs to be passed to the newly spawned local tasks via custom kernel code
 modifications. Those tasks should in turn use the passed handle in their
 ``kcov_remote_start`` and ``kcov_remote_stop`` annotations.
+In the kernel, common handles are wrapped in a ``kcov_common_handle_id``, which
+consumes no space in builds without ``CONFIG_KCOV``; subsystems that integrate
+with this mechanism should not need to use any ``#ifdef CONFIG_KCOV`` or such.
 
 KCOV follows a predefined format for both global and common handles. Each
 handle is a ``u64`` integer. Currently, only the one top and the lower 4 bytes

---
base-commit: ab5fce87a778cb780a05984a2ca448f2b41aafbf
change-id: 20260519-kcov-docs-15feabfb10aa

--  
Jann Horn <jannh@google.com>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] kcov: update documentation on remote coverage collection
  2026-05-20 18:21 [PATCH v2] kcov: update documentation on remote coverage collection Jann Horn
@ 2026-05-21 23:18 ` Andrew Morton
  2026-05-26 14:08   ` Jann Horn
  2026-06-05 13:46 ` Alexander Potapenko
  1 sibling, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2026-05-21 23:18 UTC (permalink / raw)
  To: Jann Horn
  Cc: Alexander Potapenko, Dmitry Vyukov, Andrey Konovalov, kasan-dev,
	linux-kernel

On Wed, 20 May 2026 20:21:29 +0200 Jann Horn <jannh@google.com> wrote:

> Adjust the docs on remote coverage collection to reflect the changes made
> in "kcov: refactor common handle ID into kcov_common_handle_id" and
> "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".

This has all become rather confusing, with fixes and new versions of
fixes under different titles, etc.

I did my best to piece it all together then I joined everything into a
single patch, below.  Please check it for accuracy, up-to-dateness and
changelog truthfulness, thanks.


From: Jann Horn <jannh@google.com>
Subject: kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE
Date: Tue, 05 May 2026 11:00:46 +0200

Allow the same userspace thread to simultaneously collect normal coverage
in syscall context (KCOV_ENABLE) and remote coverage of asynchronous work
created by the thread (KCOV_REMOTE_ENABLE).  With this, remote KCOV
coverage becomes useful for generic fuzzing and not just fuzzing of
specific data injection interfaces.

This requires that the task_struct::kcov_* fields are separated into ones
that are used by the task that generates coverage, and ones that are used
by the task that requested remote coverage.  To split this up:

 - Split task_struct::kcov into kcov and kcov_remote. kcov_task_exit() now
   has to clean up both separately.
 - Only use task_struct::kcov_mode on the task that generates coverage.
 - Only reset task_struct::kcov_handle on the task that requested remote
   coverage.

After this change, fields used by the task that generates coverage are:

 - kcov_mode
 - kcov_size
 - kcov_area
 - kcov
 - kcov_sequence
 - kcov_softirq

Fields used by the task that requested remote coverage are:

 - kcov_remote
 - kcov_handle

[jannh@google.com: remove unused constant KCOV_MODE_REMOTE, per Dmitry]
  Link: https://lore.kernel.org/20260515-kcov-simultaneous-remote-v2-1-56fde1cfa509@google.com
[jannh@google.com: update documentation on remote coverage collection]
  Link: https://lore.kernel.org/20260519-kcov-docs-v1-1-5bb22f4cb20c@google.com
[jannh@google.com: move and reword sentence on simultaneous normal/remote collection
  Link: https://lore.kernel.org/20260520-kcov-docs-v2-1-819f78778763@google.com
Link: https://lore.kernel.org/20260505-kcov-simultaneous-remote-v1-1-a670ba7cefd2@google.com
Signed-off-by: Jann Horn <jannh@google.com>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Marco Elver <elver@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 Documentation/dev-tools/kcov.rst |    6 +
 include/linux/kcov.h             |    2 
 include/linux/sched.h            |    3 
 kernel/kcov.c                    |   94 ++++++++++++++++-------------
 4 files changed, 61 insertions(+), 44 deletions(-)

--- a/include/linux/sched.h~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/include/linux/sched.h
@@ -1517,6 +1517,9 @@ struct task_struct {
 	/* KCOV descriptor wired with this task or NULL: */
 	struct kcov			*kcov;
 
+	/* KCOV descriptor for remote coverage collection from other tasks: */
+	struct kcov			*kcov_remote;
+
 	/* KCOV common handle for remote coverage collection: */
 	u64				kcov_handle;
 
--- a/kernel/kcov.c~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/kernel/kcov.c
@@ -368,6 +368,7 @@ static void kcov_start(struct task_struc
 	WRITE_ONCE(t->kcov_mode, mode);
 }
 
+/* operates on coverage-generator-owned fields */
 static void kcov_stop(struct task_struct *t)
 {
 	WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED);
@@ -377,16 +378,17 @@ static void kcov_stop(struct task_struct
 	t->kcov_area = NULL;
 }
 
+/* operates on coverage-generator-owned fields */
 static void kcov_task_reset(struct task_struct *t)
 {
 	kcov_stop(t);
 	t->kcov_sequence = 0;
-	t->kcov_handle = 0;
 }
 
 void kcov_task_init(struct task_struct *t)
 {
 	kcov_task_reset(t);
+	t->kcov_remote = NULL;
 	t->kcov_handle = current->kcov_handle;
 }
 
@@ -423,11 +425,14 @@ static void kcov_remote_reset(struct kco
 static void kcov_disable(struct task_struct *t, struct kcov *kcov)
 	__must_hold(&kcov->lock)
 {
-	kcov_task_reset(t);
-	if (kcov->remote)
+	if (kcov->remote) {
+		t->kcov_handle = 0;
+		t->kcov_remote = NULL;
 		kcov_remote_reset(kcov);
-	else
+	} else {
+		kcov_task_reset(t);
 		kcov_reset(kcov);
+	}
 }
 
 static void kcov_get(struct kcov *kcov)
@@ -453,41 +458,47 @@ void kcov_task_exit(struct task_struct *
 	unsigned long flags;
 
 	kcov = t->kcov;
-	if (kcov == NULL)
-		return;
-
-	spin_lock_irqsave(&kcov->lock, flags);
-	kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
-	/*
-	 * For KCOV_ENABLE devices we want to make sure that t->kcov->t == t,
-	 * which comes down to:
-	 *        WARN_ON(!kcov->remote && kcov->t != t);
-	 *
-	 * For KCOV_REMOTE_ENABLE devices, the exiting task is either:
-	 *
-	 * 1. A remote task between kcov_remote_start() and kcov_remote_stop().
-	 *    In this case we should print a warning right away, since a task
-	 *    shouldn't be exiting when it's in a kcov coverage collection
-	 *    section. Here t points to the task that is collecting remote
-	 *    coverage, and t->kcov->t points to the thread that created the
-	 *    kcov device. Which means that to detect this case we need to
-	 *    check that t != t->kcov->t, and this gives us the following:
-	 *        WARN_ON(kcov->remote && kcov->t != t);
-	 *
-	 * 2. The task that created kcov exiting without calling KCOV_DISABLE,
-	 *    and then again we make sure that t->kcov->t == t:
-	 *        WARN_ON(kcov->remote && kcov->t != t);
-	 *
-	 * By combining all three checks into one we get:
-	 */
-	if (WARN_ON(kcov->t != t)) {
+	if (kcov) {
+		spin_lock_irqsave(&kcov->lock, flags);
+		kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
+		/*
+		 * This could be a remote task between kcov_remote_start() and
+		 * kcov_remote_stop().
+		 * In this case we should print a warning right away, since a
+		 * task shouldn't be exiting when it's in a kcov coverage
+		 * collection section.
+		 *
+		 * Otherwise, this should be a task that created a local
+		 * kcov instance and hasn't called KCOV_DISABLE.
+		 * Make sure that t->kcov->t is consistent.
+		 */
+		if (WARN_ON(kcov->remote) || WARN_ON(kcov->t != t)) {
+			spin_unlock_irqrestore(&kcov->lock, flags);
+			return;
+		}
+		/* Just to not leave dangling references behind. */
+		kcov_disable(t, kcov);
 		spin_unlock_irqrestore(&kcov->lock, flags);
-		return;
+		kcov_put(kcov);
+	}
+	kcov = t->kcov_remote;
+	if (kcov) {
+		spin_lock_irqsave(&kcov->lock, flags);
+		kcov_debug("t = %px, kcov->t = %px\n", t, kcov->t);
+		/*
+		 * This is a KCOV_REMOTE_ENABLE device, and the task is the
+		 * user task which has requested remote coverage collection.
+		 * Make sure that t->kcov->t is consistent.
+		 */
+		if (WARN_ON(!kcov->remote) || WARN_ON(kcov->t != t)) {
+			spin_unlock_irqrestore(&kcov->lock, flags);
+			return;
+		}
+		/* Just to not leave dangling references behind. */
+		kcov_disable(t, kcov);
+		spin_unlock_irqrestore(&kcov->lock, flags);
+		kcov_put(kcov);
 	}
-	/* Just to not leave dangling references behind. */
-	kcov_disable(t, kcov);
-	spin_unlock_irqrestore(&kcov->lock, flags);
-	kcov_put(kcov);
 }
 
 static int kcov_mmap(struct file *filep, struct vm_area_struct *vma)
@@ -629,9 +640,9 @@ static int kcov_ioctl_locked(struct kcov
 	case KCOV_DISABLE:
 		/* Disable coverage for the current task. */
 		unused = arg;
-		if (unused != 0 || current->kcov != kcov)
-			return -EINVAL;
 		t = current;
+		if (unused != 0 || (kcov != t->kcov && kcov != t->kcov_remote))
+			return -EINVAL;
 		if (WARN_ON(kcov->t != t))
 			return -EINVAL;
 		kcov_disable(t, kcov);
@@ -641,7 +652,7 @@ static int kcov_ioctl_locked(struct kcov
 		if (kcov->mode != KCOV_MODE_INIT || !kcov->area)
 			return -EINVAL;
 		t = current;
-		if (kcov->t != NULL || t->kcov != NULL)
+		if (kcov->t != NULL || t->kcov_remote != NULL)
 			return -EBUSY;
 		remote_arg = (struct kcov_remote_arg *)arg;
 		mode = kcov_get_mode(remote_arg->trace_mode);
@@ -651,8 +662,7 @@ static int kcov_ioctl_locked(struct kcov
 		    LONG_MAX / sizeof(unsigned long))
 			return -EINVAL;
 		kcov->mode = mode;
-		t->kcov = kcov;
-	        t->kcov_mode = KCOV_MODE_REMOTE;
+		t->kcov_remote = kcov;
 		kcov->t = t;
 		kcov->remote = true;
 		kcov->remote_size = remote_arg->area_size;
--- a/include/linux/kcov.h~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/include/linux/kcov.h
@@ -21,8 +21,6 @@ enum kcov_mode {
 	KCOV_MODE_TRACE_PC = 2,
 	/* Collecting comparison operands mode. */
 	KCOV_MODE_TRACE_CMP = 3,
-	/* The process owns a KCOV remote reference. */
-	KCOV_MODE_REMOTE = 4,
 };
 
 #define KCOV_IN_CTXSW	(1 << 30)
--- a/Documentation/dev-tools/kcov.rst~kcov-allow-simultaneous-kcov_enable-kcov_remote_enable
+++ a/Documentation/dev-tools/kcov.rst
@@ -237,6 +237,9 @@ Both ``kcov_remote_start`` and ``kcov_re
 collection sections. The way a handle is used depends on the context where the
 matching code section executes.
 
+A thread can use two separate KCOV instances to collect remote coverage and
+normal coverage at the same time.
+
 KCOV supports collecting remote coverage from the following contexts:
 
 1. Global kernel background tasks. These are the tasks that are spawned during
@@ -262,6 +265,9 @@ gets saved to the ``kcov_handle`` field
 needs to be passed to the newly spawned local tasks via custom kernel code
 modifications. Those tasks should in turn use the passed handle in their
 ``kcov_remote_start`` and ``kcov_remote_stop`` annotations.
+In the kernel, common handles are wrapped in a ``kcov_common_handle_id``, which
+consumes no space in builds without ``CONFIG_KCOV``; subsystems that integrate
+with this mechanism should not need to use any ``#ifdef CONFIG_KCOV`` or such.
 
 KCOV follows a predefined format for both global and common handles. Each
 handle is a ``u64`` integer. Currently, only the one top and the lower 4 bytes
_


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] kcov: update documentation on remote coverage collection
  2026-05-21 23:18 ` Andrew Morton
@ 2026-05-26 14:08   ` Jann Horn
  0 siblings, 0 replies; 4+ messages in thread
From: Jann Horn @ 2026-05-26 14:08 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Alexander Potapenko, Dmitry Vyukov, Andrey Konovalov, kasan-dev,
	linux-kernel

On Fri, May 22, 2026 at 1:18 AM Andrew Morton <akpm@linux-foundation.org> wrote:
> On Wed, 20 May 2026 20:21:29 +0200 Jann Horn <jannh@google.com> wrote:
> > Adjust the docs on remote coverage collection to reflect the changes made
> > in "kcov: refactor common handle ID into kcov_common_handle_id" and
> > "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".
>
> This has all become rather confusing, with fixes and new versions of
> fixes under different titles, etc.

glider@ suggested in
<https://lore.kernel.org/all/CAG_fn=U+V9wzvJJsRh3aB1uCm5zfWTFv3UHeBaPU_E_KXbDKFQ@mail.gmail.com/>:

| Could you also update Documentation/dev-tools/kcov.rst (a separate
| commit is also fine - it can cover the kcov_common_handle_id change as
| well)?

So that was my intent - to have these three separate patches:

"kcov: refactor common handle ID into kcov_common_handle_id"
"kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE"
"kcov: update documentation on remote coverage collection"

(where the documentation patch covers changes by both the other changes)

All the patches I sent were meant as full patches, not incremental fixups.

> I did my best to piece it all together then I joined everything into a
> single patch, below.  Please check it for accuracy, up-to-dateness and
> changelog truthfulness, thanks.

Yes, that is an accurate combination of "[PATCH v2] kcov: allow
simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE" and "[PATCH v2] kcov:
update documentation on remote coverage collection", and it is
up-to-date, and the changelog looks accurate.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2] kcov: update documentation on remote coverage collection
  2026-05-20 18:21 [PATCH v2] kcov: update documentation on remote coverage collection Jann Horn
  2026-05-21 23:18 ` Andrew Morton
@ 2026-06-05 13:46 ` Alexander Potapenko
  1 sibling, 0 replies; 4+ messages in thread
From: Alexander Potapenko @ 2026-06-05 13:46 UTC (permalink / raw)
  To: Jann Horn
  Cc: Dmitry Vyukov, Andrey Konovalov, kasan-dev, Andrew Morton, linux-kernel

On Wed, May 20, 2026 at 8:21 PM Jann Horn <jannh@google.com> wrote:
>
> Adjust the docs on remote coverage collection to reflect the changes made
> in "kcov: refactor common handle ID into kcov_common_handle_id" and
> "kcov: allow simultaneous KCOV_ENABLE/KCOV_REMOTE_ENABLE".
>
> Suggested-by: Alexander Potapenko <glider@google.com>
> Signed-off-by: Jann Horn <jannh@google.com>
Reviewed-by: Alexander Potapenko <glider@google.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-06-05 13:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-20 18:21 [PATCH v2] kcov: update documentation on remote coverage collection Jann Horn
2026-05-21 23:18 ` Andrew Morton
2026-05-26 14:08   ` Jann Horn
2026-06-05 13:46 ` Alexander Potapenko

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®