git: 3f0aea09689f - main - libc: add posix_spawnattr_{get,set}execfd_np(3)

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sun, 25 Jan 2026 17:20:55 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=3f0aea09689f6c10740de78011469355208a19a5

commit 3f0aea09689f6c10740de78011469355208a19a5
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-24 22:06:36 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-01-25 17:19:53 +0000

    libc: add posix_spawnattr_{get,set}execfd_np(3)
    
    If execfd is set, the fexecve(2) is used by posix_spawn() instead of the
    provided path.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D54862
---
 include/spawn.h            |  7 +++++++
 lib/libc/gen/Symbol.map    |  5 +++++
 lib/libc/gen/posix_spawn.c | 22 +++++++++++++++++++++-
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/include/spawn.h b/include/spawn.h
index a93315930954..a8f40e49dce0 100644
--- a/include/spawn.h
+++ b/include/spawn.h
@@ -123,6 +123,13 @@ int posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict,
     const sigset_t * __restrict);
 int posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict,
     const sigset_t * __restrict);
+
+#if __BSD_VISIBLE
+int posix_spawnattr_setexecfd_np(posix_spawnattr_t * __restrict, int);
+int posix_spawnattr_getexecfd_np(const posix_spawnattr_t * __restrict,
+    int * __restrict);
+#endif
+
 __END_DECLS
 
 #endif /* !_SPAWN_H_ */
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 494b65bc5cc1..19170768ef7c 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -474,6 +474,11 @@ FBSD_1.8 {
 	str2sig;
 };
 
+FBSD_1.9 {
+	posix_spawnattr_getexecfd_np;
+	posix_spawnattr_setexecfd_np;
+};
+
 FBSDprivate_1.0 {
 	/* needed by thread libraries */
 	__thr_jtable;
diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c
index a5b732696b8c..fc327e15bbf0 100644
--- a/lib/libc/gen/posix_spawn.c
+++ b/lib/libc/gen/posix_spawn.c
@@ -50,6 +50,7 @@ struct __posix_spawnattr {
 	int			sa_schedpolicy;
 	sigset_t		sa_sigdefault;
 	sigset_t		sa_sigmask;
+	int			sa_execfd;
 };
 
 struct __posix_spawn_file_actions {
@@ -260,7 +261,9 @@ _posix_spawn_thr(void *data)
 			_exit(127);
 	}
 	envp = psa->envp != NULL ? psa->envp : environ;
-	if (psa->use_env_path)
+	if (psa->sa != NULL && (*(psa->sa))->sa_execfd != -1)
+		fexecve((*(psa->sa))->sa_execfd, psa->argv, envp);
+	else if (psa->use_env_path)
 		__libc_execvpe(psa->path, psa->argv, envp);
 	else
 		_execve(psa->path, psa->argv, envp);
@@ -578,6 +581,7 @@ posix_spawnattr_init(posix_spawnattr_t *ret)
 	sa = calloc(1, sizeof(struct __posix_spawnattr));
 	if (sa == NULL)
 		return (errno);
+	sa->sa_execfd = -1;
 
 	/* Set defaults as specified by POSIX, cleared above */
 	*ret = sa;
@@ -639,6 +643,14 @@ posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa,
 	return (0);
 }
 
+int
+posix_spawnattr_getexecfd_np(const posix_spawnattr_t * __restrict sa,
+    int * __restrict fdp)
+{
+	*fdp = (*sa)->sa_execfd;
+	return (0);
+}
+
 int
 posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags)
 {
@@ -688,3 +700,11 @@ posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa,
 	(*sa)->sa_sigmask = *sigmask;
 	return (0);
 }
+
+int
+posix_spawnattr_setexecfd_np(posix_spawnattr_t * __restrict sa,
+    int execfd)
+{
+	(*sa)->sa_execfd = execfd;
+	return (0);
+}