The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=02ffca404e65b2058720e1e9d5a5bc8bb2867113

commit 02ffca404e65b2058720e1e9d5a5bc8bb2867113
Author:     Ricardo Branco <rbra...@suse.de>
AuthorDate: 2025-06-20 12:06:48 +0000
Commit:     Mark Johnston <ma...@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) \

Reply via email to