mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
Merge tag 'kthread-cleanups-for-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull kthread updates from Eric Biederman: "This updates init and user mode helper tasks to be ordinary user mode tasks. Commit40966e316f
("kthread: Ensure struct kthread is present for all kthreads") caused init and the user mode helper threads that call kernel_execve to have struct kthread allocated for them. This struct kthread going away during execve in turned made a use after free of struct kthread possible. Here, commit343f4c49f2
("kthread: Don't allocate kthread_struct for init and umh") is enough to fix the use after free and is simple enough to be backportable. The rest of the changes pass struct kernel_clone_args to clean things up and cause the code to make sense. In making init and the user mode helpers tasks purely user mode tasks I ran into two complications. The function task_tick_numa was detecting tasks without an mm by testing for the presence of PF_KTHREAD. The initramfs code in populate_initrd_image was using flush_delayed_fput to ensuere the closing of all it's file descriptors was complete, and flush_delayed_fput does not work in a userspace thread. I have looked and looked and more complications and in my code review I have not found any, and neither has anyone else with the code sitting in linux-next" * tag 'kthread-cleanups-for-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: sched: Update task_tick_numa to ignore tasks without an mm fork: Stop allowing kthreads to call execve fork: Explicitly set PF_KTHREAD init: Deal with the init process being a user mode process fork: Generalize PF_IO_WORKER handling fork: Explicity test for idle tasks in copy_thread fork: Pass struct kernel_clone_args into copy_thread kthread: Don't allocate kthread_struct for init and umh
This commit is contained in:
@@ -1982,7 +1982,7 @@ static __latent_entropy struct task_struct *copy_process(
|
||||
struct task_struct *p;
|
||||
struct multiprocess_signals delayed;
|
||||
struct file *pidfile = NULL;
|
||||
u64 clone_flags = args->flags;
|
||||
const u64 clone_flags = args->flags;
|
||||
struct nsproxy *nsp = current->nsproxy;
|
||||
|
||||
/*
|
||||
@@ -2071,6 +2071,9 @@ static __latent_entropy struct task_struct *copy_process(
|
||||
p = dup_task_struct(current, node);
|
||||
if (!p)
|
||||
goto fork_out;
|
||||
p->flags &= ~PF_KTHREAD;
|
||||
if (args->kthread)
|
||||
p->flags |= PF_KTHREAD;
|
||||
if (args->io_thread) {
|
||||
/*
|
||||
* Mark us an IO worker, and block any signal that isn't
|
||||
@@ -2160,7 +2163,7 @@ static __latent_entropy struct task_struct *copy_process(
|
||||
p->io_context = 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;
|
||||
}
|
||||
@@ -2243,7 +2246,7 @@ static __latent_entropy struct task_struct *copy_process(
|
||||
retval = copy_io(clone_flags, p);
|
||||
if (retval)
|
||||
goto bad_fork_cleanup_namespaces;
|
||||
retval = copy_thread(clone_flags, args->stack, args->stack_size, p, args->tls);
|
||||
retval = copy_thread(p, args);
|
||||
if (retval)
|
||||
goto bad_fork_cleanup_io;
|
||||
|
||||
@@ -2547,11 +2550,21 @@ static inline void init_idle_pids(struct task_struct *idle)
|
||||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
.flags = CLONE_VM,
|
||||
.flags = CLONE_VM,
|
||||
.fn = &idle_dummy,
|
||||
.fn_arg = NULL,
|
||||
.kthread = 1,
|
||||
.idle = 1,
|
||||
};
|
||||
|
||||
task = copy_process(&init_struct_pid, 0, cpu_to_node(cpu), &args);
|
||||
@@ -2582,8 +2595,8 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
|
||||
.flags = ((lower_32_bits(flags) | CLONE_VM |
|
||||
CLONE_UNTRACED) & ~CSIGNAL),
|
||||
.exit_signal = (lower_32_bits(flags) & CSIGNAL),
|
||||
.stack = (unsigned long)fn,
|
||||
.stack_size = (unsigned long)arg,
|
||||
.fn = fn,
|
||||
.fn_arg = arg,
|
||||
.io_thread = 1,
|
||||
};
|
||||
|
||||
@@ -2687,8 +2700,25 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
|
||||
.flags = ((lower_32_bits(flags) | CLONE_VM |
|
||||
CLONE_UNTRACED) & ~CSIGNAL),
|
||||
.exit_signal = (lower_32_bits(flags) & CSIGNAL),
|
||||
.stack = (unsigned long)fn,
|
||||
.stack_size = (unsigned long)arg,
|
||||
.fn = fn,
|
||||
.fn_arg = arg,
|
||||
.kthread = 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 = {
|
||||
.flags = ((lower_32_bits(flags) | CLONE_VM |
|
||||
CLONE_UNTRACED) & ~CSIGNAL),
|
||||
.exit_signal = (lower_32_bits(flags) & CSIGNAL),
|
||||
.fn = fn,
|
||||
.fn_arg = arg,
|
||||
};
|
||||
|
||||
return kernel_clone(&args);
|
||||
|
Reference in New Issue
Block a user