git: 971f738679e2 - main - kern: Make dup3() support O_CLOFORK

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Sun, 06 Jul 2025 23:18:39 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=971f738679e2e57114366c0f69af99e07150f1ff

commit 971f738679e2e57114366c0f69af99e07150f1ff
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2025-05-17 09:53:10 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-07-06 23:08:37 +0000

    kern: Make dup3() support O_CLOFORK
    
    Reviewed by:    kib
    MFC after:      1 month
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1698
---
 lib/libc/gen/dup3.c     |  9 +++++----
 sys/kern/kern_descrip.c | 15 ++++++++++++++-
 sys/sys/fcntl.h         |  4 ++++
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/lib/libc/gen/dup3.c b/lib/libc/gen/dup3.c
index fca1e99fb47b..1401c1f5b607 100644
--- a/lib/libc/gen/dup3.c
+++ b/lib/libc/gen/dup3.c
@@ -39,21 +39,22 @@ int __dup3(int, int, int);
 int
 __dup3(int oldfd, int newfd, int flags)
 {
-	int how;
+	int fdflags;
 
 	if (oldfd == newfd) {
 		errno = EINVAL;
 		return (-1);
 	}
 
-	if (flags & ~O_CLOEXEC) {
+	if ((flags & ~(O_CLOEXEC | O_CLOFORK)) != 0) {
 		errno = EINVAL;
 		return (-1);
 	}
 
-	how = (flags & O_CLOEXEC) ? F_DUP2FD_CLOEXEC : F_DUP2FD;
+	fdflags = ((flags & O_CLOEXEC) != 0 ? FD_CLOEXEC : 0) |
+	    ((flags & O_CLOFORK) != 0 ? FD_CLOFORK : 0);
 
-	return (_fcntl(oldfd, how, newfd));
+	return (_fcntl(oldfd, F_DUP3FD | (fdflags << F_DUP3FD_SHIFT), newfd));
 }
 
 __weak_reference(__dup3, dup3);
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index e432f33d810e..406236fc2723 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -38,9 +38,11 @@
 #include "opt_ddb.h"
 #include "opt_ktrace.h"
 
+#define EXTERR_CATEGORY	EXTERR_CAT_FILEDESC
 #include <sys/systm.h>
 #include <sys/capsicum.h>
 #include <sys/conf.h>
+#include <sys/exterrvar.h>
 #include <sys/fcntl.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
@@ -492,6 +494,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
 	int error, flg, kif_sz, seals, tmp, got_set, got_cleared;
 	uint64_t bsize;
 	off_t foffset;
+	int flags;
 
 	error = 0;
 	flg = F_POSIX;
@@ -923,7 +926,17 @@ revert_f_setfl:
 		break;
 
 	default:
-		error = EINVAL;
+		if ((cmd & ((1u << F_DUP3FD_SHIFT) - 1)) != F_DUP3FD)
+			return (EXTERROR(EINVAL, "invalid fcntl cmd"));
+		/* Handle F_DUP3FD */
+		flags = (cmd >> F_DUP3FD_SHIFT);
+		if ((flags & ~(FD_CLOEXEC | FD_CLOFORK)) != 0)
+			return (EXTERROR(EINVAL, "invalid flags for F_DUP3FD"));
+		tmp = arg;
+		error = kern_dup(td, FDDUP_FIXED,
+		    ((flags & FD_CLOEXEC) != 0 ? FDDUP_FLAG_CLOEXEC : 0) |
+		    ((flags & FD_CLOFORK) != 0 ? FDDUP_FLAG_CLOFORK : 0),
+		    fd, tmp);
 		break;
 	}
 	return (error);
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
index 7234c9240c84..18d3928e91c7 100644
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -291,6 +291,10 @@ typedef	__pid_t		pid_t;
 #endif
 
 #if __BSD_VISIBLE
+#define F_DUP3FD	24		/* Used with dup3() */
+
+#define F_DUP3FD_SHIFT	16		/* Shift used for F_DUP3FD */
+
 /* Seals (F_ADD_SEALS, F_GET_SEALS). */
 #define	F_SEAL_SEAL	0x0001		/* Prevent adding sealings */
 #define	F_SEAL_SHRINK	0x0002		/* May not shrink */