[RFC PATCH 13/24] fork: let new tasks start with task work

From: Li Chen

Date: Thu Jul 16 2026 - 11:53:30 EST


Process builders need to run setup in the child before its first return
to userspace without storing a kernel callback in architecture-specific
saved registers.

Allow an internal clone caller to supply task work. Queue it after the
last ordinary fork failure check, while the child is still TASK_NEW. A
NULL work pointer leaves existing clone callers unchanged.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Li Chen <me@linux.beauty>
---
include/linux/sched/task.h | 2 ++
kernel/fork.c | 6 ++++++
2 files changed, 8 insertions(+)

diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
index 5b7facf12b33b..830de99aabaed 100644
--- a/include/linux/sched/task.h
+++ b/include/linux/sched/task.h
@@ -43,6 +43,8 @@ struct kernel_clone_args {
int idle;
int (*fn)(void *);
void *fn_arg;
+ /* Run before the new task first returns to userspace. */
+ struct callback_head *task_work;
struct cgroup *cgrp;
struct css_set *cset;
bool embryonic_exec;
diff --git a/kernel/fork.c b/kernel/fork.c
index e3ade83b2d4e2..c0584eaa74711 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -109,6 +109,7 @@
#include <uapi/linux/pidfd.h>
#include <linux/pidfs.h>
#include <linux/tick.h>
+#include <linux/task_work.h>
#include <linux/unwind_deferred.h>
#include <linux/pgalloc.h>
#include <linux/uaccess.h>
@@ -2504,6 +2505,11 @@ __latent_entropy struct task_struct *copy_process(
retval = -EINTR;
goto bad_fork_core_free;
}
+ if (args->task_work) {
+ retval = task_work_add(p, args->task_work, TWA_RESUME);
+ if (WARN_ON_ONCE(retval))
+ goto bad_fork_core_free;
+ }

/* No more failure paths after this point. */

--
2.52.0