linux(4): Add struct clone_args for future clone3 system call.
In preparation for clone3 system call add struct clone_args and use it in clone implementation. Move all of clone related bits to the newly created linux_fork.h header. Differential revision: https://reviews.freebsd.org/D31474 MFC after: 2 weeks
This commit is contained in:
parent
0c08f34f4d
commit
0a4b664ae8
@ -88,6 +88,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <amd64/linux/linux_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_file.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_ipc.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_mmap.h>
|
||||
|
@ -77,6 +77,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <amd64/linux/linux.h>
|
||||
#include <amd64/linux/linux_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_ioctl.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
|
@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <amd64/linux32/linux.h>
|
||||
#include <amd64/linux32/linux32_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_ipc.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_mmap.h>
|
||||
|
@ -83,6 +83,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <amd64/linux32/linux.h>
|
||||
#include <amd64/linux32/linux32_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_ioctl.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
|
@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <arm64/linux/linux_proto.h>
|
||||
#include <compat/linux/linux_dtrace.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_mmap.h>
|
||||
#include <compat/linux/linux_util.h>
|
||||
|
@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <arm64/linux/linux_proto.h>
|
||||
#include <compat/linux/linux_dtrace.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_ioctl.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
|
@ -265,4 +265,6 @@ struct l_statx {
|
||||
uint64_t __spare2[13];
|
||||
};
|
||||
|
||||
#define lower_32_bits(n) ((uint32_t)((n) & 0xffffffff))
|
||||
|
||||
#endif /* _LINUX_MI_H_ */
|
||||
|
@ -139,7 +139,7 @@ linux_set_default_stacksize(struct thread *td, struct proc *p)
|
||||
}
|
||||
|
||||
void
|
||||
linux_proc_init(struct thread *td, struct thread *newtd, int flags)
|
||||
linux_proc_init(struct thread *td, struct thread *newtd, bool init_thread)
|
||||
{
|
||||
struct linux_emuldata *em;
|
||||
struct linux_pemuldata *pem;
|
||||
@ -150,7 +150,7 @@ linux_proc_init(struct thread *td, struct thread *newtd, int flags)
|
||||
|
||||
/* non-exec call */
|
||||
em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO);
|
||||
if (flags & LINUX_CLONE_THREAD) {
|
||||
if (init_thread) {
|
||||
LINUX_CTR1(proc_init, "thread newtd(%d)",
|
||||
newtd->td_tid);
|
||||
|
||||
@ -312,12 +312,12 @@ linux_on_exec(struct proc *p, struct image_params *imgp)
|
||||
* before exec. Update emuldata to reflect
|
||||
* single-threaded cleaned state after exec.
|
||||
*/
|
||||
linux_proc_init(td, NULL, 0);
|
||||
linux_proc_init(td, NULL, false);
|
||||
} else {
|
||||
/*
|
||||
* We are switching the process to Linux emulator.
|
||||
*/
|
||||
linux_proc_init(td, td, 0);
|
||||
linux_proc_init(td, td, false);
|
||||
|
||||
/*
|
||||
* Create a transient td_emuldata for all suspended
|
||||
@ -328,7 +328,7 @@ linux_on_exec(struct proc *p, struct image_params *imgp)
|
||||
FOREACH_THREAD_IN_PROC(td->td_proc, othertd) {
|
||||
if (othertd == td)
|
||||
continue;
|
||||
linux_proc_init(td, othertd, LINUX_CLONE_THREAD);
|
||||
linux_proc_init(td, othertd, true);
|
||||
}
|
||||
}
|
||||
#if defined(__amd64__)
|
||||
|
@ -55,12 +55,11 @@ struct linux_emuldata {
|
||||
struct linux_emuldata *em_find(struct thread *);
|
||||
|
||||
int linux_exec_imgact_try(struct image_params *);
|
||||
void linux_proc_init(struct thread *, struct thread *, int);
|
||||
void linux_proc_init(struct thread *, struct thread *, bool);
|
||||
void linux_on_exit(struct proc *);
|
||||
void linux_schedtail(struct thread *);
|
||||
void linux_on_exec(struct proc *, struct image_params *);
|
||||
void linux_thread_dtor(struct thread *);
|
||||
void linux_thread_detach(struct thread *);
|
||||
int linux_common_execve(struct thread *, struct image_args *);
|
||||
void linux32_prepare_notes(struct thread *, struct note_info_list *, size_t *);
|
||||
void linux64_prepare_notes(struct thread *, struct note_info_list *, size_t *);
|
||||
|
@ -60,7 +60,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/../linux/linux.h>
|
||||
#include <machine/../linux/linux_proto.h>
|
||||
#endif
|
||||
#include <compat/linux/linux.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_futex.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_util.h>
|
||||
@ -82,7 +84,7 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
|
||||
|
||||
td2 = FIRST_THREAD_IN_PROC(p2);
|
||||
|
||||
linux_proc_init(td, td2, 0);
|
||||
linux_proc_init(td, td2, false);
|
||||
|
||||
td->td_retval[0] = p2->p_pid;
|
||||
|
||||
@ -112,7 +114,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
|
||||
|
||||
td2 = FIRST_THREAD_IN_PROC(p2);
|
||||
|
||||
linux_proc_init(td, td2, 0);
|
||||
linux_proc_init(td, td2, false);
|
||||
|
||||
td->td_retval[0] = p2->p_pid;
|
||||
|
||||
@ -128,7 +130,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
|
||||
#endif
|
||||
|
||||
static int
|
||||
linux_clone_proc(struct thread *td, struct linux_clone_args *args)
|
||||
linux_clone_proc(struct thread *td, struct l_clone_args *args)
|
||||
{
|
||||
struct fork_req fr;
|
||||
int error, ff = RFPROC | RFSTOPPED, f2;
|
||||
@ -138,11 +140,12 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
|
||||
struct linux_emuldata *em;
|
||||
|
||||
f2 = 0;
|
||||
exit_signal = args->flags & 0x000000ff;
|
||||
if (LINUX_SIG_VALID(exit_signal)) {
|
||||
exit_signal = linux_to_bsd_signal(exit_signal);
|
||||
} else if (exit_signal != 0)
|
||||
if (LINUX_SIG_VALID(args->exit_signal)) {
|
||||
exit_signal = linux_to_bsd_signal(args->exit_signal);
|
||||
} else if (args->exit_signal != 0)
|
||||
return (EINVAL);
|
||||
else
|
||||
exit_signal = 0;
|
||||
|
||||
if (args->flags & LINUX_CLONE_VM)
|
||||
ff |= RFMEM;
|
||||
@ -158,7 +161,7 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
|
||||
}
|
||||
|
||||
if (args->flags & LINUX_CLONE_PARENT_SETTID)
|
||||
if (args->parent_tidptr == NULL)
|
||||
if (args->parent_tid == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
if (args->flags & LINUX_CLONE_VFORK)
|
||||
@ -175,23 +178,23 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
|
||||
td2 = FIRST_THREAD_IN_PROC(p2);
|
||||
|
||||
/* create the emuldata */
|
||||
linux_proc_init(td, td2, args->flags);
|
||||
linux_proc_init(td, td2, false);
|
||||
|
||||
em = em_find(td2);
|
||||
KASSERT(em != NULL, ("clone_proc: emuldata not found.\n"));
|
||||
|
||||
if (args->flags & LINUX_CLONE_CHILD_SETTID)
|
||||
em->child_set_tid = args->child_tidptr;
|
||||
em->child_set_tid = args->child_tid;
|
||||
else
|
||||
em->child_set_tid = NULL;
|
||||
|
||||
if (args->flags & LINUX_CLONE_CHILD_CLEARTID)
|
||||
em->child_clear_tid = args->child_tidptr;
|
||||
em->child_clear_tid = args->child_tid;
|
||||
else
|
||||
em->child_clear_tid = NULL;
|
||||
|
||||
if (args->flags & LINUX_CLONE_PARENT_SETTID) {
|
||||
error = copyout(&p2->p_pid, args->parent_tidptr,
|
||||
error = copyout(&p2->p_pid, args->parent_tid,
|
||||
sizeof(p2->p_pid));
|
||||
if (error)
|
||||
linux_msg(td, "copyout p_pid failed!");
|
||||
@ -235,7 +238,7 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
|
||||
}
|
||||
|
||||
static int
|
||||
linux_clone_thread(struct thread *td, struct linux_clone_args *args)
|
||||
linux_clone_thread(struct thread *td, struct l_clone_args *args)
|
||||
{
|
||||
struct linux_emuldata *em;
|
||||
struct thread *newtd;
|
||||
@ -244,12 +247,12 @@ linux_clone_thread(struct thread *td, struct linux_clone_args *args)
|
||||
|
||||
LINUX_CTR4(clone_thread, "thread(%d) flags %x ptid %p ctid %p",
|
||||
td->td_tid, (unsigned)args->flags,
|
||||
args->parent_tidptr, args->child_tidptr);
|
||||
args->parent_tid, args->child_tid);
|
||||
|
||||
if ((args->flags & LINUX_CLONE_PARENT) != 0)
|
||||
return (EINVAL);
|
||||
if (args->flags & LINUX_CLONE_PARENT_SETTID)
|
||||
if (args->parent_tidptr == NULL)
|
||||
if (args->parent_tid == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/* Threads should be created with own stack */
|
||||
@ -284,7 +287,7 @@ linux_clone_thread(struct thread *td, struct linux_clone_args *args)
|
||||
thread_cow_get(newtd, td);
|
||||
|
||||
/* create the emuldata */
|
||||
linux_proc_init(td, newtd, args->flags);
|
||||
linux_proc_init(td, newtd, true);
|
||||
|
||||
em = em_find(newtd);
|
||||
KASSERT(em != NULL, ("clone_thread: emuldata not found.\n"));
|
||||
@ -293,12 +296,12 @@ linux_clone_thread(struct thread *td, struct linux_clone_args *args)
|
||||
linux_set_cloned_tls(newtd, PTRIN(args->tls));
|
||||
|
||||
if (args->flags & LINUX_CLONE_CHILD_SETTID)
|
||||
em->child_set_tid = args->child_tidptr;
|
||||
em->child_set_tid = args->child_tid;
|
||||
else
|
||||
em->child_set_tid = NULL;
|
||||
|
||||
if (args->flags & LINUX_CLONE_CHILD_CLEARTID)
|
||||
em->child_clear_tid = args->child_tidptr;
|
||||
em->child_clear_tid = args->child_tid;
|
||||
else
|
||||
em->child_clear_tid = NULL;
|
||||
|
||||
@ -328,7 +331,7 @@ linux_clone_thread(struct thread *td, struct linux_clone_args *args)
|
||||
td->td_tid, newtd->td_tid);
|
||||
|
||||
if (args->flags & LINUX_CLONE_PARENT_SETTID) {
|
||||
error = copyout(&newtd->td_tid, args->parent_tidptr,
|
||||
error = copyout(&newtd->td_tid, args->parent_tid,
|
||||
sizeof(newtd->td_tid));
|
||||
if (error)
|
||||
linux_msg(td, "clone_thread: copyout td_tid failed!");
|
||||
@ -359,11 +362,19 @@ linux_clone_thread(struct thread *td, struct linux_clone_args *args)
|
||||
int
|
||||
linux_clone(struct thread *td, struct linux_clone_args *args)
|
||||
{
|
||||
struct l_clone_args ca = {
|
||||
.flags = (lower_32_bits(args->flags) & ~LINUX_CSIGNAL),
|
||||
.child_tid = args->child_tidptr,
|
||||
.parent_tid = args->parent_tidptr,
|
||||
.exit_signal = (lower_32_bits(args->flags) & LINUX_CSIGNAL),
|
||||
.stack = args->stack,
|
||||
.tls = args->tls,
|
||||
};
|
||||
|
||||
if (args->flags & LINUX_CLONE_THREAD)
|
||||
return (linux_clone_thread(td, args));
|
||||
return (linux_clone_thread(td, &ca));
|
||||
else
|
||||
return (linux_clone_proc(td, args));
|
||||
return (linux_clone_proc(td, &ca));
|
||||
}
|
||||
|
||||
int
|
||||
|
92
sys/compat/linux/linux_fork.h
Normal file
92
sys/compat/linux/linux_fork.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (c) 2021 Dmitry Chagin <dchagin@FreeBSD.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_FORK_H_
|
||||
#define _LINUX_FORK_H_
|
||||
|
||||
#define LINUX_CLONE_VM 0x00000100
|
||||
#define LINUX_CLONE_FS 0x00000200
|
||||
#define LINUX_CLONE_FILES 0x00000400
|
||||
#define LINUX_CLONE_SIGHAND 0x00000800
|
||||
#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
|
||||
#define LINUX_CLONE_PTRACE 0x00002000
|
||||
#define LINUX_CLONE_VFORK 0x00004000
|
||||
#define LINUX_CLONE_PARENT 0x00008000
|
||||
#define LINUX_CLONE_THREAD 0x00010000
|
||||
#define LINUX_CLONE_NEWNS 0x00020000 /* New mount NS */
|
||||
#define LINUX_CLONE_SYSVSEM 0x00040000
|
||||
#define LINUX_CLONE_SETTLS 0x00080000
|
||||
#define LINUX_CLONE_PARENT_SETTID 0x00100000
|
||||
#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
|
||||
#define LINUX_CLONE_DETACHED 0x00400000 /* Unused */
|
||||
#define LINUX_CLONE_UNTRACED 0x00800000
|
||||
#define LINUX_CLONE_CHILD_SETTID 0x01000000
|
||||
#define LINUX_CLONE_NEWCGROUP 0x02000000 /* New cgroup NS */
|
||||
#define LINUX_CLONE_NEWUTS 0x04000000
|
||||
#define LINUX_CLONE_NEWIPC 0x08000000
|
||||
#define LINUX_CLONE_NEWUSER 0x10000000
|
||||
#define LINUX_CLONE_NEWPID 0x20000000
|
||||
#define LINUX_CLONE_NEWNET 0x40000000
|
||||
#define LINUX_CLONE_IO 0x80000000
|
||||
|
||||
#define LINUX_CSIGNAL 0x000000ff
|
||||
|
||||
/*
|
||||
* User-space clone3 args layout.
|
||||
*/
|
||||
struct l_user_clone_args {
|
||||
uint64_t flags;
|
||||
uint64_t pidfd;
|
||||
uint64_t child_tid;
|
||||
uint64_t parent_tid;
|
||||
uint64_t exit_signal;
|
||||
uint64_t stack;
|
||||
uint64_t stack_size;
|
||||
uint64_t tls;
|
||||
uint64_t set_tid;
|
||||
uint64_t set_tid_size;
|
||||
uint64_t cgroup;
|
||||
};
|
||||
|
||||
/*
|
||||
* Kernel clone3 args layout.
|
||||
*/
|
||||
struct l_clone_args {
|
||||
uint64_t flags;
|
||||
l_int *child_tid;
|
||||
l_int *parent_tid;
|
||||
l_int exit_signal;
|
||||
l_ulong stack;
|
||||
l_ulong stack_size;
|
||||
l_ulong tls;
|
||||
};
|
||||
|
||||
int linux_set_upcall(struct thread *, register_t);
|
||||
int linux_set_cloned_tls(struct thread *, void *);
|
||||
void linux_thread_detach(struct thread *);
|
||||
|
||||
#endif /* _LINUX_FORK_H_ */
|
@ -98,31 +98,6 @@
|
||||
#define __LINUX_NPXCW__ 0x37f
|
||||
#endif
|
||||
|
||||
#define LINUX_CLONE_VM 0x00000100
|
||||
#define LINUX_CLONE_FS 0x00000200
|
||||
#define LINUX_CLONE_FILES 0x00000400
|
||||
#define LINUX_CLONE_SIGHAND 0x00000800
|
||||
#define LINUX_CLONE_PID 0x00001000 /* No longer exist in Linux */
|
||||
#define LINUX_CLONE_PTRACE 0x00002000
|
||||
#define LINUX_CLONE_VFORK 0x00004000
|
||||
#define LINUX_CLONE_PARENT 0x00008000
|
||||
#define LINUX_CLONE_THREAD 0x00010000
|
||||
#define LINUX_CLONE_NEWNS 0x00020000 /* New mount NS */
|
||||
#define LINUX_CLONE_SYSVSEM 0x00040000
|
||||
#define LINUX_CLONE_SETTLS 0x00080000
|
||||
#define LINUX_CLONE_PARENT_SETTID 0x00100000
|
||||
#define LINUX_CLONE_CHILD_CLEARTID 0x00200000
|
||||
#define LINUX_CLONE_DETACHED 0x00400000 /* Unused */
|
||||
#define LINUX_CLONE_UNTRACED 0x00800000
|
||||
#define LINUX_CLONE_CHILD_SETTID 0x01000000
|
||||
#define LINUX_CLONE_NEWCGROUP 0x02000000 /* New cgroup NS */
|
||||
#define LINUX_CLONE_NEWUTS 0x04000000
|
||||
#define LINUX_CLONE_NEWIPC 0x08000000
|
||||
#define LINUX_CLONE_NEWUSER 0x10000000
|
||||
#define LINUX_CLONE_NEWPID 0x20000000
|
||||
#define LINUX_CLONE_NEWNET 0x40000000
|
||||
#define LINUX_CLONE_IO 0x80000000
|
||||
|
||||
/* Scheduling policies */
|
||||
#define LINUX_SCHED_OTHER 0
|
||||
#define LINUX_SCHED_FIFO 1
|
||||
@ -180,8 +155,6 @@ extern int stclohz;
|
||||
int linux_ptrace_status(struct thread *td, int pid, int status);
|
||||
#endif
|
||||
void linux_to_bsd_waitopts(int options, int *bsdopts);
|
||||
int linux_set_upcall(struct thread *td, register_t stack);
|
||||
int linux_set_cloned_tls(struct thread *td, void *desc);
|
||||
struct thread *linux_tdfind(struct thread *, lwpid_t, pid_t);
|
||||
|
||||
#endif /* _LINUX_MISC_H_ */
|
||||
|
@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <i386/linux/linux.h>
|
||||
#include <i386/linux/linux_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_ipc.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_mmap.h>
|
||||
|
@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <i386/linux/linux.h>
|
||||
#include <i386/linux/linux_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_fork.h>
|
||||
#include <compat/linux/linux_ioctl.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
|
Loading…
Reference in New Issue
Block a user