[RFC PATCH v2 05/14] kcov: clear dataflow fields on fork

From: Yunseong Kim

Date: Thu Jun 11 2026 - 12:32:07 EST


dup_task_struct() copies the parent task_struct byte-for-byte. Without
explicitly clearing the dataflow fields, a forked child inherits the
parent's kcov_df_enabled flag and buffer pointer, leading to two tasks
writing to the same buffer and a potential use-after-free if the parent
closes the trace file.

Add kcov_dataflow_task_init() in kernel/kcov_dataflow.c and call it from
kernel/fork.c alongside kcov_task_init(), matching how kcov_stop() clears
the legacy kcov fields during fork.

Reported-by: sashiko-bot <sashiko-bot@xxxxxxxxxx>
Closes: https://sashiko.dev/#/patchset/20260603-kcov-dataflow-next-20260603-v2-0-fee0939de2c4%40est.tech
Signed-off-by: Yunseong Kim <yunseong.kim@xxxxxxxx>
---
include/linux/kcov.h | 6 ++++++
kernel/fork.c | 1 +
kernel/kcov_dataflow.c | 10 ++++++++++
3 files changed, 17 insertions(+)

diff --git a/include/linux/kcov.h b/include/linux/kcov.h
index 895b761b2db1..e9822b02982b 100644
--- a/include/linux/kcov.h
+++ b/include/linux/kcov.h
@@ -28,6 +28,12 @@ enum kcov_mode {
void kcov_task_init(struct task_struct *t);
void kcov_task_exit(struct task_struct *t);

+#if defined(CONFIG_KCOV_DATAFLOW_ARGS) || defined(CONFIG_KCOV_DATAFLOW_RET)
+void kcov_dataflow_task_init(struct task_struct *t);
+#else
+static inline void kcov_dataflow_task_init(struct task_struct *t) {}
+#endif
+
#define kcov_prepare_switch(t) \
do { \
(t)->kcov_mode |= KCOV_IN_CTXSW; \
diff --git a/kernel/fork.c b/kernel/fork.c
index 892a95214c54..a5741de07979 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -980,6 +980,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
tsk->worker_private = NULL;

kcov_task_init(tsk);
+ kcov_dataflow_task_init(tsk);
kmsan_task_create(tsk);
kmap_local_fork(tsk);

diff --git a/kernel/kcov_dataflow.c b/kernel/kcov_dataflow.c
index 27587b8ceeab..7cfe2495275a 100644
--- a/kernel/kcov_dataflow.c
+++ b/kernel/kcov_dataflow.c
@@ -32,6 +32,7 @@
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/refcount.h>
+#include <linux/kcov.h>

#define KCOV_DF_TYPE_ENTRY 0xE0000000ULL
#define KCOV_DF_TYPE_RET 0xF0000000ULL
@@ -186,6 +187,15 @@ __sanitizer_cov_trace_ret(u64 pc, u32 ret_size, void *ret_val,
EXPORT_SYMBOL(__sanitizer_cov_trace_ret);
#endif

+/* Called from kernel/fork.c to clear inherited state. */
+void kcov_dataflow_task_init(struct task_struct *t)
+{
+ t->kcov_df_area = NULL;
+ t->kcov_df_size = 0;
+ t->kcov_df_seq = 0;
+ t->kcov_df_enabled = false;
+}
+
/* File operations for /sys/kernel/debug/kcov_dataflow */

static int kcov_df_open(struct inode *inode, struct file *filep)

--
2.43.0