Skip to content

Commit 523e777

Browse files
kern: Add support for POSIX O_CLOFORK flag
1 parent 7c27c50 commit 523e777

File tree

9 files changed

+70
-38
lines changed

9 files changed

+70
-38
lines changed

sys/kern/kern_descrip.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ int dodup3(struct proc *, int, int, int, register_t *);
8080

8181
#define DUPF_CLOEXEC 0x01
8282
#define DUPF_DUP2 0x02
83+
#define DUPF_CLOFORK 0x04
8384

8485
struct pool file_pool;
8586
struct pool fdesc_pool;
@@ -336,7 +337,7 @@ sys_dup3(struct proc *p, void *v, register_t *retval)
336337

337338
if (SCARG(uap, from) == SCARG(uap, to))
338339
return (EINVAL);
339-
if (SCARG(uap, flags) & ~O_CLOEXEC)
340+
if (SCARG(uap, flags) & ~(O_CLOEXEC | O_CLOFORK))
340341
return (EINVAL);
341342
return (dodup3(p, SCARG(uap, from), SCARG(uap, to),
342343
SCARG(uap, flags), retval));
@@ -388,6 +389,8 @@ dodup3(struct proc *p, int old, int new, int flags, register_t *retval)
388389
dupflags = DUPF_DUP2;
389390
if (flags & O_CLOEXEC)
390391
dupflags |= DUPF_CLOEXEC;
392+
if (flags & O_CLOFORK)
393+
dupflags |= DUPF_CLOFORK;
391394

392395
/* No need for FRELE(), finishdup() uses current ref. */
393396
return (finishdup(p, fp, old, new, retval, dupflags));
@@ -423,6 +426,7 @@ sys_fcntl(struct proc *p, void *v, register_t *retval)
423426

424427
case F_DUPFD:
425428
case F_DUPFD_CLOEXEC:
429+
case F_DUPFD_CLOFORK:
426430
newmin = (long)SCARG(uap, arg);
427431
if ((u_int)newmin >= lim_cur(RLIMIT_NOFILE) ||
428432
(u_int)newmin >= atomic_load_int(&maxfiles)) {
@@ -444,6 +448,8 @@ sys_fcntl(struct proc *p, void *v, register_t *retval)
444448

445449
if (SCARG(uap, cmd) == F_DUPFD_CLOEXEC)
446450
dupflags |= DUPF_CLOEXEC;
451+
else if (SCARG(uap, cmd) == F_DUPFD_CLOFORK)
452+
dupflags |= DUPF_CLOFORK;
447453

448454
/* No need for FRELE(), finishdup() uses current ref. */
449455
error = finishdup(p, fp, fd, i, retval, dupflags);
@@ -452,16 +458,17 @@ sys_fcntl(struct proc *p, void *v, register_t *retval)
452458

453459
case F_GETFD:
454460
fdplock(fdp);
455-
*retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
461+
*retval =
462+
((fdp->fd_ofileflags[fd] & UF_EXCLOSE) ? FD_CLOEXEC : 0) |
463+
((fdp->fd_ofileflags[fd] & UF_FOCLOSE) ? FD_CLOFORK : 0);
456464
fdpunlock(fdp);
457465
break;
458466

459467
case F_SETFD:
460468
fdplock(fdp);
461-
if ((long)SCARG(uap, arg) & 1)
462-
fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
463-
else
464-
fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
469+
fdp->fd_ofileflags[fd] =
470+
(((long)SCARG(uap, arg) & FD_CLOEXEC) ? UF_EXCLOSE : 0) |
471+
(((long)SCARG(uap, arg) & FD_CLOFORK) ? UF_FOCLOSE : 0);
465472
fdpunlock(fdp);
466473
break;
467474

@@ -667,9 +674,12 @@ finishdup(struct proc *p, struct file *fp, int old, int new,
667674
fdp->fd_ofiles[new] = fp;
668675
mtx_leave(&fdp->fd_fplock);
669676

670-
fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
677+
fdp->fd_ofileflags[new] =
678+
fdp->fd_ofileflags[old] & ~(UF_EXCLOSE | UF_FOCLOSE);
671679
if (dupflags & DUPF_CLOEXEC)
672680
fdp->fd_ofileflags[new] |= UF_EXCLOSE;
681+
if (dupflags & DUPF_CLOFORK)
682+
fdp->fd_ofileflags[new] |= UF_FOCLOSE;
673683
*retval = new;
674684

675685
if (oldfp != NULL) {
@@ -711,7 +721,7 @@ fdinsert(struct filedesc *fdp, int fd, int flags, struct file *fp)
711721
fdp->fd_ofiles[fd] = fp;
712722
mtx_leave(&fdp->fd_fplock);
713723

714-
fdp->fd_ofileflags[fd] |= (flags & UF_EXCLOSE);
724+
fdp->fd_ofileflags[fd] |= (flags & (UF_EXCLOSE | UF_FOCLOSE));
715725
}
716726

717727
void
@@ -1150,6 +1160,7 @@ fdcopy(struct process *pr)
11501160
* their internal consistency, so close them here.
11511161
*/
11521162
if (fp->f_count >= FDUP_MAX_COUNT ||
1163+
(fdp->fd_ofileflags[i] & UF_FOCLOSE) != 0 ||
11531164
fp->f_type == DTYPE_KQUEUE) {
11541165
if (i < newfdp->fd_freefile)
11551166
newfdp->fd_freefile = i;
@@ -1407,8 +1418,9 @@ dupfdopen(struct proc *p, int indx, int mode)
14071418
fdp->fd_ofiles[indx] = wfp;
14081419
mtx_leave(&fdp->fd_fplock);
14091420

1410-
fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) |
1411-
(fdp->fd_ofileflags[dupfd] & ~UF_EXCLOSE);
1421+
fdp->fd_ofileflags[indx] =
1422+
(fdp->fd_ofileflags[indx] & (UF_EXCLOSE | UF_FOCLOSE)) |
1423+
(fdp->fd_ofileflags[dupfd] & ~(UF_EXCLOSE | UF_FOCLOSE));
14121424

14131425
return (0);
14141426
}

sys/kern/sys_pipe.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ sys_pipe2(struct proc *p, void *v, register_t *retval)
162162
syscallarg(int) flags;
163163
} */ *uap = v;
164164

165-
if (SCARG(uap, flags) & ~(O_CLOEXEC | FNONBLOCK))
165+
if (SCARG(uap, flags) & ~(O_CLOEXEC | O_CLOFORK | FNONBLOCK))
166166
return (EINVAL);
167167

168168
return (dopipe(p, SCARG(uap, fdp), SCARG(uap, flags)));
@@ -175,9 +175,10 @@ dopipe(struct proc *p, int *ufds, int flags)
175175
struct file *rf, *wf;
176176
struct pipe_pair *pp;
177177
struct pipe *rpipe, *wpipe = NULL;
178-
int fds[2], cloexec, error;
178+
int fds[2], fdflags, error;
179179

180-
cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
180+
fdflags = ((flags & O_CLOEXEC) ? UF_EXCLOSE : 0) |
181+
((flags & O_CLOFORK) ? UF_FOCLOSE : 0);
181182

182183
pp = pipe_pair_create();
183184
if (pp == NULL)
@@ -203,8 +204,8 @@ dopipe(struct proc *p, int *ufds, int flags)
203204
wf->f_data = wpipe;
204205
wf->f_ops = &pipeops;
205206

206-
fdinsert(fdp, fds[0], cloexec, rf);
207-
fdinsert(fdp, fds[1], cloexec, wf);
207+
fdinsert(fdp, fds[0], fdflags, rf);
208+
fdinsert(fdp, fds[1], fdflags, wf);
208209

209210
error = copyout(fds, ufds, sizeof(fds));
210211
if (error == 0) {

sys/kern/uipc_syscalls.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ sys_socket(struct proc *p, void *v, register_t *retval)
8181
struct file *fp;
8282
int type = SCARG(uap, type);
8383
int domain = SCARG(uap, domain);
84-
int fd, cloexec, nonblock, fflag, error;
84+
int fd, fdflags, nonblock, fflag, error;
8585
unsigned int ss = 0;
8686

8787
if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6))
@@ -93,8 +93,9 @@ sys_socket(struct proc *p, void *v, register_t *retval)
9393
if (error)
9494
return (error);
9595

96-
type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DNS);
97-
cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
96+
type &= ~(SOCK_CLOEXEC | SOCK_CLOFORK | SOCK_NONBLOCK | SOCK_DNS);
97+
fdflags = ((SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0) |
98+
((SCARG(uap, type) & SOCK_CLOFORK) ? UF_FOCLOSE : 0);
9899
nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
99100
fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
100101

@@ -113,7 +114,7 @@ sys_socket(struct proc *p, void *v, register_t *retval)
113114
fp->f_ops = &socketops;
114115
so->so_state |= ss;
115116
fp->f_data = so;
116-
fdinsert(fdp, fd, cloexec, fp);
117+
fdinsert(fdp, fd, fdflags, fp);
117118
fdpunlock(fdp);
118119
FRELE(fp, p);
119120
*retval = fd;
@@ -240,7 +241,7 @@ sys_accept4(struct proc *p, void *v, register_t *retval)
240241
syscallarg(socklen_t *) int flags;
241242
} */ *uap = v;
242243

243-
if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
244+
if (SCARG(uap, flags) & ~(SOCK_CLOEXEC | SOCK_CLOFORK | SOCK_NONBLOCK))
244245
return (EINVAL);
245246

246247
return (doaccept(p, SCARG(uap, s), SCARG(uap, name),
@@ -257,9 +258,10 @@ doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen,
257258
socklen_t namelen;
258259
int error, tmpfd;
259260
struct socket *head, *so;
260-
int cloexec, nflag;
261+
int fdflags, nflag;
261262

262-
cloexec = (flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
263+
fdflags = ((flags & SOCK_CLOEXEC) ? UF_EXCLOSE : 0) |
264+
((flags & SOCK_CLOFORK) ? UF_FOCLOSE : 0);
263265

264266
if (name && (error = copyin(anamelen, &namelen, sizeof (namelen))))
265267
return (error);
@@ -346,7 +348,7 @@ doaccept(struct proc *p, int sock, struct sockaddr *name, socklen_t *anamelen,
346348
}
347349

348350
fdplock(fdp);
349-
fdinsert(fdp, tmpfd, cloexec, fp);
351+
fdinsert(fdp, tmpfd, fdflags, fp);
350352
fdpunlock(fdp);
351353
FRELE(fp, p);
352354
*retval = tmpfd;
@@ -457,10 +459,11 @@ sys_socketpair(struct proc *p, void *v, register_t *retval)
457459
struct filedesc *fdp = p->p_fd;
458460
struct file *fp1 = NULL, *fp2 = NULL;
459461
struct socket *so1, *so2;
460-
int type, cloexec, nonblock, fflag, error, sv[2];
462+
int type, fdflags, nonblock, fflag, error, sv[2];
461463

462-
type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
463-
cloexec = (SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0;
464+
type = SCARG(uap, type) & ~(SOCK_CLOEXEC | SOCK_CLOFORK | SOCK_NONBLOCK);
465+
fdflags = ((SCARG(uap, type) & SOCK_CLOEXEC) ? UF_EXCLOSE : 0) |
466+
((SCARG(uap, type) & SOCK_CLOFORK) ? UF_FOCLOSE : 0);
464467
nonblock = SCARG(uap, type) & SOCK_NONBLOCK;
465468
fflag = FREAD | FWRITE | (nonblock ? FNONBLOCK : 0);
466469

@@ -498,8 +501,8 @@ sys_socketpair(struct proc *p, void *v, register_t *retval)
498501
fp2->f_data = so2;
499502
error = copyout(sv, SCARG(uap, rsv), 2 * sizeof (int));
500503
if (error == 0) {
501-
fdinsert(fdp, sv[0], cloexec, fp1);
502-
fdinsert(fdp, sv[1], cloexec, fp2);
504+
fdinsert(fdp, sv[0], fdflags, fp1);
505+
fdinsert(fdp, sv[1], fdflags, fp2);
503506
fdpunlock(fdp);
504507
#ifdef KTRACE
505508
if (KTRPOINT(p, KTR_STRUCT))

sys/kern/uipc_usrreq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,8 @@ unp_externalize(struct mbuf *rights, socklen_t controllen, int flags)
11461146
fdp->fd_ofileflags[fds[i]] = (rp->flags & UF_PLEDGED);
11471147
if (flags & MSG_CMSG_CLOEXEC)
11481148
fdp->fd_ofileflags[fds[i]] |= UF_EXCLOSE;
1149+
if (flags & MSG_CMSG_CLOFORK)
1150+
fdp->fd_ofileflags[fds[i]] |= UF_FOCLOSE;
11491151

11501152
rp++;
11511153
}

sys/kern/vfs_syscalls.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode,
10861086
struct file *fp;
10871087
struct vnode *vp;
10881088
struct vattr vattr;
1089-
int flags, cloexec, cmode;
1089+
int flags, fdflags, cmode;
10901090
int type, indx, error, localtrunc = 0;
10911091
struct flock lf;
10921092
struct nameidata nd;
@@ -1099,7 +1099,8 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode,
10991099
return (error);
11001100
}
11011101

1102-
cloexec = (oflags & O_CLOEXEC) ? UF_EXCLOSE : 0;
1102+
fdflags = ((oflags & O_CLOEXEC) ? UF_EXCLOSE : 0) |
1103+
((oflags & O_CLOFORK) ? UF_FOCLOSE : 0);
11031104

11041105
fdplock(fdp);
11051106
if ((error = falloc(p, &fp, &indx)) != 0) {
@@ -1200,7 +1201,7 @@ doopenat(struct proc *p, int fd, const char *path, int oflags, mode_t mode,
12001201
KERNEL_UNLOCK();
12011202
*retval = indx;
12021203
fdplock(fdp);
1203-
fdinsert(fdp, indx, cloexec, fp);
1204+
fdinsert(fdp, indx, fdflags, fp);
12041205
fdpunlock(fdp);
12051206
FRELE(fp, p);
12061207
return (error);
@@ -1224,17 +1225,19 @@ sys___tmpfd(struct proc *p, void *v, register_t *retval)
12241225
struct file *fp;
12251226
struct vnode *vp;
12261227
int oflags = SCARG(uap, flags);
1227-
int flags, cloexec, cmode;
1228+
int flags, fdflags, cmode;
12281229
int indx, error;
12291230
unsigned int i;
12301231
struct nameidata nd;
12311232
char path[64];
12321233
static const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
12331234

12341235
/* most flags are hardwired */
1235-
oflags = O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | (oflags & O_CLOEXEC);
1236+
oflags = O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW |
1237+
(oflags & (O_CLOEXEC | O_CLOFORK));
12361238

1237-
cloexec = (oflags & O_CLOEXEC) ? UF_EXCLOSE : 0;
1239+
fdflags = ((oflags & O_CLOEXEC) ? UF_EXCLOSE : 0) |
1240+
((oflags & O_CLOFORK) ? UF_FOCLOSE : 0);
12381241

12391242
fdplock(fdp);
12401243
if ((error = falloc(p, &fp, &indx)) != 0) {
@@ -1270,7 +1273,7 @@ sys___tmpfd(struct proc *p, void *v, register_t *retval)
12701273
VOP_UNLOCK(vp);
12711274
*retval = indx;
12721275
fdplock(fdp);
1273-
fdinsert(fdp, indx, cloexec, fp);
1276+
fdinsert(fdp, indx, fdflags, fp);
12741277
fdpunlock(fdp);
12751278
FRELE(fp, p);
12761279

@@ -1352,7 +1355,7 @@ sys_fhopen(struct proc *p, void *v, register_t *retval)
13521355
struct vnode *vp = NULL;
13531356
struct mount *mp;
13541357
struct ucred *cred = p->p_ucred;
1355-
int flags, cloexec;
1358+
int flags, fdflags;
13561359
int type, indx, error=0;
13571360
struct flock lf;
13581361
struct vattr va;
@@ -1370,7 +1373,8 @@ sys_fhopen(struct proc *p, void *v, register_t *retval)
13701373
if ((flags & O_CREAT))
13711374
return (EINVAL);
13721375

1373-
cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
1376+
fdflags = ((flags & O_CLOEXEC) ? UF_EXCLOSE : 0) |
1377+
((flags & O_CLOFORK) ? UF_FOCLOSE : 0);
13741378

13751379
fdplock(fdp);
13761380
if ((error = falloc(p, &fp, &indx)) != 0) {
@@ -1456,7 +1460,7 @@ sys_fhopen(struct proc *p, void *v, register_t *retval)
14561460
VOP_UNLOCK(vp);
14571461
*retval = indx;
14581462
fdplock(fdp);
1459-
fdinsert(fdp, indx, cloexec, fp);
1463+
fdinsert(fdp, indx, fdflags, fp);
14601464
fdpunlock(fdp);
14611465
FRELE(fp, p);
14621466
return (0);

sys/sys/fcntl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
/* defined by POSIX Issue 7 */
107107
#define O_CLOEXEC 0x10000 /* atomically set FD_CLOEXEC */
108108
#define O_DIRECTORY 0x20000 /* fail if not a directory */
109+
#define O_CLOFORK 0x40000 /* atomically set FD_CLOFORK */
109110

110111
#ifdef _KERNEL
111112
/*
@@ -158,9 +159,13 @@
158159
#if __BSD_VISIBLE
159160
#define F_ISATTY 11 /* used by isatty(3) */
160161
#endif
162+
#if __POSIX_VISIBLE >= 202405
163+
#define F_DUPFD_CLOFORK 12 /* duplicate with FD_CLOFORK set */
164+
#endif
161165

162166
/* file descriptor flags (F_GETFD, F_SETFD) */
163167
#define FD_CLOEXEC 1 /* close-on-exec flag */
168+
#define FD_CLOFORK 2 /* close-on-fork flag */
164169

165170
/* record locking flags (F_GETLK, F_SETLK, F_SETLKW) */
166171
#define F_RDLCK 1 /* shared or read lock */

sys/sys/filedesc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ struct filedesc0 {
115115
*/
116116
#define UF_EXCLOSE 0x01 /* auto-close on exec */
117117
#define UF_PLEDGED 0x02 /* open after pledge(2) */
118+
#define UF_FOCLOSE 0x04 /* auto-close on fork */
118119

119120
/*
120121
* Flags on the file descriptor table.

sys/sys/socket.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ typedef __sa_family_t sa_family_t; /* sockaddr address family type */
7979
#define SOCK_NONBLOCK_INHERIT 0x2000 /* inherit O_NONBLOCK from listener */
8080
#endif
8181
#define SOCK_DNS 0x1000 /* set SS_DNS */
82+
#define SOCK_CLOFORK 0x0800 /* set FD_CLOFORK */
8283
#endif /* __BSD_VISIBLE */
8384

8485
/*
@@ -511,6 +512,7 @@ struct timespec;
511512
#define MSG_NOSIGNAL 0x400 /* do not send SIGPIPE */
512513
#define MSG_CMSG_CLOEXEC 0x800 /* set FD_CLOEXEC on received fds */
513514
#define MSG_WAITFORONE 0x1000 /* nonblocking but wait for one msg */
515+
#define MSG_CMSG_CLOFORK 0x2000 /* set FD_CLOFORK on received fds */
514516

515517
/*
516518
* Header for ancillary data objects in msg_control buffer.

usr.bin/fstat/fstat.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@ vtrans(struct kinfo_file *kf)
482482
strlcat(rwep, "w", sizeof rwep);
483483
if (kf->fd_ofileflags & UF_EXCLOSE)
484484
strlcat(rwep, "e", sizeof rwep);
485+
if (kf->fd_ofileflags & UF_FOCLOSE)
486+
strlcat(rwep, "f", sizeof rwep);
485487
if (kf->fd_ofileflags & UF_PLEDGED)
486488
strlcat(rwep, "p", sizeof rwep);
487489
printf(" %4s", rwep);

0 commit comments

Comments
 (0)