Page MenuHomeFreeBSD

D31475.diff
No OneTemporary

D31475.diff

diff --git a/sys/amd64/linux/syscalls.master b/sys/amd64/linux/syscalls.master
--- a/sys/amd64/linux/syscalls.master
+++ b/sys/amd64/linux/syscalls.master
@@ -2082,7 +2082,10 @@
int linux_pidfd_open(void);
}
435 AUE_NULL STD {
- int linux_clone3(void);
+ int linux_clone3(
+ struct l_user_clone_args *uargs,
+ l_size_t usize
+ );
}
436 AUE_NULL STD {
int linux_close_range(void);
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -2484,7 +2484,10 @@
int linux_pidfd_open(void);
}
435 AUE_NULL STD {
- int linux_clone3(void);
+ int linux_clone3(
+ struct l_user_clone_args *uargs,
+ l_size_t usize
+ );
}
436 AUE_NULL STD {
int linux_close_range(void);
diff --git a/sys/arm64/linux/syscalls.master b/sys/arm64/linux/syscalls.master
--- a/sys/arm64/linux/syscalls.master
+++ b/sys/arm64/linux/syscalls.master
@@ -1731,7 +1731,10 @@
int linux_pidfd_open(void);
}
435 AUE_NULL STD {
- int linux_clone3(void);
+ int linux_clone3(
+ struct l_user_clone_args *uargs,
+ l_size_t usize
+ );
}
436 AUE_NULL STD {
int linux_close_range(void);
diff --git a/sys/compat/linux/linux_fork.h b/sys/compat/linux/linux_fork.h
--- a/sys/compat/linux/linux_fork.h
+++ b/sys/compat/linux/linux_fork.h
@@ -53,6 +53,13 @@
#define LINUX_CLONE_NEWNET 0x40000000
#define LINUX_CLONE_IO 0x80000000
+/* Flags for the clone3() syscall. */
+#define LINUX_CLONE_CLEAR_SIGHAND 0x100000000ULL
+#define LINUX_CLONE_INTO_CGROUP 0x200000000ULL
+#define LINUX_CLONE_NEWTIME 0x00000080
+
+#define LINUX_CLONE_LEGACY_FLAGS 0xffffffffULL
+
#define LINUX_CSIGNAL 0x000000ff
/*
@@ -85,6 +92,8 @@
l_ulong tls;
};
+#define LINUX_CLONE_ARGS_SIZE_VER0 64
+
int linux_set_upcall(struct thread *, register_t);
int linux_set_cloned_tls(struct thread *, void *);
void linux_thread_detach(struct thread *);
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -377,6 +377,86 @@
return (linux_clone_proc(td, &ca));
}
+
+static int
+linux_clone3_args_valid(struct l_user_clone_args *uca)
+{
+
+ /* Verify that no unknown flags are passed along. */
+ if ((uca->flags & ~(LINUX_CLONE_LEGACY_FLAGS |
+ LINUX_CLONE_CLEAR_SIGHAND | LINUX_CLONE_INTO_CGROUP)) != 0)
+ return (EINVAL);
+ if ((uca->flags & (LINUX_CLONE_DETACHED | LINUX_CSIGNAL)) != 0)
+ return (EINVAL);
+
+ if ((uca->flags & (LINUX_CLONE_SIGHAND | LINUX_CLONE_CLEAR_SIGHAND)) ==
+ (LINUX_CLONE_SIGHAND | LINUX_CLONE_CLEAR_SIGHAND))
+ return (EINVAL);
+ if ((uca->flags & (LINUX_CLONE_THREAD | LINUX_CLONE_PARENT)) != 0 &&
+ uca->exit_signal != 0)
+ return (EINVAL);
+
+ /* We don't support set_tid, only validate input. */
+ if (uca->set_tid_size > LINUX_MAX_PID_NS_LEVEL)
+ return (EINVAL);
+ if (uca->set_tid == 0 && uca->set_tid_size > 0)
+ return (EINVAL);
+ if (uca->set_tid != 0 && uca->set_tid_size == 0)
+ return (EINVAL);
+
+ if (uca->stack == 0 && uca->stack_size > 0)
+ return (EINVAL);
+ if (uca->stack != 0 && uca->stack_size == 0)
+ return (EINVAL);
+
+ return (0);
+}
+
+int
+linux_clone3(struct thread *td, struct linux_clone3_args *args)
+{
+ struct l_user_clone_args *uca;
+ struct l_clone_args *ca;
+ size_t size;
+ int error;
+
+ if (args->usize > PAGE_SIZE)
+ return (E2BIG);
+ if (args->usize < LINUX_CLONE_ARGS_SIZE_VER0)
+ return (EINVAL);
+
+ /*
+ * usize can be less than size of struct clone_args, to avoid using
+ * of uninitialized data of struct clone_args, allocate at least
+ * sizeof(struct clone_args) storage and zero it.
+ */
+ size = max(args->usize, sizeof(*uca));
+ uca = malloc(size, M_LINUX, M_WAITOK | M_ZERO);
+ error = copyin(args->uargs, uca, args->usize);
+ if (error != 0)
+ goto out;
+ error = linux_clone3_args_valid(uca);
+ if (error != 0)
+ goto out;
+ ca = malloc(sizeof(*ca), M_LINUX, M_WAITOK | M_ZERO);
+ ca->flags = uca->flags;
+ ca->child_tid = PTRIN(uca->child_tid);
+ ca->parent_tid = PTRIN(uca->parent_tid);
+ ca->exit_signal = uca->exit_signal;
+ ca->stack = uca->stack + uca->stack_size;
+ ca->stack_size = uca->stack_size;
+ ca->tls = uca->tls;
+
+ if ((ca->flags & LINUX_CLONE_THREAD) != 0)
+ error = linux_clone_thread(td, ca);
+ else
+ error = linux_clone_proc(td, ca);
+ free(ca, M_LINUX);
+out:
+ free(uca, M_LINUX);
+ return (error);
+}
+
int
linux_exit(struct thread *td, struct linux_exit_args *args)
{
diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h
--- a/sys/compat/linux/linux_misc.h
+++ b/sys/compat/linux/linux_misc.h
@@ -33,6 +33,8 @@
#include <sys/sysctl.h>
+#define LINUX_MAX_PID_NS_LEVEL 32
+
/* bits per mask */
#define LINUX_NFDBITS sizeof(l_fd_mask) * 8
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -2502,7 +2502,10 @@
int linux_pidfd_open(void);
}
435 AUE_NULL STD {
- int linux_clone3(void);
+ int linux_clone3(
+ struct l_user_clone_args *uargs,
+ l_size_t usize
+ );
}
436 AUE_NULL STD {
int linux_close_range(void);

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 14, 6:26 PM (7 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15799427
Default Alt Text
D31475.diff (5 KB)

Event Timeline