linux-doc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area()
@ 2025-07-28 18:43 Soham Bagchi
  2025-07-28 18:43 ` [PATCH 2/2] kcov: load acquire coverage count in user-space code Soham Bagchi
  2025-07-28 20:26 ` [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area() Marco Elver
  0 siblings, 2 replies; 7+ messages in thread
From: Soham Bagchi @ 2025-07-28 18:43 UTC (permalink / raw)
  To: dvyukov, andreyknvl, elver, akpm, tglx, glider, sohambagchi, arnd,
	kasan-dev, linux-kernel, corbet, workflows, linux-doc
  Cc: Soham Bagchi

KCOV Remote uses two separate memory buffers, one private to the kernel
space (kcov_remote_areas) and the second one shared between user and
kernel space (kcov->area). After every pair of kcov_remote_start() and
kcov_remote_stop(), the coverage data collected in the
kcov_remote_areas is copied to kcov->area so the user can read the
collected coverage data. This memcpy() is located in kcov_move_area().

The load/store pattern on the kernel-side [1] is:

```
/* dst_area === kcov->area, dst_area[0] is where the count is stored */
dst_len = READ_ONCE(*(unsigned long *)dst_area);
...
memcpy(dst_entries, src_entries, ...);
...
WRITE_ONCE(*(unsigned long *)dst_area, dst_len + entries_moved);
```

And for the user [2]:

```
/* cover is equivalent to kcov->area */
n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
```

Without a write-memory barrier, the atomic load for the user can
potentially read fresh values of the count stored at cover[0],
but continue to read stale coverage data from the buffer itself.
Hence, we recommend adding a write-memory barrier between the
memcpy() and the WRITE_ONCE() in kcov_move_area().

[1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/kernel/kcov.c?h=master#n978
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/dev-tools/kcov.rst#n364

Signed-off-by: Soham Bagchi <soham.bagchi@utah.edu>
---
 kernel/kcov.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/kernel/kcov.c b/kernel/kcov.c
index 187ba1b80bd..f6ee6d7dc2c 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -978,6 +978,15 @@ static void kcov_move_area(enum kcov_mode mode, void *dst_area,
 	memcpy(dst_entries, src_entries, bytes_to_move);
 	entries_moved = bytes_to_move >> entry_size_log;
 
+	/*
+	 * A write memory barrier is required here, to ensure
+	 * that the writes from the memcpy() are visible before
+	 * the count is updated. Without this, it is possible for
+	 * a user to observe a new count value but stale
+	 * coverage data.
+	 */
+	smp_wmb();
+
 	switch (mode) {
 	case KCOV_MODE_TRACE_PC:
 		WRITE_ONCE(*(unsigned long *)dst_area, dst_len + entries_moved);
-- 
2.34.1


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

* [PATCH 2/2] kcov: load acquire coverage count in user-space code
  2025-07-28 18:43 [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area() Soham Bagchi
@ 2025-07-28 18:43 ` Soham Bagchi
  2025-07-28 20:32   ` Marco Elver
  2025-07-28 20:26 ` [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area() Marco Elver
  1 sibling, 1 reply; 7+ messages in thread
From: Soham Bagchi @ 2025-07-28 18:43 UTC (permalink / raw)
  To: dvyukov, andreyknvl, elver, akpm, tglx, glider, sohambagchi, arnd,
	kasan-dev, linux-kernel, corbet, workflows, linux-doc
  Cc: Soham Bagchi

Updating the KCOV documentation to use a load-acquire
operation for the first element of the shared memory
buffer between kernel-space and user-space.

The load-acquire pairs with the write memory barrier
used in kcov_move_area()

Signed-off-by: Soham Bagchi <soham.bagchi@utah.edu>
---
 Documentation/dev-tools/kcov.rst | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
index 6611434e2dd..46450fb46fe 100644
--- a/Documentation/dev-tools/kcov.rst
+++ b/Documentation/dev-tools/kcov.rst
@@ -287,6 +287,11 @@ handle instance id.
 The following program demonstrates using KCOV to collect coverage from both
 local tasks spawned by the process and the global task that handles USB bus #1:
 
+The user-space code for KCOV should also use an acquire to fetch the count
+of coverage entries in the shared buffer. This acquire pairs with the
+corresponding write memory barrier (smp_wmb()) on the kernel-side in
+kcov_move_area().
+
 .. code-block:: c
 
     /* Same includes and defines as above. */
@@ -361,7 +366,7 @@ local tasks spawned by the process and the global task that handles USB bus #1:
 	 */
 	sleep(2);
 
-	n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
+	n = __atomic_load_n(&cover[0], __ATOMIC_ACQUIRE);
 	for (i = 0; i < n; i++)
 		printf("0x%lx\n", cover[i + 1]);
 	if (ioctl(fd, KCOV_DISABLE, 0))
-- 
2.34.1


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

* Re: [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area()
  2025-07-28 18:43 [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area() Soham Bagchi
  2025-07-28 18:43 ` [PATCH 2/2] kcov: load acquire coverage count in user-space code Soham Bagchi
@ 2025-07-28 20:26 ` Marco Elver
  1 sibling, 0 replies; 7+ messages in thread
From: Marco Elver @ 2025-07-28 20:26 UTC (permalink / raw)
  To: Soham Bagchi
  Cc: dvyukov, andreyknvl, akpm, tglx, glider, sohambagchi, arnd,
	kasan-dev, linux-kernel, corbet, workflows, linux-doc

On Mon, 28 Jul 2025 at 20:43, Soham Bagchi <soham.bagchi@utah.edu> wrote:
>
> KCOV Remote uses two separate memory buffers, one private to the kernel
> space (kcov_remote_areas) and the second one shared between user and
> kernel space (kcov->area). After every pair of kcov_remote_start() and
> kcov_remote_stop(), the coverage data collected in the
> kcov_remote_areas is copied to kcov->area so the user can read the
> collected coverage data. This memcpy() is located in kcov_move_area().
>
> The load/store pattern on the kernel-side [1] is:
>
> ```
> /* dst_area === kcov->area, dst_area[0] is where the count is stored */
> dst_len = READ_ONCE(*(unsigned long *)dst_area);
> ...
> memcpy(dst_entries, src_entries, ...);
> ...
> WRITE_ONCE(*(unsigned long *)dst_area, dst_len + entries_moved);
> ```
>
> And for the user [2]:
>
> ```
> /* cover is equivalent to kcov->area */
> n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
> ```
>
> Without a write-memory barrier, the atomic load for the user can
> potentially read fresh values of the count stored at cover[0],
> but continue to read stale coverage data from the buffer itself.
> Hence, we recommend adding a write-memory barrier between the
> memcpy() and the WRITE_ONCE() in kcov_move_area().
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/kernel/kcov.c?h=master#n978
> [2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/dev-tools/kcov.rst#n364
>
> Signed-off-by: Soham Bagchi <soham.bagchi@utah.edu>

Reviewed-by: Marco Elver <elver@google.com>

> ---
>  kernel/kcov.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/kernel/kcov.c b/kernel/kcov.c
> index 187ba1b80bd..f6ee6d7dc2c 100644
> --- a/kernel/kcov.c
> +++ b/kernel/kcov.c
> @@ -978,6 +978,15 @@ static void kcov_move_area(enum kcov_mode mode, void *dst_area,
>         memcpy(dst_entries, src_entries, bytes_to_move);
>         entries_moved = bytes_to_move >> entry_size_log;
>
> +       /*
> +        * A write memory barrier is required here, to ensure
> +        * that the writes from the memcpy() are visible before
> +        * the count is updated. Without this, it is possible for
> +        * a user to observe a new count value but stale
> +        * coverage data.
> +        */
> +       smp_wmb();
> +
>         switch (mode) {
>         case KCOV_MODE_TRACE_PC:
>                 WRITE_ONCE(*(unsigned long *)dst_area, dst_len + entries_moved);
> --
> 2.34.1
>
> --
> You received this message because you are subscribed to the Google Groups "kasan-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to kasan-dev+unsubscribe@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/kasan-dev/20250728184318.1839137-1-soham.bagchi%40utah.edu.

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

* Re: [PATCH 2/2] kcov: load acquire coverage count in user-space code
  2025-07-28 18:43 ` [PATCH 2/2] kcov: load acquire coverage count in user-space code Soham Bagchi
@ 2025-07-28 20:32   ` Marco Elver
  2025-08-03 18:05     ` [PATCH v2] " Soham Bagchi
  0 siblings, 1 reply; 7+ messages in thread
From: Marco Elver @ 2025-07-28 20:32 UTC (permalink / raw)
  To: Soham Bagchi
  Cc: dvyukov, andreyknvl, akpm, tglx, glider, sohambagchi, arnd,
	kasan-dev, linux-kernel, corbet, workflows, linux-doc

On Mon, 28 Jul 2025 at 20:43, Soham Bagchi <soham.bagchi@utah.edu> wrote:
>
> Updating the KCOV documentation to use a load-acquire
> operation for the first element of the shared memory
> buffer between kernel-space and user-space.
>
> The load-acquire pairs with the write memory barrier
> used in kcov_move_area()
>
> Signed-off-by: Soham Bagchi <soham.bagchi@utah.edu>
> ---
>  Documentation/dev-tools/kcov.rst | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
> index 6611434e2dd..46450fb46fe 100644
> --- a/Documentation/dev-tools/kcov.rst
> +++ b/Documentation/dev-tools/kcov.rst
> @@ -287,6 +287,11 @@ handle instance id.
>  The following program demonstrates using KCOV to collect coverage from both
>  local tasks spawned by the process and the global task that handles USB bus #1:
>
> +The user-space code for KCOV should also use an acquire to fetch the count
> +of coverage entries in the shared buffer. This acquire pairs with the
> +corresponding write memory barrier (smp_wmb()) on the kernel-side in
> +kcov_move_area().
> +

This new paragraph is misplaced.
You've added it after the "... handles USB bus #1:" part which clearly
should be right before the code (note the colon).

Why not add what you wrote here as a block-comment (similar in style
to comment above the sleep()) right above the __atomic_load_n below? I
think those details probably don't quite belong into the high level
text, but the detailed code example.

>  .. code-block:: c
>
>      /* Same includes and defines as above. */
> @@ -361,7 +366,7 @@ local tasks spawned by the process and the global task that handles USB bus #1:
>          */
>         sleep(2);
>
> -       n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
> +       n = __atomic_load_n(&cover[0], __ATOMIC_ACQUIRE);
>         for (i = 0; i < n; i++)
>                 printf("0x%lx\n", cover[i + 1]);
>         if (ioctl(fd, KCOV_DISABLE, 0))
> --
> 2.34.1
>

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

* [PATCH v2] kcov: load acquire coverage count in user-space code
  2025-07-28 20:32   ` Marco Elver
@ 2025-08-03 18:05     ` Soham Bagchi
  2025-08-04  6:00       ` Marco Elver
  0 siblings, 1 reply; 7+ messages in thread
From: Soham Bagchi @ 2025-08-03 18:05 UTC (permalink / raw)
  To: elver
  Cc: akpm, andreyknvl, arnd, corbet, dvyukov, glider, kasan-dev,
	linux-doc, linux-kernel, soham.bagchi, sohambagchi, tglx,
	workflows

Updating the KCOV documentation to use a load-acquire
operation for the first element of the shared memory
buffer between kernel-space and user-space.

The load-acquire pairs with the write memory barrier
used in kcov_move_area()

Signed-off-by: Soham Bagchi <soham.bagchi@utah.edu>
---

Changes in v2:
- note for load-acquire shifted to block comment
  in code rather than in the preceding paragraphs
---
 Documentation/dev-tools/kcov.rst | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
index 6611434e2dd..40a4b500073 100644
--- a/Documentation/dev-tools/kcov.rst
+++ b/Documentation/dev-tools/kcov.rst
@@ -361,7 +361,12 @@ local tasks spawned by the process and the global task that handles USB bus #1:
 	 */
 	sleep(2);
 
-	n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
+        /*
+         * The load to the coverage count should be an acquire to pair with 
+         * pair with the corresponding write memory barrier (smp_wmb()) on 
+         * the kernel-side in kcov_move_area().
+         */
+	n = __atomic_load_n(&cover[0], __ATOMIC_ACQUIRE);
 	for (i = 0; i < n; i++)
 		printf("0x%lx\n", cover[i + 1]);
 	if (ioctl(fd, KCOV_DISABLE, 0))
-- 
2.34.1


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

* Re: [PATCH v2] kcov: load acquire coverage count in user-space code
  2025-08-03 18:05     ` [PATCH v2] " Soham Bagchi
@ 2025-08-04  6:00       ` Marco Elver
  2025-08-07  0:36         ` Andrew Morton
  0 siblings, 1 reply; 7+ messages in thread
From: Marco Elver @ 2025-08-04  6:00 UTC (permalink / raw)
  To: Soham Bagchi
  Cc: akpm, andreyknvl, arnd, corbet, dvyukov, glider, kasan-dev,
	linux-doc, linux-kernel, sohambagchi, tglx, workflows

On Sun, 3 Aug 2025 at 20:06, Soham Bagchi <soham.bagchi@utah.edu> wrote:
>
> Updating the KCOV documentation to use a load-acquire
> operation for the first element of the shared memory
> buffer between kernel-space and user-space.
>
> The load-acquire pairs with the write memory barrier
> used in kcov_move_area()
>
> Signed-off-by: Soham Bagchi <soham.bagchi@utah.edu>

Reviewed-by: Marco Elver <elver@google.com>

> ---
>
> Changes in v2:

Btw, it is customary to send out the whole patch series on a version
bump, even if only one of the patches changed.
https://www.kernel.org/doc/html/latest/process/submitting-patches.html#explicit-in-reply-to-headers

> - note for load-acquire shifted to block comment
>   in code rather than in the preceding paragraphs
> ---
>  Documentation/dev-tools/kcov.rst | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/dev-tools/kcov.rst b/Documentation/dev-tools/kcov.rst
> index 6611434e2dd..40a4b500073 100644
> --- a/Documentation/dev-tools/kcov.rst
> +++ b/Documentation/dev-tools/kcov.rst
> @@ -361,7 +361,12 @@ local tasks spawned by the process and the global task that handles USB bus #1:
>          */
>         sleep(2);
>
> -       n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
> +        /*
> +         * The load to the coverage count should be an acquire to pair with
> +         * pair with the corresponding write memory barrier (smp_wmb()) on
> +         * the kernel-side in kcov_move_area().
> +         */
> +       n = __atomic_load_n(&cover[0], __ATOMIC_ACQUIRE);
>         for (i = 0; i < n; i++)
>                 printf("0x%lx\n", cover[i + 1]);
>         if (ioctl(fd, KCOV_DISABLE, 0))
> --
> 2.34.1
>

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

* Re: [PATCH v2] kcov: load acquire coverage count in user-space code
  2025-08-04  6:00       ` Marco Elver
@ 2025-08-07  0:36         ` Andrew Morton
  0 siblings, 0 replies; 7+ messages in thread
From: Andrew Morton @ 2025-08-07  0:36 UTC (permalink / raw)
  To: Marco Elver
  Cc: Soham Bagchi, andreyknvl, arnd, corbet, dvyukov, glider,
	kasan-dev, linux-doc, linux-kernel, sohambagchi, tglx, workflows

On Mon, 4 Aug 2025 08:00:00 +0200 Marco Elver <elver@google.com> wrote:

> > The load-acquire pairs with the write memory barrier
> > used in kcov_move_area()
> >
> > Signed-off-by: Soham Bagchi <soham.bagchi@utah.edu>
> 
> Reviewed-by: Marco Elver <elver@google.com>
> 
> > ---
> >
> > Changes in v2:
> 
> Btw, it is customary to send out the whole patch series on a version
> bump, even if only one of the patches changed.
> https://www.kernel.org/doc/html/latest/process/submitting-patches.html#explicit-in-reply-to-headers

Yes please, try to keep everything together.  We look at a lot of
patches!

I queued this as a -fix against the original
https://lkml.kernel.org/r/20250728184318.1839137-2-soham.bagchi@utah.edu

--- a/Documentation/dev-tools/kcov.rst~kcov-load-acquire-coverage-count-in-user-space-code-v2
+++ a/Documentation/dev-tools/kcov.rst
@@ -287,11 +287,6 @@ handle instance id.
 The following program demonstrates using KCOV to collect coverage from both
 local tasks spawned by the process and the global task that handles USB bus #1:
 
-The user-space code for KCOV should also use an acquire to fetch the count
-of coverage entries in the shared buffer. This acquire pairs with the
-corresponding write memory barrier (smp_wmb()) on the kernel-side in
-kcov_move_area().
-
 .. code-block:: c
 
     /* Same includes and defines as above. */
@@ -366,6 +361,11 @@ kcov_move_area().
 	 */
 	sleep(2);
 
+        /*
+         * The load to the coverage count should be an acquire to pair with
+         * pair with the corresponding write memory barrier (smp_wmb()) on
+         * the kernel-side in kcov_move_area().
+         */
 	n = __atomic_load_n(&cover[0], __ATOMIC_ACQUIRE);
 	for (i = 0; i < n; i++)
 		printf("0x%lx\n", cover[i + 1]);
_


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

end of thread, other threads:[~2025-08-07  0:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-28 18:43 [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area() Soham Bagchi
2025-07-28 18:43 ` [PATCH 2/2] kcov: load acquire coverage count in user-space code Soham Bagchi
2025-07-28 20:32   ` Marco Elver
2025-08-03 18:05     ` [PATCH v2] " Soham Bagchi
2025-08-04  6:00       ` Marco Elver
2025-08-07  0:36         ` Andrew Morton
2025-07-28 20:26 ` [PATCH 1/2] kcov: use write memory barrier after memcpy() in kcov_move_area() Marco Elver

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).