mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] [PATCH] [RFC] make clone() usable
@ 2023-05-30 23:35 Rich Felker
  2023-06-01 10:12 ` Alexey Izbyshev
  0 siblings, 1 reply; 8+ messages in thread
From: Rich Felker @ 2023-05-30 23:35 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 852 bytes --]

As discussed before (see the 2021 thread "Incorrect thread TID
caching") clone() has been effectively unusable because it produces a
child process in invalid state, with wrong tid in its thread
structure, among other problems.

The attached proposed patch attempts to make clone() usable by having
it share the _Fork logic for establishing a consistent process state
after forking, and also blocks use of flags which produce invalid
state.

With CLONE_VM, the old behavior is kept, with a caveat that the child
context is extremely restrictive, ala vfork.

It was raised previously (pardon the pun) that raise() should perhaps
be modified to make a SYS_gettid syscall rather than using the thread
structure tid, so that it's possible to call raise() in a vfork
context without signaling the wrong process. It might make sense to do
that now too.

Rich

[-- Attachment #2: clone.diff --]
[-- Type: text/plain, Size: 3062 bytes --]

diff --git a/src/internal/fork_impl.h b/src/internal/fork_impl.h
index 354e733b..f995fce2 100644
--- a/src/internal/fork_impl.h
+++ b/src/internal/fork_impl.h
@@ -17,3 +17,5 @@ extern hidden volatile int *const __vmlock_lockptr;
 hidden void __malloc_atfork(int);
 hidden void __ldso_atfork(int);
 hidden void __pthread_key_atfork(int);
+
+hidden void __post_Fork(int);
diff --git a/src/linux/clone.c b/src/linux/clone.c
index 8c1af7d3..e8f76bbc 100644
--- a/src/linux/clone.c
+++ b/src/linux/clone.c
@@ -4,18 +4,55 @@
 #include <sched.h>
 #include "pthread_impl.h"
 #include "syscall.h"
+#include "lock.h"
+#include "fork_impl.h"
+
+struct clone_start_args {
+	int (*func)(void *);
+	void *arg;
+	sigset_t sigmask;
+};
+
+static int clone_start(void *arg)
+{
+	struct clone_start_args *csa = arg;
+	__post_Fork(0);
+	__restore_sigs(&csa->sigmask);
+	return csa->func(csa->arg);
+}
 
 int clone(int (*func)(void *), void *stack, int flags, void *arg, ...)
 {
+	struct clone_start_args csa;
 	va_list ap;
-	pid_t *ptid, *ctid;
-	void  *tls;
+	pid_t *ptid = 0, *ctid = 0;
+	void  *tls = 0;
+
+	/* Flags that produce an invalid thread/TLS state are disallowed. */
+	int badflags = CLONE_THREAD | CLONE_SETTLS | CLONE_CHILD_CLEARTID;
+	if (flags & badflags)
+		return __syscall_ret(-EINVAL);
 
 	va_start(ap, arg);
-	ptid = va_arg(ap, pid_t *);
-	tls  = va_arg(ap, void *);
-	ctid = va_arg(ap, pid_t *);
+	if (flags & (CLONE_PIDFD | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID))
+	 	ptid = va_arg(ap, pid_t *);
+	if (flags & CLONE_CHILD_SETTID) {
+		tls = va_arg(ap, void *);
+		ctid = va_arg(ap, pid_t *);
+	}
 	va_end(ap);
 
-	return __syscall_ret(__clone(func, stack, flags, arg, ptid, tls, ctid));
+	if (flags & CLONE_VM)
+		return __syscall_ret(__clone(func, stack, flags, arg, ptid, tls, ctid));
+
+	__block_all_sigs(&csa.sigmask);
+	LOCK(__abort_lock);
+
+	csa.func = func;
+	csa.arg = arg;
+	int ret = __clone(clone_start, stack, flags, &csa, ptid, tls, ctid);
+
+	__post_Fork(ret);
+	__restore_sigs(&csa.sigmask);
+	return __syscall_ret(ret);
 }
diff --git a/src/process/_Fork.c b/src/process/_Fork.c
index fb0fdc2c..94906103 100644
--- a/src/process/_Fork.c
+++ b/src/process/_Fork.c
@@ -5,21 +5,13 @@
 #include "lock.h"
 #include "pthread_impl.h"
 #include "aio_impl.h"
+#include "fork_impl.h"
 
 static void dummy(int x) { }
 weak_alias(dummy, __aio_atfork);
 
-pid_t _Fork(void)
+void __post_Fork(int ret)
 {
-	pid_t ret;
-	sigset_t set;
-	__block_all_sigs(&set);
-	LOCK(__abort_lock);
-#ifdef SYS_fork
-	ret = __syscall(SYS_fork);
-#else
-	ret = __syscall(SYS_clone, SIGCHLD, 0);
-#endif
 	if (!ret) {
 		pthread_t self = __pthread_self();
 		self->tid = __syscall(SYS_gettid);
@@ -32,6 +24,20 @@ pid_t _Fork(void)
 	}
 	UNLOCK(__abort_lock);
 	if (!ret) __aio_atfork(1);
+}
+
+pid_t _Fork(void)
+{
+	pid_t ret;
+	sigset_t set;
+	__block_all_sigs(&set);
+	LOCK(__abort_lock);
+#ifdef SYS_fork
+	ret = __syscall(SYS_fork);
+#else
+	ret = __syscall(SYS_clone, SIGCHLD, 0);
+#endif
+	__post_Fork(ret);
 	__restore_sigs(&set);
 	return __syscall_ret(ret);
 }

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2023-06-02 15:30 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-30 23:35 [musl] [PATCH] [RFC] make clone() usable Rich Felker
2023-06-01 10:12 ` Alexey Izbyshev
2023-06-01 20:08   ` Rich Felker
2023-06-01 20:17     ` [musl] [PATCH] [v2] " Rich Felker
2023-06-02  7:28     ` [musl] [PATCH] [RFC] " Alexey Izbyshev
2023-06-02 14:16       ` Rich Felker
2023-06-02 14:19     ` Markus Wichmann
2023-06-02 15:30       ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).