The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=971f738679e2e57114366c0f69af99e07150f1ff
commit 971f738679e2e57114366c0f69af99e07150f1ff Author: Ricardo Branco <rbra...@suse.de> AuthorDate: 2025-05-17 09:53:10 +0000 Commit: Mark Johnston <ma...@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 */