git: 02ffca404e65 - main - kern: Add support for POSIX O_CLOFORK flag
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 06 Jul 2025 23:18:35 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=02ffca404e65b2058720e1e9d5a5bc8bb2867113
commit 02ffca404e65b2058720e1e9d5a5bc8bb2867113
Author: Ricardo Branco <rbranco@suse.de>
AuthorDate: 2025-06-20 12:06:48 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-07-06 23:08:19 +0000
kern: Add support for POSIX O_CLOFORK flag
Reviewed by: kib
MFC after: 1 month
Pull Request: https://github.com/freebsd/freebsd-src/pull/1698
---
sys/kern/kern_descrip.c | 28 ++++++++++++++++++++++------
sys/kern/sys_pipe.c | 2 +-
sys/sys/fcntl.h | 13 +++++++++++++
sys/sys/filedesc.h | 2 ++
4 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index ac4b6ac3f457..bd6fa0c14075 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -511,6 +511,11 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
error = kern_dup(td, FDDUP_FCNTL, FDDUP_FLAG_CLOEXEC, fd, tmp);
break;
+ case F_DUPFD_CLOFORK:
+ tmp = arg;
+ error = kern_dup(td, FDDUP_FCNTL, FDDUP_FLAG_CLOFORK, fd, tmp);
+ break;
+
case F_DUP2FD:
tmp = arg;
error = kern_dup(td, FDDUP_FIXED, 0, fd, tmp);
@@ -528,6 +533,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
if (fde != NULL) {
td->td_retval[0] =
((fde->fde_flags & UF_EXCLOSE) ? FD_CLOEXEC : 0) |
+ ((fde->fde_flags & UF_FOCLOSE) ? FD_CLOFORK : 0) |
((fde->fde_flags & UF_RESOLVE_BENEATH) ?
FD_RESOLVE_BENEATH : 0);
error = 0;
@@ -545,6 +551,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
*/
fde->fde_flags = (fde->fde_flags & ~UF_EXCLOSE) |
((arg & FD_CLOEXEC) != 0 ? UF_EXCLOSE : 0) |
+ ((arg & FD_CLOFORK) != 0 ? UF_FOCLOSE : 0) |
((arg & FD_RESOLVE_BENEATH) != 0 ?
UF_RESOLVE_BENEATH : 0);
error = 0;
@@ -946,7 +953,7 @@ kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
fdp = p->p_fd;
oioctls = NULL;
- MPASS((flags & ~(FDDUP_FLAG_CLOEXEC)) == 0);
+ MPASS((flags & ~(FDDUP_FLAG_CLOEXEC | FDDUP_FLAG_CLOFORK)) == 0);
MPASS(mode < FDDUP_LASTMODE);
AUDIT_ARG_FD(old);
@@ -971,8 +978,10 @@ kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
goto unlock;
if (mode == FDDUP_FIXED && old == new) {
td->td_retval[0] = new;
- if (flags & FDDUP_FLAG_CLOEXEC)
+ if ((flags & FDDUP_FLAG_CLOEXEC) != 0)
fdp->fd_ofiles[new].fde_flags |= UF_EXCLOSE;
+ if ((flags & FDDUP_FLAG_CLOFORK) != 0)
+ fdp->fd_ofiles[new].fde_flags |= UF_FOCLOSE;
error = 0;
goto unlock;
}
@@ -1047,10 +1056,9 @@ kern_dup(struct thread *td, u_int mode, int flags, int old, int new)
fde_copy(oldfde, newfde);
filecaps_copy_finish(&oldfde->fde_caps, &newfde->fde_caps,
nioctls);
- if ((flags & FDDUP_FLAG_CLOEXEC) != 0)
- newfde->fde_flags = oldfde->fde_flags | UF_EXCLOSE;
- else
- newfde->fde_flags = oldfde->fde_flags & ~UF_EXCLOSE;
+ newfde->fde_flags = (oldfde->fde_flags & ~(UF_EXCLOSE | UF_FOCLOSE)) |
+ ((flags & FDDUP_FLAG_CLOEXEC) != 0 ? UF_EXCLOSE : 0) |
+ ((flags & FDDUP_FLAG_CLOFORK) != 0 ? UF_FOCLOSE : 0);
#ifdef CAPABILITIES
seqc_write_end(&newfde->fde_seqc);
#endif
@@ -2172,6 +2180,7 @@ _finstall(struct filedesc *fdp, struct file *fp, int fd, int flags,
#endif
fde->fde_file = fp;
fde->fde_flags = ((flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0) |
+ ((flags & O_CLOFORK) != 0 ? UF_FOCLOSE : 0) |
((flags & O_RESOLVE_BENEATH) != 0 ? UF_RESOLVE_BENEATH : 0);
if (fcaps != NULL)
filecaps_move(fcaps, &fde->fde_caps);
@@ -2432,6 +2441,7 @@ fdcopy(struct filedesc *fdp)
newfdp->fd_freefile = fdp->fd_freefile;
FILEDESC_FOREACH_FDE(fdp, i, ofde) {
if ((ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0 ||
+ (ofde->fde_flags & UF_FOCLOSE) != 0 ||
!fhold(ofde->fde_file)) {
if (newfdp->fd_freefile == fdp->fd_freefile)
newfdp->fd_freefile = i;
@@ -2729,6 +2739,12 @@ fdcloseexec(struct thread *td)
fdfree(fdp, i);
(void) closefp(fdp, i, fp, td, false, false);
FILEDESC_UNLOCK_ASSERT(fdp);
+ } else if (fde->fde_flags & UF_FOCLOSE) {
+ /*
+ * https://austingroupbugs.net/view.php?id=1851
+ * FD_CLOFORK should not be preserved across exec
+ */
+ fde->fde_flags &= ~UF_FOCLOSE;
}
}
}
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 9340779918a2..ed651da96b14 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -548,7 +548,7 @@ sys_pipe2(struct thread *td, struct pipe2_args *uap)
{
int error, fildes[2];
- if (uap->flags & ~(O_CLOEXEC | O_NONBLOCK))
+ if ((uap->flags & ~(O_CLOEXEC | O_CLOFORK | O_NONBLOCK)) != 0)
return (EINVAL);
error = kern_pipe(td, fildes, uap->flags, NULL, NULL);
if (error)
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
index dd9fccf5cf38..7234c9240c84 100644
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -144,6 +144,10 @@ typedef __pid_t pid_t;
#define O_XATTR O_NAMEDATTR /* Solaris compatibility */
#endif
+#if __POSIX_VISIBLE >= 202405
+#define O_CLOFORK 0x08000000
+#endif
+
/*
* !!! DANGER !!!
*
@@ -280,7 +284,13 @@ typedef __pid_t pid_t;
#define F_GET_SEALS 20
#define F_ISUNIONSTACK 21 /* Kludge for libc, don't use it. */
#define F_KINFO 22 /* Return kinfo_file for this fd */
+#endif /* __BSD_VISIBLE */
+#if __POSIX_VISIBLE >= 202405
+#define F_DUPFD_CLOFORK 23 /* Like F_DUPFD, but FD_CLOFORK is set */
+#endif
+
+#if __BSD_VISIBLE
/* Seals (F_ADD_SEALS, F_GET_SEALS). */
#define F_SEAL_SEAL 0x0001 /* Prevent adding sealings */
#define F_SEAL_SHRINK 0x0002 /* May not shrink */
@@ -292,6 +302,9 @@ typedef __pid_t pid_t;
#define FD_CLOEXEC 1 /* close-on-exec flag */
#define FD_RESOLVE_BENEATH 2 /* all lookups relative to fd have
O_RESOLVE_BENEATH semantics */
+#if __POSIX_VISIBLE >= 202405
+#define FD_CLOFORK 4 /* close-on-fork flag */
+#endif
/* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */
#define F_RDLCK 1 /* shared or read lock */
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 55969b2ff4b3..0a388c90de26 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -149,6 +149,7 @@ struct filedesc_to_leader {
*/
#define UF_EXCLOSE 0x01 /* auto-close on exec */
#define UF_RESOLVE_BENEATH 0x02 /* lookups must be beneath this dir */
+#define UF_FOCLOSE 0x04 /* auto-close on fork */
#ifdef _KERNEL
@@ -221,6 +222,7 @@ enum {
/* Flags for kern_dup(). */
#define FDDUP_FLAG_CLOEXEC 0x1 /* Atomically set UF_EXCLOSE. */
+#define FDDUP_FLAG_CLOFORK 0x2 /* Atomically set UF_FOCLOSE. */
/* For backward compatibility. */
#define falloc(td, resultfp, resultfd, flags) \