From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F0EAC433EF for ; Fri, 6 May 2022 14:15:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1442170AbiEFOTX (ORCPT ); Fri, 6 May 2022 10:19:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42688 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1390697AbiEFOTR (ORCPT ); Fri, 6 May 2022 10:19:17 -0400 Received: from out03.mta.xmission.com (out03.mta.xmission.com [166.70.13.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D469A1DA6B; Fri, 6 May 2022 07:15:33 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:33830) by out03.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmyjz-001V0o-S3; Fri, 06 May 2022 08:15:32 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37210 helo=localhost.localdomain) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmyjy-007Cxx-8O; Fri, 06 May 2022 08:15:31 -0600 From: "Eric W. Biederman" To: linux-arch@vger.kernel.org Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , linux-kernel@vger.kernel.org, "Eric W. Biederman" , stable@vger.kernel.org, =?UTF-8?q?=D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC=20=D0=9A=D1=83=D1=82=D1=8F=D0=B2=D0=B8=D0=BD?= Date: Fri, 6 May 2022 09:15:06 -0500 Message-Id: <20220506141512.516114-1-ebiederm@xmission.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> References: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-XM-SPF: eid=1nmyjy-007Cxx-8O;;;mid=<20220506141512.516114-1-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX1/6Fq28LXF6kTwesTM8nfhPUaGtjnsT1W4= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 1/7] kthread: Don't allocate kthread_struct for init and umh X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If kthread_is_per_cpu runs concurrently with free_kthread_struct the kthread_struct that was just freed may be read from. This bug was introduced by commit 40966e316f86 ("kthread: Ensure struct kthread is present for all kthreads"). When kthread_struct started to be allocated for all tasks that have PF_KTHREAD set. This in turn required the kthread_struct to be freed in kernel_execve and violated the assumption that kthread_struct will have the same lifetime as the task. Looking a bit deeper this only applies to callers of kernel_execve which is just the init process and the user mode helper processes. These processes really don't want to be kernel threads but are for historical reasons. Mostly that copy_thread does not know how to take a kernel mode function to the process with for processes without PF_KTHREAD or PF_IO_WORKER set. Solve this by not allocating kthread_struct for the init process and the user mode helper processes. This is done by adding a kthread member to struct kernel_clone_args. Setting kthread in fork_idle and kernel_thread. Adding user_mode_thread that works like kernel_thread except it does not set kthread. In fork only allocating the kthread_struct if .kthread is set. I have looked at kernel/kthread.c and since commit 40966e316f86 ("kthread: Ensure struct kthread is present for all kthreads") there have been no assumptions added that to_kthread or __to_kthread will not return NULL. There are a few callers of to_kthread or __to_kthread that assume a non-NULL struct kthread pointer will be returned. These functions are kthread_data(), kthread_parmme(), kthread_exit(), kthread(), kthread_park(), kthread_unpark(), kthread_stop(). All of those functions can reasonably expected to be called when it is know that a task is a kthread so that assumption seems reasonable. Cc: stable@vger.kernel.org Fixes: 40966e316f86 ("kthread: Ensure struct kthread is present for all kth= reads") Reported-by: =D0=9C=D0=B0=D0=BA=D1=81=D0=B8=D0=BC =D0=9A=D1=83=D1=82=D1=8F= =D0=B2=D0=B8=D0=BD Signed-off-by: "Eric W. Biederman" --- fs/exec.c | 6 ++++-- include/linux/sched/task.h | 2 ++ init/main.c | 2 +- kernel/fork.c | 22 ++++++++++++++++++++-- kernel/umh.c | 6 +++--- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index e3e55d5e0be1..75eb6e0ee7b2 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1308,8 +1308,6 @@ int begin_new_exec(struct linux_binprm * bprm) if (retval) goto out_unlock; =20 - if (me->flags & PF_KTHREAD) - free_kthread_struct(me); me->flags &=3D ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE | PF_NO_SETAFFINITY); flush_thread(); @@ -1955,6 +1953,10 @@ int kernel_execve(const char *kernel_filename, int fd =3D AT_FDCWD; int retval; =20 + if (WARN_ON_ONCE((current->flags & PF_KTHREAD) && + (current->worker_private))) + return -EINVAL; + filename =3D getname_kernel(kernel_filename); if (IS_ERR(filename)) return PTR_ERR(filename); diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index 719c9a6cac8d..4492266935dd 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -32,6 +32,7 @@ struct kernel_clone_args { size_t set_tid_size; int cgroup; int io_thread; + int kthread; struct cgroup *cgrp; struct css_set *cset; }; @@ -89,6 +90,7 @@ struct task_struct *create_io_thread(int (*fn)(void *), v= oid *arg, int node); struct task_struct *fork_idle(int); struct mm_struct *copy_init_mm(void); extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long fla= gs); +extern pid_t user_mode_thread(int (*fn)(void *), void *arg, unsigned long = flags); extern long kernel_wait4(pid_t, int __user *, int, struct rusage *); int kernel_wait(pid_t pid, int *stat); =20 diff --git a/init/main.c b/init/main.c index 98182c3c2c4b..39baac0211c6 100644 --- a/init/main.c +++ b/init/main.c @@ -688,7 +688,7 @@ noinline void __ref rest_init(void) * the init task will end up wanting to create kthreads, which, if * we schedule it before we create kthreadd, will OOPS. */ - pid =3D kernel_thread(kernel_init, NULL, CLONE_FS); + pid =3D user_mode_thread(kernel_init, NULL, CLONE_FS); /* * Pin init on the boot CPU. Task migration is not properly working * until sched_init_smp() has been run. It will set the allowed diff --git a/kernel/fork.c b/kernel/fork.c index 9796897560ab..27c5203750b4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2157,7 +2157,7 @@ static __latent_entropy struct task_struct *copy_proc= ess( p->io_context =3D NULL; audit_set_context(p, NULL); cgroup_fork(p); - if (p->flags & PF_KTHREAD) { + if (args->kthread) { if (!set_kthread_struct(p)) goto bad_fork_cleanup_delayacct; } @@ -2548,7 +2548,8 @@ struct task_struct * __init fork_idle(int cpu) { struct task_struct *task; struct kernel_clone_args args =3D { - .flags =3D CLONE_VM, + .flags =3D CLONE_VM, + .kthread =3D 1, }; =20 task =3D copy_process(&init_struct_pid, 0, cpu_to_node(cpu), &args); @@ -2679,6 +2680,23 @@ pid_t kernel_clone(struct kernel_clone_args *args) * Create a kernel thread. */ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + struct kernel_clone_args args =3D { + .flags =3D ((lower_32_bits(flags) | CLONE_VM | + CLONE_UNTRACED) & ~CSIGNAL), + .exit_signal =3D (lower_32_bits(flags) & CSIGNAL), + .stack =3D (unsigned long)fn, + .stack_size =3D (unsigned long)arg, + .kthread =3D 1, + }; + + return kernel_clone(&args); +} + +/* + * Create a user mode thread. + */ +pid_t user_mode_thread(int (*fn)(void *), void *arg, unsigned long flags) { struct kernel_clone_args args =3D { .flags =3D ((lower_32_bits(flags) | CLONE_VM | diff --git a/kernel/umh.c b/kernel/umh.c index 36c123360ab8..b989736e8707 100644 --- a/kernel/umh.c +++ b/kernel/umh.c @@ -132,7 +132,7 @@ static void call_usermodehelper_exec_sync(struct subpro= cess_info *sub_info) =20 /* If SIGCLD is ignored do_wait won't populate the status. */ kernel_sigaction(SIGCHLD, SIG_DFL); - pid =3D kernel_thread(call_usermodehelper_exec_async, sub_info, SIGCHLD); + pid =3D user_mode_thread(call_usermodehelper_exec_async, sub_info, SIGCHL= D); if (pid < 0) sub_info->retval =3D pid; else @@ -171,8 +171,8 @@ static void call_usermodehelper_exec_work(struct work_s= truct *work) * want to pollute current->children, and we need a parent * that always ignores SIGCHLD to ensure auto-reaping. */ - pid =3D kernel_thread(call_usermodehelper_exec_async, sub_info, - CLONE_PARENT | SIGCHLD); + pid =3D user_mode_thread(call_usermodehelper_exec_async, sub_info, + CLONE_PARENT | SIGCHLD); if (pid < 0) { sub_info->retval =3D pid; umh_complete(sub_info); --=20 2.35.3 From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6FF4BC433EF for ; Fri, 6 May 2022 14:15:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1442145AbiEFOTc (ORCPT ); Fri, 6 May 2022 10:19:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1442140AbiEFOTW (ORCPT ); Fri, 6 May 2022 10:19:22 -0400 Received: from out01.mta.xmission.com (out01.mta.xmission.com [166.70.13.231]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26CEF1DA6B; Fri, 6 May 2022 07:15:36 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:55974) by out01.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmyk3-007C8x-Do; Fri, 06 May 2022 08:15:35 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37210 helo=localhost.localdomain) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmyk1-007Cxx-3p; Fri, 06 May 2022 08:15:34 -0600 From: "Eric W. Biederman" To: linux-arch@vger.kernel.org Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , linux-kernel@vger.kernel.org, "Eric W. Biederman" Date: Fri, 6 May 2022 09:15:07 -0500 Message-Id: <20220506141512.516114-2-ebiederm@xmission.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> References: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-XM-SPF: eid=1nmyk1-007Cxx-3p;;;mid=<20220506141512.516114-2-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX18EWowv4UmYU8OgbxfJhOr0MsF/jYW8XGU= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 2/7] fork: Pass struct kernel_clone_args into copy_thread X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" With io_uring we have started supporting tasks that are for most purposes user space tasks that exclusively run code in kernel mode. The kernel task that exec's init and tasks that exec user mode helpers are also user mode tasks that just run kernel code until they call kernel execve. Pass kernel_clone_args into copy_thread so these oddball tasks can be supported more cleanly and easily. Signed-off-by: "Eric W. Biederman" Reported-by: kernel test robot --- arch/alpha/kernel/process.c | 8 +++++--- arch/arc/kernel/process.c | 8 +++++--- arch/arm/kernel/process.c | 7 +++++-- arch/arm64/kernel/process.c | 7 +++++-- arch/csky/kernel/process.c | 10 +++++----- arch/h8300/kernel/process.c | 5 +++-- arch/hexagon/kernel/process.c | 7 +++++-- arch/ia64/kernel/process.c | 7 +++++-- arch/m68k/kernel/process.c | 7 +++++-- arch/microblaze/kernel/process.c | 7 +++++-- arch/mips/kernel/process.c | 8 +++++--- arch/nios2/kernel/process.c | 7 +++++-- arch/openrisc/kernel/process.c | 7 +++++-- arch/parisc/kernel/process.c | 7 +++++-- arch/powerpc/kernel/process.c | 8 +++++--- arch/riscv/kernel/process.c | 7 +++++-- arch/s390/kernel/process.c | 7 +++++-- arch/sh/kernel/process_32.c | 7 +++++-- arch/sparc/kernel/process_32.c | 7 +++++-- arch/sparc/kernel/process_64.c | 7 +++++-- arch/um/kernel/process.c | 7 +++++-- arch/x86/kernel/process.c | 7 +++++-- arch/xtensa/kernel/process.c | 8 +++++--- include/linux/sched/task.h | 3 +-- kernel/fork.c | 4 ++-- 25 files changed, 116 insertions(+), 58 deletions(-) diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 5f8527081da9..732e39217c7f 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -233,10 +233,12 @@ release_thread(struct task_struct *dead_task) /* * Copy architecture-specific thread state */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p, - unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long kthread_arg =3D args->stack_size; + unsigned long tls =3D args->tls; extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); =20 diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 5f7f5aab361f..caf948ba647c 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -162,10 +162,12 @@ asmlinkage void ret_from_fork(void); * | user_r25 | * ------------------ <=3D=3D=3D=3D=3D END of PAGE */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p, - unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long kthread_arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *c_regs; /* child's pt_regs */ unsigned long *childksp; /* to unwind out of __switch_to() */ struct callee_regs *c_callee; /* child's callee regs */ diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 0617af11377f..8e13b426dd26 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -238,9 +238,12 @@ void release_thread(struct task_struct *dead_task) =20 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); =20 -int copy_thread(unsigned long clone_flags, unsigned long stack_start, - unsigned long stk_sz, struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long stack_start =3D args->stack; + unsigned long stk_sz =3D args->stack_size; + unsigned long tls =3D args->tls; struct thread_info *thread =3D task_thread_info(p); struct pt_regs *childregs =3D task_pt_regs(p); =20 diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 7fa97df55e3a..e002f6681c8d 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -316,9 +316,12 @@ int arch_dup_task_struct(struct task_struct *dst, stru= ct task_struct *src) =20 asmlinkage void ret_from_fork(void) asm("ret_from_fork"); =20 -int copy_thread(unsigned long clone_flags, unsigned long stack_start, - unsigned long stk_sz, struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long stack_start =3D args->stack; + unsigned long stk_sz =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); =20 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c index 3d0ca22cd0e2..7dba33d37e1a 100644 --- a/arch/csky/kernel/process.c +++ b/arch/csky/kernel/process.c @@ -30,12 +30,12 @@ asmlinkage void ret_from_kernel_thread(void); */ void flush_thread(void){} =20 -int copy_thread(unsigned long clone_flags, - unsigned long usp, - unsigned long kthread_arg, - struct task_struct *p, - unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long kthread_arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct switch_stack *childstack; struct pt_regs *childregs =3D task_pt_regs(p); =20 diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 8833fa4f5d51..296ff831446e 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -105,9 +105,10 @@ void flush_thread(void) { } =20 -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long topstk, struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const kernel_cloen_args *args) { + unsigned long usp =3D args->stack; + unsigned long topstk =3D args->stack_size; struct pt_regs *childregs; =20 childregs =3D (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c index eab03c691f53..f1c1f6f21941 100644 --- a/arch/hexagon/kernel/process.c +++ b/arch/hexagon/kernel/process.c @@ -50,9 +50,12 @@ void arch_cpu_idle(void) /* * Copy architecture-specific thread state */ -int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned lon= g arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct hexagon_switch_stack *ss; struct pt_regs *childregs; diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index d7a256bd9d6b..10d41ded05a5 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -295,9 +295,12 @@ ia64_load_extra (struct task_struct *task) * so there is nothing to worry about. */ int -copy_thread(unsigned long clone_flags, unsigned long user_stack_base, - unsigned long user_stack_size, struct task_struct *p, unsigned long t= ls) +copy_thread(struct task_struct *p, const struct kernel_clone_args *args) { + unsigned long clone_flags =3D args->flags; + unsigned long user_stack_base =3D args->stack; + unsigned long user_stack_size =3D args->stack_size; + unsigned long tls =3D args->tls; extern char ia64_ret_from_clone; struct switch_stack *child_stack, *stack; unsigned long rbs, child_rbs, rbs_size; diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index a6030dbaa089..8ac575656fc4 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -138,9 +138,12 @@ asmlinkage int m68k_clone3(struct pt_regs *regs) return sys_clone3((struct clone_args __user *)regs->d1, regs->d2); } =20 -int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned lon= g arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct fork_frame { struct switch_stack sw; struct pt_regs regs; diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/proc= ess.c index 1b944d319d73..b5f549125c6a 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -52,9 +52,12 @@ void flush_thread(void) { } =20 -int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned lon= g arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); struct thread_info *ti =3D task_thread_info(p); =20 diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index c2d5f4bfe1f3..a572d097b16b 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -105,10 +105,12 @@ int arch_dup_task_struct(struct task_struct *dst, str= uct task_struct *src) /* * Copy architecture-specific thread state */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p, - unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long kthread_arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct pt_regs *childregs, *regs =3D current_pt_regs(); unsigned long childksp; diff --git a/arch/nios2/kernel/process.c b/arch/nios2/kernel/process.c index f8ea522a1588..98c4bfe972e0 100644 --- a/arch/nios2/kernel/process.c +++ b/arch/nios2/kernel/process.c @@ -100,9 +100,12 @@ void flush_thread(void) { } =20 -int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned lon= g arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); struct pt_regs *regs; struct switch_stack *stack; diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index 3c0c91bcdcba..486e46dd5883 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -152,9 +152,12 @@ extern asmlinkage void ret_from_fork(void); */ =20 int -copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long ar= g, - struct task_struct *p, unsigned long tls) +copy_thread(struct task_struct *p, const struct kernel_clone_args *args) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *userregs; struct pt_regs *kregs; unsigned long sp =3D (unsigned long)task_stack_page(p) + THREAD_SIZE; diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 28b6a2a5574c..129c17de45ba 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -206,9 +206,12 @@ arch_initcall(parisc_idle_init); * Copy architecture-specific thread state */ int -copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p, unsigned long tls) +copy_thread(struct task_struct *p, const struct kernel_clone_args *args) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long kthread_arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *cregs =3D &(p->thread.regs); void *stack =3D task_stack_page(p); =09 diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 984813a4d5dc..3fd67c861d54 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1716,10 +1716,12 @@ static void setup_ksp_vsid(struct task_struct *p, u= nsigned long sp) /* * Copy architecture-specific thread state */ -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long kthread_arg, struct task_struct *p, - unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long kthread_arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); extern void ret_from_fork_scv(void); diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 504b496787aa..334382731725 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -120,9 +120,12 @@ int arch_dup_task_struct(struct task_struct *dst, stru= ct task_struct *src) return 0; } =20 -int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned lon= g arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); =20 /* p->thread holds context to be restored by __switch_to() */ diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 71d86f73b02c..bb5daec39516 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -94,9 +94,12 @@ int arch_dup_task_struct(struct task_struct *dst, struct= task_struct *src) return 0; } =20 -int copy_thread(unsigned long clone_flags, unsigned long new_stackp, - unsigned long arg, struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long new_stackp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct fake_frame { struct stack_frame sf; diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index ca01286a0610..6023399b1892 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -92,9 +92,12 @@ void release_thread(struct task_struct *dead_task) asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); =20 -int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned lon= g arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct pt_regs *childregs; =20 diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 88c0c14aaff0..80e6775e18c0 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -259,9 +259,12 @@ clone_stackframe(struct sparc_stackf __user *dst, extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); =20 -int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long= arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long sp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct pt_regs *childregs, *regs =3D current_pt_regs(); char *new_stack; diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index 9a2ceb080ac9..38c46ca826d9 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -564,9 +564,12 @@ void fault_in_user_windows(struct pt_regs *regs) * Parent --> %o0 =3D=3D childs pid, %o1 =3D=3D 0 * Child --> %o0 =3D=3D parents pid, %o1 =3D=3D 1 */ -int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long= arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long sp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct thread_info *t =3D task_thread_info(p); struct pt_regs *regs =3D current_pt_regs(); struct sparc_stackf *parent_sf; diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 80504680be08..fd2d2361484d 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -154,9 +154,12 @@ void fork_handler(void) userspace(¤t->thread.regs.regs, current_thread_info()->aux_fp_regs); } =20 -int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long arg, struct task_struct * p, unsigned long tls) +int copy_thread(struct task_struct * p, const struct kernel_clone_args *ar= gs) { + unsigned long clone_flags =3D args->flags; + unsigned long sp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; void (*handler)(void); int kthread =3D current->flags & (PF_KTHREAD | PF_IO_WORKER); int ret =3D 0; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index b370767f5b19..0fce52b10dc4 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -130,9 +130,12 @@ static int set_new_tls(struct task_struct *p, unsigned= long tls) return do_set_thread_area_64(p, ARCH_SET_FS, tls); } =20 -int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long= arg, - struct task_struct *p, unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long sp =3D args->stack; + unsigned long arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct inactive_task_frame *frame; struct fork_frame *fork_frame; struct pt_regs *childregs; diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index e8bfbca5f001..15ce25073142 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -201,10 +201,12 @@ int arch_dup_task_struct(struct task_struct *dst, str= uct task_struct *src) * involved. Much simpler to just not copy those live frames across. */ =20 -int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, - unsigned long thread_fn_arg, struct task_struct *p, - unsigned long tls) +int copy_thread(struct task_struct *p, const struct kernel_clone_args *arg= s) { + unsigned long clone_flags =3D args->flags; + unsigned long usp_thread_fn =3D args->stack; + unsigned long thread_fn_arg =3D args->stack_size; + unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); =20 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index 4492266935dd..fcdcba231aac 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -68,8 +68,7 @@ extern void fork_init(void); =20 extern void release_task(struct task_struct * p); =20 -extern int copy_thread(unsigned long, unsigned long, unsigned long, - struct task_struct *, unsigned long); +extern int copy_thread(struct task_struct *, const struct kernel_clone_arg= s *); =20 extern void flush_thread(void); =20 diff --git a/kernel/fork.c b/kernel/fork.c index 27c5203750b4..d39a248a8d8d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1979,7 +1979,7 @@ static __latent_entropy struct task_struct *copy_proc= ess( struct task_struct *p; struct multiprocess_signals delayed; struct file *pidfile =3D NULL; - u64 clone_flags =3D args->flags; + const u64 clone_flags =3D args->flags; struct nsproxy *nsp =3D current->nsproxy; =20 /* @@ -2240,7 +2240,7 @@ static __latent_entropy struct task_struct *copy_proc= ess( retval =3D copy_io(clone_flags, p); if (retval) goto bad_fork_cleanup_namespaces; - retval =3D copy_thread(clone_flags, args->stack, args->stack_size, p, arg= s->tls); + retval =3D copy_thread(p, args); if (retval) goto bad_fork_cleanup_io; =20 --=20 2.35.3 From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CCB53C43217 for ; Fri, 6 May 2022 14:15:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1442155AbiEFOTg (ORCPT ); Fri, 6 May 2022 10:19:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42830 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1442156AbiEFOTW (ORCPT ); Fri, 6 May 2022 10:19:22 -0400 Received: from out03.mta.xmission.com (out03.mta.xmission.com [166.70.13.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 24F6024BDB; Fri, 6 May 2022 07:15:39 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:33946) by out03.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmyk5-001V1f-P3; Fri, 06 May 2022 08:15:38 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37210 helo=localhost.localdomain) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmyk4-007Cxx-KB; Fri, 06 May 2022 08:15:37 -0600 From: "Eric W. Biederman" To: linux-arch@vger.kernel.org Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , linux-kernel@vger.kernel.org, "Eric W. Biederman" Date: Fri, 6 May 2022 09:15:08 -0500 Message-Id: <20220506141512.516114-3-ebiederm@xmission.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> References: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-XM-SPF: eid=1nmyk4-007Cxx-KB;;;mid=<20220506141512.516114-3-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX1/mDmv+ns3fcb9e/GMSp2NnY4KNRo/+Yic= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 3/7] fork: Explicity test for idle tasks in copy_thread X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The architectures ia64 and parisc have special handling for the idle thread in copy_process. Add a flag named idle to kernel_clone_args and use it to explicity test if an idle process is being created. Fullfill the expectations of the rest of the copy_thread implemetations and pass a function pointer in .stack from fork_idle(). This makes what is happening in copy_thread better defined, and is useful to make idle threads less special. Signed-off-by: "Eric W. Biederman" --- arch/ia64/kernel/process.c | 2 +- arch/parisc/kernel/process.c | 2 +- include/linux/sched/task.h | 1 + kernel/fork.c | 9 +++++++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 10d41ded05a5..8f010ae818bc 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -342,7 +342,7 @@ copy_thread(struct task_struct *p, const struct kernel_= clone_args *args) ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ =20 if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { - if (unlikely(!user_stack_base)) { + if (unlikely(args->idle)) { /* fork_idle() called us */ return 0; } diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 129c17de45ba..30a5874ca845 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -224,7 +224,7 @@ copy_thread(struct task_struct *p, const struct kernel_= clone_args *args) if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { /* kernel thread */ memset(cregs, 0, sizeof(struct pt_regs)); - if (!usp) /* idle thread */ + if (args->idle) /* idle thread */ return 0; /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index fcdcba231aac..3d6b99ce5408 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -33,6 +33,7 @@ struct kernel_clone_args { int cgroup; int io_thread; int kthread; + int idle; struct cgroup *cgrp; struct css_set *cset; }; diff --git a/kernel/fork.c b/kernel/fork.c index d39a248a8d8d..93d77ee921ff 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2544,12 +2544,21 @@ static inline void init_idle_pids(struct task_struc= t *idle) } } =20 +static int idle_dummy(void *dummy) +{ + /* This function is never called */ + return 0; +} + struct task_struct * __init fork_idle(int cpu) { struct task_struct *task; struct kernel_clone_args args =3D { .flags =3D CLONE_VM, + .stack =3D (unsigned long)&idle_dummy, + .stack_size =3D (unsigned long)NULL, .kthread =3D 1, + .idle =3D 1, }; =20 task =3D copy_process(&init_struct_pid, 0, cpu_to_node(cpu), &args); --=20 2.35.3 From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 62E20C433EF for ; Fri, 6 May 2022 14:15:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1442169AbiEFOTi (ORCPT ); Fri, 6 May 2022 10:19:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42916 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1442201AbiEFOT2 (ORCPT ); Fri, 6 May 2022 10:19:28 -0400 Received: from out01.mta.xmission.com (out01.mta.xmission.com [166.70.13.231]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9AC5689BE; Fri, 6 May 2022 07:15:43 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:56086) by out01.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmykA-007CCn-7V; Fri, 06 May 2022 08:15:42 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37210 helo=localhost.localdomain) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmyk7-007Cxx-0l; Fri, 06 May 2022 08:15:41 -0600 From: "Eric W. Biederman" To: linux-arch@vger.kernel.org Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , linux-kernel@vger.kernel.org, "Eric W. Biederman" Date: Fri, 6 May 2022 09:15:09 -0500 Message-Id: <20220506141512.516114-4-ebiederm@xmission.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> References: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-XM-SPF: eid=1nmyk7-007Cxx-0l;;;mid=<20220506141512.516114-4-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX1+yxzSsqYESjuBvR1QAuIiTLD1G9JGUvi0= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 4/7] fork: Generalize PF_IO_WORKER handling X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add fn and fn_arg members into struct kernel_clone_args and test for them in copy_thread (instead of testing for PF_KTHREAD | PF_IO_WORKER). This allows any task that wants to be a user space task that only runs in kernel mode to use this functionality. The code on x86 is an exception and still retains a PF_KTHREAD test because x86 unlikely everything else handles kthreads slightly differently than user space tasks that start with a function. The functions that created tasks that start with a function have been updated to set ".fn" and ".fn_arg" instead of ".stack" and ".stack_size". These functions are fork_idle(), create_io_thread(), kernel_thread(), and user_mode_thread(). Signed-off-by: "Eric W. Biederman" --- arch/alpha/kernel/process.c | 7 +++---- arch/arc/kernel/process.c | 7 +++---- arch/arm/kernel/process.c | 7 +++---- arch/arm64/kernel/process.c | 7 +++---- arch/csky/kernel/process.c | 7 +++---- arch/h8300/kernel/process.c | 7 +++---- arch/hexagon/kernel/process.c | 7 +++---- arch/ia64/kernel/process.c | 6 +++--- arch/m68k/kernel/process.c | 7 +++---- arch/microblaze/kernel/process.c | 7 +++---- arch/mips/kernel/process.c | 7 +++---- arch/nios2/kernel/process.c | 7 +++---- arch/openrisc/kernel/process.c | 7 +++---- arch/parisc/kernel/process.c | 11 +++++------ arch/powerpc/kernel/process.c | 9 ++++----- arch/riscv/kernel/process.c | 7 +++---- arch/s390/kernel/process.c | 7 +++---- arch/sh/kernel/process_32.c | 7 +++---- arch/sparc/kernel/process_32.c | 7 +++---- arch/sparc/kernel/process_64.c | 7 +++---- arch/um/kernel/process.c | 10 ++++------ arch/x86/include/asm/fpu/sched.h | 2 +- arch/x86/include/asm/switch_to.h | 8 ++++---- arch/x86/kernel/fpu/core.c | 4 ++-- arch/x86/kernel/process.c | 13 ++++++------- arch/xtensa/kernel/process.c | 11 +++++------ include/linux/sched/task.h | 2 ++ kernel/fork.c | 16 ++++++++-------- 28 files changed, 95 insertions(+), 116 deletions(-) diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 732e39217c7f..6cbba7370b4e 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -237,7 +237,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long kthread_arg =3D args->stack_size; unsigned long tls =3D args->tls; extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); @@ -251,13 +250,13 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) childti->pcb.ksp =3D (unsigned long) childstack; childti->pcb.flags =3D 1; /* set FEN, clear everything else */ =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* kernel thread */ memset(childstack, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); childstack->r26 =3D (unsigned long) ret_from_kernel_thread; - childstack->r9 =3D usp; /* function */ - childstack->r10 =3D kthread_arg; + childstack->r9 =3D (unsigned long) args->fn; + childstack->r10 =3D (unsigned long) args->fn_arg; childregs->hae =3D alpha_mv.hae_cache; childti->pcb.usp =3D 0; return 0; diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index caf948ba647c..3369f0700702 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -166,7 +166,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long kthread_arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *c_regs; /* child's pt_regs */ unsigned long *childksp; /* to unwind out of __switch_to() */ @@ -193,11 +192,11 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) childksp[0] =3D 0; /* fp */ childksp[1] =3D (unsigned long)ret_from_fork; /* blink */ =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(c_regs, 0, sizeof(struct pt_regs)); =20 - c_callee->r13 =3D kthread_arg; - c_callee->r14 =3D usp; /* function */ + c_callee->r13 =3D (unsigned long)args->fn_arg; + c_callee->r14 =3D (unsigned long)args->fn; =20 return 0; } diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 8e13b426dd26..3d9cace63884 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -242,7 +242,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long stack_start =3D args->stack; - unsigned long stk_sz =3D args->stack_size; unsigned long tls =3D args->tls; struct thread_info *thread =3D task_thread_info(p); struct pt_regs *childregs =3D task_pt_regs(p); @@ -259,15 +258,15 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) thread->cpu_domain =3D get_domain(); #endif =20 - if (likely(!(p->flags & (PF_KTHREAD | PF_IO_WORKER)))) { + if (likely(!args->fn)) { *childregs =3D *current_pt_regs(); childregs->ARM_r0 =3D 0; if (stack_start) childregs->ARM_sp =3D stack_start; } else { memset(childregs, 0, sizeof(struct pt_regs)); - thread->cpu_context.r4 =3D stk_sz; - thread->cpu_context.r5 =3D stack_start; + thread->cpu_context.r4 =3D (unsigned long)args->fn_arg; + thread->cpu_context.r5 =3D (unsigned long)args->fn; childregs->ARM_cpsr =3D SVC_MODE; } thread->cpu_context.pc =3D (unsigned long)ret_from_fork; diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index e002f6681c8d..d0ef05c661b0 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -320,7 +320,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long stack_start =3D args->stack; - unsigned long stk_sz =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); =20 @@ -337,7 +336,7 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) =20 ptrauth_thread_init_kernel(p); =20 - if (likely(!(p->flags & (PF_KTHREAD | PF_IO_WORKER)))) { + if (likely(!args->fn)) { *childregs =3D *current_pt_regs(); childregs->regs[0] =3D 0; =20 @@ -371,8 +370,8 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) memset(childregs, 0, sizeof(struct pt_regs)); childregs->pstate =3D PSR_MODE_EL1h | PSR_IL_BIT; =20 - p->thread.cpu_context.x19 =3D stack_start; - p->thread.cpu_context.x20 =3D stk_sz; + p->thread.cpu_context.x19 =3D (unsigned long)args->fn; + p->thread.cpu_context.x20 =3D (unsigned long)args->fn_arg; } p->thread.cpu_context.pc =3D (unsigned long)ret_from_fork; p->thread.cpu_context.sp =3D (unsigned long)childregs; diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c index 7dba33d37e1a..9af49aea1c3b 100644 --- a/arch/csky/kernel/process.c +++ b/arch/csky/kernel/process.c @@ -34,7 +34,6 @@ int copy_thread(struct task_struct *p, const struct kerne= l_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long kthread_arg =3D args->stack_size; unsigned long tls =3D args->tls; struct switch_stack *childstack; struct pt_regs *childregs =3D task_pt_regs(p); @@ -49,11 +48,11 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) /* setup thread.sp for switch_to !!! */ p->thread.sp =3D (unsigned long)childstack; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(childregs, 0, sizeof(struct pt_regs)); childstack->r15 =3D (unsigned long) ret_from_kernel_thread; - childstack->r10 =3D kthread_arg; - childstack->r9 =3D usp; + childstack->r10 =3D (unsigned long) args->fn_arg; + childstack->r9 =3D (unsigned long) args->fn; childregs->sr =3D mfcr("psr"); } else { *childregs =3D *(current_pt_regs()); diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 296ff831446e..5bfe0f8f54bf 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -108,16 +108,15 @@ void flush_thread(void) int copy_thread(struct task_struct *p, const kernel_cloen_args *args) { unsigned long usp =3D args->stack; - unsigned long topstk =3D args->stack_size; struct pt_regs *childregs; =20 childregs =3D (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(childregs, 0, sizeof(struct pt_regs)); childregs->retpc =3D (unsigned long) ret_from_kernel_thread; - childregs->er4 =3D topstk; /* arg */ - childregs->er5 =3D usp; /* fn */ + childregs->er4 =3D (unsigned long) args->fn_arg; + childregs->er5 =3D (unsigned long) args->fn; } else { *childregs =3D *current_pt_regs(); childregs->er0 =3D 0; diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c index f1c1f6f21941..f0552f98a7ba 100644 --- a/arch/hexagon/kernel/process.c +++ b/arch/hexagon/kernel/process.c @@ -54,7 +54,6 @@ int copy_thread(struct task_struct *p, const struct kerne= l_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct hexagon_switch_stack *ss; @@ -76,11 +75,11 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) sizeof(*ss)); ss->lr =3D (unsigned long)ret_from_fork; p->thread.switch_sp =3D ss; - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(childregs, 0, sizeof(struct pt_regs)); /* r24 <- fn, r25 <- arg */ - ss->r24 =3D usp; - ss->r25 =3D arg; + ss->r24 =3D (unsigned long)args->fn; + ss->r25 =3D (unsigned long)args->fn_arg; pt_set_kmode(childregs); return 0; } diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 8f010ae818bc..167b1765bea1 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -341,14 +341,14 @@ copy_thread(struct task_struct *p, const struct kerne= l_clone_args *args) =20 ia64_drop_fpu(p); /* don't pick up stale state from a CPU's fph */ =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { if (unlikely(args->idle)) { /* fork_idle() called us */ return 0; } memset(child_stack, 0, sizeof(*child_ptregs) + sizeof(*child_stack)); - child_stack->r4 =3D user_stack_base; /* payload */ - child_stack->r5 =3D user_stack_size; /* argument */ + child_stack->r4 =3D (unsigned long) args->fn; + child_stack->r5 =3D (unsigned long) args->fn_arg; /* * Preserve PSR bits, except for bits 32-34 and 37-45, * which we can't read. diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index 8ac575656fc4..221feb0269f1 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -142,7 +142,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct fork_frame { struct switch_stack sw; @@ -160,12 +159,12 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) */ p->thread.fc =3D USER_DATA; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* kernel thread */ memset(frame, 0, sizeof(struct fork_frame)); frame->regs.sr =3D PS_S; - frame->sw.a3 =3D usp; /* function */ - frame->sw.d7 =3D arg; + frame->sw.a3 =3D (unsigned long)args->fn; + frame->sw.d7 =3D (unsigned long)args->fn_arg; frame->sw.retpc =3D (unsigned long)ret_from_kernel_thread; p->thread.usp =3D 0; return 0; diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/proc= ess.c index b5f549125c6a..3c6241bcaea8 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c @@ -56,19 +56,18 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); struct thread_info *ti =3D task_thread_info(p); =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* if we're creating a new kernel thread then just zeroing all * the registers. That's OK for a brand new thread.*/ memset(childregs, 0, sizeof(struct pt_regs)); memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); ti->cpu_context.r1 =3D (unsigned long)childregs; - ti->cpu_context.r20 =3D (unsigned long)usp; /* fn */ - ti->cpu_context.r19 =3D (unsigned long)arg; + ti->cpu_context.r20 =3D (unsigned long)args->fn; + ti->cpu_context.r19 =3D (unsigned long)args->fn_arg; childregs->pt_mode =3D 1; local_save_flags(childregs->msr); ti->cpu_context.msr =3D childregs->msr & ~MSR_IE; diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index a572d097b16b..35b912bce429 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -109,7 +109,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long kthread_arg =3D args->stack_size; unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct pt_regs *childregs, *regs =3D current_pt_regs(); @@ -122,12 +121,12 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) /* Put the stack after the struct pt_regs. */ childksp =3D (unsigned long) childregs; p->thread.cp0_status =3D (read_c0_status() & ~(ST0_CU2|ST0_CU1)) | ST0_KE= RNEL_CUMASK; - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* kernel thread */ unsigned long status =3D p->thread.cp0_status; memset(childregs, 0, sizeof(struct pt_regs)); - p->thread.reg16 =3D usp; /* fn */ - p->thread.reg17 =3D kthread_arg; + p->thread.reg16 =3D (unsigned long)args->fn; + p->thread.reg17 =3D (unsigned long)args->fn_arg; p->thread.reg29 =3D childksp; p->thread.reg31 =3D (unsigned long) ret_from_kernel_thread; #if defined(CONFIG_CPU_R3000) diff --git a/arch/nios2/kernel/process.c b/arch/nios2/kernel/process.c index 98c4bfe972e0..29593b98567d 100644 --- a/arch/nios2/kernel/process.c +++ b/arch/nios2/kernel/process.c @@ -104,7 +104,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); struct pt_regs *regs; @@ -112,12 +111,12 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) struct switch_stack *childstack =3D ((struct switch_stack *)childregs) - 1; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(childstack, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); =20 - childstack->r16 =3D usp; /* fn */ - childstack->r17 =3D arg; + childstack->r16 =3D (unsigned long) args->fn; + childstack->r17 =3D (unsigned long) args->fn_arg; childstack->ra =3D (unsigned long) ret_from_kernel_thread; childregs->estatus =3D STATUS_PIE; childregs->sp =3D (unsigned long) childstack; diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index 486e46dd5883..d9697cc9bc4d 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -156,7 +156,6 @@ copy_thread(struct task_struct *p, const struct kernel_= clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *userregs; struct pt_regs *kregs; @@ -175,10 +174,10 @@ copy_thread(struct task_struct *p, const struct kerne= l_clone_args *args) sp -=3D sizeof(struct pt_regs); kregs =3D (struct pt_regs *)sp; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(kregs, 0, sizeof(struct pt_regs)); - kregs->gpr[20] =3D usp; /* fn, kernel thread */ - kregs->gpr[22] =3D arg; + kregs->gpr[20] =3D (unsigned long)args->fn; + kregs->gpr[22] =3D (unsigned long)args->fn_arg; } else { *userregs =3D *current_pt_regs(); =20 diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 30a5874ca845..a6a2a558fc5b 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -210,7 +210,6 @@ copy_thread(struct task_struct *p, const struct kernel_= clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long kthread_arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *cregs =3D &(p->thread.regs); void *stack =3D task_stack_page(p); @@ -221,7 +220,7 @@ copy_thread(struct task_struct *p, const struct kernel_= clone_args *args) extern void * const ret_from_kernel_thread; extern void * const child_return; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* kernel thread */ memset(cregs, 0, sizeof(struct pt_regs)); if (args->idle) /* idle thread */ @@ -236,12 +235,12 @@ copy_thread(struct task_struct *p, const struct kerne= l_clone_args *args) * ret_from_kernel_thread. */ #ifdef CONFIG_64BIT - cregs->gr[27] =3D ((unsigned long *)usp)[3]; - cregs->gr[26] =3D ((unsigned long *)usp)[2]; + cregs->gr[27] =3D ((unsigned long *)args->fn)[3]; + cregs->gr[26] =3D ((unsigned long *)args->fn)[2]; #else - cregs->gr[26] =3D usp; + cregs->gr[26] =3D (unsigned long) args->fn; #endif - cregs->gr[25] =3D kthread_arg; + cregs->gr[25] =3D (unsigned long) args->fn_arg; } else { /* user thread */ /* usp must be word aligned. This also prevents users from diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3fd67c861d54..4f367bb68906 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1720,7 +1720,6 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long kthread_arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *childregs, *kregs; extern void ret_from_fork(void); @@ -1738,18 +1737,18 @@ int copy_thread(struct task_struct *p, const struct= kernel_clone_args *args) /* Copy registers */ sp -=3D sizeof(struct pt_regs); childregs =3D (struct pt_regs *) sp; - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* kernel thread */ memset(childregs, 0, sizeof(struct pt_regs)); childregs->gpr[1] =3D sp + sizeof(struct pt_regs); /* function */ - if (usp) - childregs->gpr[14] =3D ppc_function_entry((void *)usp); + if (args->fn) + childregs->gpr[14] =3D ppc_function_entry((void *)args->fn); #ifdef CONFIG_PPC64 clear_tsk_thread_flag(p, TIF_32BIT); childregs->softe =3D IRQS_ENABLED; #endif - childregs->gpr[15] =3D kthread_arg; + childregs->gpr[15] =3D (unsigned long)args->fn_arg; p->thread.regs =3D NULL; /* no user register state */ ti->flags |=3D _TIF_RESTOREALL; f =3D ret_from_kernel_thread; diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 334382731725..24efabdbc551 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -124,12 +124,11 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); =20 /* p->thread holds context to be restored by __switch_to() */ - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* Kernel thread */ memset(childregs, 0, sizeof(struct pt_regs)); childregs->gp =3D gp_in_global; @@ -137,8 +136,8 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) childregs->status =3D SR_PP | SR_PIE; =20 p->thread.ra =3D (unsigned long)ret_from_kernel_thread; - p->thread.s[0] =3D usp; /* fn */ - p->thread.s[1] =3D arg; + p->thread.s[0] =3D (unsigned long)args->fn; + p->thread.s[1] =3D (unsigned long)args->fn_arg; } else { *childregs =3D *(current_pt_regs()); if (usp) /* User fork */ diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index bb5daec39516..89949b9f3cf8 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -98,7 +98,6 @@ int copy_thread(struct task_struct *p, const struct kerne= l_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long new_stackp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct fake_frame { @@ -133,15 +132,15 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) frame->sf.gprs[9] =3D (unsigned long)frame; =20 /* Store access registers to kernel stack of new process. */ - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { /* kernel thread */ memset(&frame->childregs, 0, sizeof(struct pt_regs)); frame->childregs.psw.mask =3D PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; frame->childregs.psw.addr =3D (unsigned long)__ret_from_fork; - frame->childregs.gprs[9] =3D new_stackp; /* function */ - frame->childregs.gprs[10] =3D arg; + frame->childregs.gprs[9] =3D (unsigned long)args->fn; + frame->childregs.gprs[10] =3D (unsigned long)args->fn_arg; frame->childregs.orig_gpr2 =3D -1; frame->childregs.last_break =3D 1; return 0; diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 6023399b1892..a808843375e7 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -96,7 +96,6 @@ int copy_thread(struct task_struct *p, const struct kerne= l_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct pt_regs *childregs; @@ -117,11 +116,11 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) =20 childregs =3D task_pt_regs(p); p->thread.sp =3D (unsigned long) childregs; - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(childregs, 0, sizeof(struct pt_regs)); p->thread.pc =3D (unsigned long) ret_from_kernel_thread; - childregs->regs[4] =3D arg; - childregs->regs[5] =3D usp; + childregs->regs[4] =3D (unsigned long) args->fn_arg; + childregs->regs[5] =3D (unsigned long) args->fn; childregs->sr =3D SR_MD; #if defined(CONFIG_SH_FPU) childregs->sr |=3D SR_FD; diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 80e6775e18c0..33b0215a4182 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c @@ -263,7 +263,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long sp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct thread_info *ti =3D task_thread_info(p); struct pt_regs *childregs, *regs =3D current_pt_regs(); @@ -299,13 +298,13 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) ti->ksp =3D (unsigned long) new_stack; p->thread.kregs =3D childregs; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { extern int nwindows; unsigned long psr; memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ); ti->kpc =3D (((unsigned long) ret_from_kernel_thread) - 0x8); - childregs->u_regs[UREG_G1] =3D sp; /* function */ - childregs->u_regs[UREG_G2] =3D arg; + childregs->u_regs[UREG_G1] =3D (unsigned long) args->fn; + childregs->u_regs[UREG_G2] =3D (unsigned long) args->fn_arg; psr =3D childregs->psr =3D get_psr(); ti->kpsr =3D psr | PSR_PIL; ti->kwim =3D 1 << (((psr & PSR_CWP) + 1) % nwindows); diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index 38c46ca826d9..6335b698a4b4 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -568,7 +568,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long sp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct thread_info *t =3D task_thread_info(p); struct pt_regs *regs =3D current_pt_regs(); @@ -587,12 +586,12 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) sizeof(struct sparc_stackf)); t->fpsaved[0] =3D 0; =20 - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (unlikely(args->fn)) { memset(child_trap_frame, 0, child_stack_sz); __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =3D=20 (current_pt_regs()->tstate + 1) & TSTATE_CWP; - t->kregs->u_regs[UREG_G1] =3D sp; /* function */ - t->kregs->u_regs[UREG_G2] =3D arg; + t->kregs->u_regs[UREG_G1] =3D (unsigned long) args->fn; + t->kregs->u_regs[UREG_G2] =3D (unsigned long) args->fn_arg; return 0; } =20 diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index fd2d2361484d..181cc9aafb25 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -158,15 +158,13 @@ int copy_thread(struct task_struct * p, const struct = kernel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long sp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; void (*handler)(void); - int kthread =3D current->flags & (PF_KTHREAD | PF_IO_WORKER); int ret =3D 0; =20 p->thread =3D (struct thread_struct) INIT_THREAD; =20 - if (!kthread) { + if (!args->fn) { memcpy(&p->thread.regs.regs, current_pt_regs(), sizeof(p->thread.regs.regs)); PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); @@ -178,14 +176,14 @@ int copy_thread(struct task_struct * p, const struct = kernel_clone_args *args) arch_copy_thread(¤t->thread.arch, &p->thread.arch); } else { get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); - p->thread.request.u.thread.proc =3D (int (*)(void *))sp; - p->thread.request.u.thread.arg =3D (void *)arg; + p->thread.request.u.thread.proc =3D args->fn; + p->thread.request.u.thread.arg =3D args->fn_arg; handler =3D new_thread_handler; } =20 new_thread(task_stack_page(p), &p->thread.switch_buf, handler); =20 - if (!kthread) { + if (!args->fn) { clear_flushed_tls(p); =20 /* diff --git a/arch/x86/include/asm/fpu/sched.h b/arch/x86/include/asm/fpu/sc= hed.h index 99a8820e8cc4..b2486b2cbc6e 100644 --- a/arch/x86/include/asm/fpu/sched.h +++ b/arch/x86/include/asm/fpu/sched.h @@ -11,7 +11,7 @@ =20 extern void save_fpregs_to_fpstate(struct fpu *fpu); extern void fpu__drop(struct fpu *fpu); -extern int fpu_clone(struct task_struct *dst, unsigned long clone_flags); +extern int fpu_clone(struct task_struct *dst, unsigned long clone_flags, = bool minimal); extern void fpu_flush_thread(void); =20 /* diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch= _to.h index b5f0d2ff47e4..c08eb0fdd11f 100644 --- a/arch/x86/include/asm/switch_to.h +++ b/arch/x86/include/asm/switch_to.h @@ -78,13 +78,13 @@ static inline void update_task_stack(struct task_struct= *task) } =20 static inline void kthread_frame_init(struct inactive_task_frame *frame, - unsigned long fun, unsigned long arg) + int (*fun)(void *), void *arg) { - frame->bx =3D fun; + frame->bx =3D (unsigned long)fun; #ifdef CONFIG_X86_32 - frame->di =3D arg; + frame->di =3D (unsigned long)arg; #else - frame->r12 =3D arg; + frame->r12 =3D (unsigned long)arg; #endif } =20 diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index c049561f373a..fbade5a3975b 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -556,7 +556,7 @@ static inline void fpu_inherit_perms(struct fpu *dst_fp= u) } =20 /* Clone current's FPU state on fork */ -int fpu_clone(struct task_struct *dst, unsigned long clone_flags) +int fpu_clone(struct task_struct *dst, unsigned long clone_flags, bool min= imal) { struct fpu *src_fpu =3D ¤t->thread.fpu; struct fpu *dst_fpu =3D &dst->thread.fpu; @@ -579,7 +579,7 @@ int fpu_clone(struct task_struct *dst, unsigned long cl= one_flags) * No FPU state inheritance for kernel threads and IO * worker threads. */ - if (dst->flags & (PF_KTHREAD | PF_IO_WORKER)) { + if (minimal) { /* Clear out the minimal state */ memcpy(&dst_fpu->fpstate->regs, &init_fpstate.regs, init_fpstate_copy_size()); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 0fce52b10dc4..d20eaad52a85 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -134,7 +134,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long sp =3D args->stack; - unsigned long arg =3D args->stack_size; unsigned long tls =3D args->tls; struct inactive_task_frame *frame; struct fork_frame *fork_frame; @@ -172,13 +171,13 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) frame->flags =3D X86_EFLAGS_FIXED; #endif =20 - fpu_clone(p, clone_flags); + fpu_clone(p, clone_flags, args->fn); =20 /* Kernel thread ? */ if (unlikely(p->flags & PF_KTHREAD)) { p->thread.pkru =3D pkru_get_init_value(); memset(childregs, 0, sizeof(struct pt_regs)); - kthread_frame_init(frame, sp, arg); + kthread_frame_init(frame, args->fn, args->fn_arg); return 0; } =20 @@ -198,10 +197,10 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) task_user_gs(p) =3D get_user_gs(current_pt_regs()); #endif =20 - if (unlikely(p->flags & PF_IO_WORKER)) { + if (unlikely(args->fn)) { /* - * An IO thread is a user space thread, but it doesn't - * return to ret_after_fork(). + * A user space thread, but it doesn't return to + * ret_after_fork(). * * In order to indicate that to tools like gdb, * we reset the stack and instruction pointers. @@ -211,7 +210,7 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) */ childregs->sp =3D 0; childregs->ip =3D 0; - kthread_frame_init(frame, sp, arg); + kthread_frame_init(frame, args->fn, args->fn_arg); return 0; } =20 diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 15ce25073142..c3751cc88e5d 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -205,7 +205,6 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) { unsigned long clone_flags =3D args->flags; unsigned long usp_thread_fn =3D args->stack; - unsigned long thread_fn_arg =3D args->stack_size; unsigned long tls =3D args->tls; struct pt_regs *childregs =3D task_pt_regs(p); =20 @@ -226,7 +225,7 @@ int copy_thread(struct task_struct *p, const struct ker= nel_clone_args *args) #error Unsupported Xtensa ABI #endif =20 - if (!(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { + if (!args->fn) { struct pt_regs *regs =3D current_pt_regs(); unsigned long usp =3D usp_thread_fn ? usp_thread_fn : regs->areg[1]; @@ -278,15 +277,15 @@ int copy_thread(struct task_struct *p, const struct k= ernel_clone_args *args) * Window underflow will load registers from the * spill slots on the stack on return from _switch_to. */ - SPILL_SLOT(childregs, 2) =3D usp_thread_fn; - SPILL_SLOT(childregs, 3) =3D thread_fn_arg; + SPILL_SLOT(childregs, 2) =3D (unsigned long)args->fn; + SPILL_SLOT(childregs, 3) =3D (unsigned long)args->fn_arg; #elif defined(__XTENSA_CALL0_ABI__) /* * a12 =3D thread_fn, a13 =3D thread_fn arg. * _switch_to epilogue will load registers from the stack. */ - ((unsigned long *)p->thread.sp)[0] =3D usp_thread_fn; - ((unsigned long *)p->thread.sp)[1] =3D thread_fn_arg; + ((unsigned long *)p->thread.sp)[0] =3D (unsigned long)args->fn; + ((unsigned long *)p->thread.sp)[1] =3D (unsigned long)args->fn_arg; #else #error Unsupported Xtensa ABI #endif diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index 3d6b99ce5408..505aaf9fe477 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -34,6 +34,8 @@ struct kernel_clone_args { int io_thread; int kthread; int idle; + int (*fn)(void *); + void *fn_arg; struct cgroup *cgrp; struct css_set *cset; }; diff --git a/kernel/fork.c b/kernel/fork.c index 93d77ee921ff..8e17c3fbce42 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2555,8 +2555,8 @@ struct task_struct * __init fork_idle(int cpu) struct task_struct *task; struct kernel_clone_args args =3D { .flags =3D CLONE_VM, - .stack =3D (unsigned long)&idle_dummy, - .stack_size =3D (unsigned long)NULL, + .fn =3D &idle_dummy, + .fn_arg =3D NULL, .kthread =3D 1, .idle =3D 1, }; @@ -2589,8 +2589,8 @@ struct task_struct *create_io_thread(int (*fn)(void *= ), void *arg, int node) .flags =3D ((lower_32_bits(flags) | CLONE_VM | CLONE_UNTRACED) & ~CSIGNAL), .exit_signal =3D (lower_32_bits(flags) & CSIGNAL), - .stack =3D (unsigned long)fn, - .stack_size =3D (unsigned long)arg, + .fn =3D fn, + .fn_arg =3D arg, .io_thread =3D 1, }; =20 @@ -2694,8 +2694,8 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, uns= igned long flags) .flags =3D ((lower_32_bits(flags) | CLONE_VM | CLONE_UNTRACED) & ~CSIGNAL), .exit_signal =3D (lower_32_bits(flags) & CSIGNAL), - .stack =3D (unsigned long)fn, - .stack_size =3D (unsigned long)arg, + .fn =3D fn, + .fn_arg =3D arg, .kthread =3D 1, }; =20 @@ -2711,8 +2711,8 @@ pid_t user_mode_thread(int (*fn)(void *), void *arg, = unsigned long flags) .flags =3D ((lower_32_bits(flags) | CLONE_VM | CLONE_UNTRACED) & ~CSIGNAL), .exit_signal =3D (lower_32_bits(flags) & CSIGNAL), - .stack =3D (unsigned long)fn, - .stack_size =3D (unsigned long)arg, + .fn =3D fn, + .fn_arg =3D arg, }; =20 return kernel_clone(&args); --=20 2.35.3 From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E2969C433EF for ; Fri, 6 May 2022 14:16:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1442163AbiEFOTz (ORCPT ); Fri, 6 May 2022 10:19:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42892 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1442190AbiEFOTe (ORCPT ); Fri, 6 May 2022 10:19:34 -0400 X-Greylist: delayed 210 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Fri, 06 May 2022 07:15:46 PDT Received: from out02.mta.xmission.com (out02.mta.xmission.com [166.70.13.232]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A10022BC4; Fri, 6 May 2022 07:15:45 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:56272) by out02.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmykC-009n4e-Hs; Fri, 06 May 2022 08:15:44 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37210 helo=localhost.localdomain) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmykB-007Cxx-Eb; Fri, 06 May 2022 08:15:44 -0600 From: "Eric W. Biederman" To: linux-arch@vger.kernel.org Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , linux-kernel@vger.kernel.org, "Eric W. Biederman" Date: Fri, 6 May 2022 09:15:10 -0500 Message-Id: <20220506141512.516114-5-ebiederm@xmission.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> References: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-XM-SPF: eid=1nmykB-007Cxx-Eb;;;mid=<20220506141512.516114-5-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX1+YtAybj6KSom4BKXaqhR+tPpLicoHoVIw= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 5/7] init: Deal with the init process being a user mode process X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" It is silly for user_mode_thread to leave PF_KTHREAD set on the resulting task. Update the init process so that it does not care if PF_KTHREAD is set or not. Ensure do_populate_rootfs flushes all delayed fput work by calling task_work_run. In the rare instance that async_schedule_domain calls do_populate_rootfs synchronously it is possible do_populate_rootfs will be called directly from the init process. At which point fput will call "task_work_add(current, ..., TWA_RESUME)". The files on the initramfs need to be completely put before we attempt to exec them (which is before the code enters userspace). So call task_work_run just in case there are any pending fput operations. Signed-off-by: "Eric W. Biederman" --- init/initramfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/init/initramfs.c b/init/initramfs.c index 2f3d96dc3db6..41e7857d510d 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -15,6 +15,7 @@ #include #include #include +#include #include =20 static ssize_t __init xwrite(struct file *file, const char *p, size_t coun= t, @@ -703,6 +704,7 @@ static void __init do_populate_rootfs(void *unused, asy= nc_cookie_t cookie) initrd_end =3D 0; =20 flush_delayed_fput(); + task_work_run(); } =20 static ASYNC_DOMAIN_EXCLUSIVE(initramfs_domain); --=20 2.35.3 From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9A49FC433EF for ; Fri, 6 May 2022 14:16:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1442178AbiEFOTm (ORCPT ); Fri, 6 May 2022 10:19:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42934 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1442207AbiEFOTe (ORCPT ); Fri, 6 May 2022 10:19:34 -0400 Received: from out01.mta.xmission.com (out01.mta.xmission.com [166.70.13.231]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ECD566928D; Fri, 6 May 2022 07:15:47 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:56172) by out01.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmykE-007CH6-TV; Fri, 06 May 2022 08:15:46 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37210 helo=localhost.localdomain) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmykD-007Cxx-P8; Fri, 06 May 2022 08:15:46 -0600 From: "Eric W. Biederman" To: linux-arch@vger.kernel.org Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , linux-kernel@vger.kernel.org, "Eric W. Biederman" Date: Fri, 6 May 2022 09:15:11 -0500 Message-Id: <20220506141512.516114-6-ebiederm@xmission.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> References: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-XM-SPF: eid=1nmykD-007Cxx-P8;;;mid=<20220506141512.516114-6-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX1+i6APYhR/pOCN3BklB4+V7ylUJfo+qYO8= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 6/7] fork: Explicitly set PF_KTHREAD X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Instead of implicitly inheriting PF_KTHREAD from the parent process examine arguments in kernel_clone_args to see if PF_KTHREAD should be set. This makes knowledge of which new threads are kernel threads explicit. This also makes it so that init and the user mode helper processes no longer have PF_KTHREAD set. Signed-off-by: "Eric W. Biederman" --- kernel/fork.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/fork.c b/kernel/fork.c index 8e17c3fbce42..35645f57bd2f 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2068,6 +2068,9 @@ static __latent_entropy struct task_struct *copy_proc= ess( p =3D dup_task_struct(current, node); if (!p) goto fork_out; + p->flags &=3D ~PF_KTHREAD; + if (args->kthread) + p->flags |=3D PF_KTHREAD; if (args->io_thread) { /* * Mark us an IO worker, and block any signal that isn't --=20 2.35.3 From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DBE7DC433F5 for ; Fri, 6 May 2022 14:16:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1442046AbiEFOTt (ORCPT ); Fri, 6 May 2022 10:19:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43076 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1442213AbiEFOTf (ORCPT ); Fri, 6 May 2022 10:19:35 -0400 Received: from out01.mta.xmission.com (out01.mta.xmission.com [166.70.13.231]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 923086929A; Fri, 6 May 2022 07:15:50 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:56240) by out01.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmykH-007CHd-A4; Fri, 06 May 2022 08:15:49 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37210 helo=localhost.localdomain) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1nmykG-007Cxx-5y; Fri, 06 May 2022 08:15:48 -0600 From: "Eric W. Biederman" To: linux-arch@vger.kernel.org Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , linux-kernel@vger.kernel.org, "Eric W. Biederman" Date: Fri, 6 May 2022 09:15:12 -0500 Message-Id: <20220506141512.516114-7-ebiederm@xmission.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> References: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-XM-SPF: eid=1nmykG-007Cxx-5y;;;mid=<20220506141512.516114-7-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX19K/oVZiCW2l9YdNNLzHZzyn9V7eD5myBs= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 7/7] fork: Stop allowing kthreads to call execve X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Now that kernel_execve is no longer called from kernel threads stop supporting kernel threads calling kernel_execve. Remove the code for converting a kthread to a normal thread in execve. Document the restriction that kthreads may not call kernel_execve by having kernel_execve fail if called by a kthread. Signed-off-by: "Eric W. Biederman" --- fs/exec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 75eb6e0ee7b2..9c5260e74517 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1308,7 +1308,7 @@ int begin_new_exec(struct linux_binprm * bprm) if (retval) goto out_unlock; =20 - me->flags &=3D ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | + me->flags &=3D ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_NOFREEZE | PF_NO_SETAFFINITY); flush_thread(); me->personality &=3D ~bprm->per_clear; @@ -1953,8 +1953,8 @@ int kernel_execve(const char *kernel_filename, int fd =3D AT_FDCWD; int retval; =20 - if (WARN_ON_ONCE((current->flags & PF_KTHREAD) && - (current->worker_private))) + /* It is non-sense for kernel threads to call execve */ + if (WARN_ON_ONCE(current->flags & PF_KTHREAD)) return -EINVAL; =20 filename =3D getname_kernel(kernel_filename); --=20 2.35.3 From nobody Mon Jun 15 02:41:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0AFC2C433EF for ; Wed, 11 May 2022 17:37:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345677AbiEKRhr (ORCPT ); Wed, 11 May 2022 13:37:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38242 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234039AbiEKRhl (ORCPT ); Wed, 11 May 2022 13:37:41 -0400 Received: from out02.mta.xmission.com (out02.mta.xmission.com [166.70.13.232]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 99FAD692AC; Wed, 11 May 2022 10:37:40 -0700 (PDT) Received: from in01.mta.xmission.com ([166.70.13.51]:58578) by out02.mta.xmission.com with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1noqHJ-006mps-BT; Wed, 11 May 2022 11:37:37 -0600 Received: from ip68-227-174-4.om.om.cox.net ([68.227.174.4]:37816 helo=email.froward.int.ebiederm.org.xmission.com) by in01.mta.xmission.com with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.93) (envelope-from ) id 1noqHH-001c0M-Bx; Wed, 11 May 2022 11:37:36 -0600 From: "Eric W. Biederman" To: Cc: Tejun Heo , Peter Zijlstra , Vincent Guittot , Al Viro , Jens Axboe , Thomas Gleixner , Linus Torvalds , References: <87a6czifo7.fsf@email.froward.int.ebiederm.org> <87ilrn1drx.ffs@tglx> <877d7zk1cf.ffs@tglx> <87y20fid4d.ffs@tglx> <87bkx5q3pk.fsf_-_@email.froward.int.ebiederm.org> <87mtfu4up3.fsf@email.froward.int.ebiederm.org> Date: Wed, 11 May 2022 12:37:10 -0500 In-Reply-To: <87mtfu4up3.fsf@email.froward.int.ebiederm.org> (Eric W. Biederman's message of "Fri, 06 May 2022 09:11:36 -0500") Message-ID: <87r150ug1l.fsf_-_@email.froward.int.ebiederm.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 X-XM-SPF: eid=1noqHH-001c0M-Bx;;;mid=<87r150ug1l.fsf_-_@email.froward.int.ebiederm.org>;;;hst=in01.mta.xmission.com;;;ip=68.227.174.4;;;frm=ebiederm@xmission.com;;;spf=softfail X-XM-AID: U2FsdGVkX19mmGlUvgKMqbZ/amgfpc+1CZO+CoJffcI= X-SA-Exim-Connect-IP: 68.227.174.4 X-SA-Exim-Mail-From: ebiederm@xmission.com Subject: [PATCH 8/7] sched: Update task_tick_numa to ignore tasks without an mm X-SA-Exim-Version: 4.2.1 (built Sat, 08 Feb 2020 21:53:50 +0000) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Qian Cai wrote: > Reverting the last 3 commits of the series fixed a boot crash. > > 1b2552cbdbe0 fork: Stop allowing kthreads to call execve > 753550eb0ce1 fork: Explicitly set PF_KTHREAD > 68d85f0a33b0 init: Deal with the init process being a user mode process > > BUG: KASAN: null-ptr-deref in task_nr_scan_windows.isra.0 > arch_atomic_long_read at ./include/linux/atomic/atomic-long.h:29 > (inlined by) atomic_long_read at ./include/linux/atomic/atomic-instrumen= ted.h:1266 > (inlined by) get_mm_counter at ./include/linux/mm.h:1996 > (inlined by) get_mm_rss at ./include/linux/mm.h:2049 > (inlined by) task_nr_scan_windows at kernel/sched/fair.c:1123 > Read of size 8 at addr 00000000000003d0 by task swapper/0/1 With the change to init and the user mode helper processes to not have PF_KTHREAD set before they call kernel_execve the PF_KTHREAD test in task_tick_numa became insufficient to detect all tasks that have "->mm =3D=3D NULL". Correct that by testing for "->mm =3D=3D NULL" directl= y. Reported-by: Qian Cai Tested-by: Qian Cai Fixes: 1b2552cbdbe0 ("fork: Stop allowing kthreads to call execve") Signed-off-by: "Eric W. Biederman" --- kernel/sched/fair.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d4bd299d67ab..db6f0df9d43e 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2915,7 +2915,7 @@ static void task_tick_numa(struct rq *rq, struct task= _struct *curr) /* * We don't care about NUMA placement if we don't have memory. */ - if ((curr->flags & (PF_EXITING | PF_KTHREAD)) || work->next !=3D work) + if (!curr->mm || (curr->flags & (PF_EXITING | PF_KTHREAD)) || work->next = !=3D work) return; =20 /* --=20 2.35.3