Index: lib/libc/sys/pdfork.2 =================================================================== --- lib/libc/sys/pdfork.2 +++ lib/libc/sys/pdfork.2 @@ -46,6 +46,8 @@ .In sys/procdesc.h .Ft pid_t .Fn pdfork "int *fdp" "int flags" +.Ft pid_t +.Fn pdvfork "int *fdp" "int flags" .Ft int .Fn pdgetpid "int fd" "pid_t *pidp" .Ft int @@ -82,6 +84,14 @@ Set close-on-exec on process descriptor. .El .Pp +.Fn pdvfork +accepts the same parameters and produces the same return value as +.Fn pdfork +but behaves as +.Xr vfork 2 , +rather than +.Xr fork 2 . +.Pp .Fn pdgetpid queries the process ID (PID) in the process descriptor .Fa fd . Index: sys/bsm/audit_kevents.h =================================================================== --- sys/bsm/audit_kevents.h +++ sys/bsm/audit_kevents.h @@ -662,6 +662,7 @@ #define AUE_SPECIALFD 43266 /* FreeBSD-specific. */ #define AUE_AIO_WRITEV 43267 /* FreeBSD-specific. */ #define AUE_AIO_READV 43268 /* FreeBSD-specific. */ +#define AUE_PDVFORK 43269 /* FreeBSD-specific. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the Index: sys/compat/freebsd32/freebsd32_syscall.h =================================================================== --- sys/compat/freebsd32/freebsd32_syscall.h +++ sys/compat/freebsd32/freebsd32_syscall.h @@ -506,4 +506,5 @@ #define FREEBSD32_SYS___specialfd 577 #define FREEBSD32_SYS_freebsd32_aio_writev 578 #define FREEBSD32_SYS_freebsd32_aio_readv 579 -#define FREEBSD32_SYS_MAXSYSCALL 580 +#define FREEBSD32_SYS_pdvfork 580 +#define FREEBSD32_SYS_MAXSYSCALL 581 Index: sys/compat/freebsd32/freebsd32_syscalls.c =================================================================== --- sys/compat/freebsd32/freebsd32_syscalls.c +++ sys/compat/freebsd32/freebsd32_syscalls.c @@ -616,4 +616,5 @@ "__specialfd", /* 577 = __specialfd */ "freebsd32_aio_writev", /* 578 = freebsd32_aio_writev */ "freebsd32_aio_readv", /* 579 = freebsd32_aio_readv */ + "pdvfork", /* 580 = pdvfork */ }; Index: sys/compat/freebsd32/freebsd32_sysent.c =================================================================== --- sys/compat/freebsd32/freebsd32_sysent.c +++ sys/compat/freebsd32/freebsd32_sysent.c @@ -669,4 +669,5 @@ { .sy_narg = AS(__specialfd_args), .sy_call = (sy_call_t *)sys___specialfd, .sy_auevent = AUE_SPECIALFD, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 577 = __specialfd */ { .sy_narg = AS(freebsd32_aio_writev_args), .sy_call = (sy_call_t *)freebsd32_aio_writev, .sy_auevent = AUE_AIO_WRITEV, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 578 = freebsd32_aio_writev */ { .sy_narg = AS(freebsd32_aio_readv_args), .sy_call = (sy_call_t *)freebsd32_aio_readv, .sy_auevent = AUE_AIO_READV, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 579 = freebsd32_aio_readv */ + { .sy_narg = AS(pdvfork_args), .sy_call = (sy_call_t *)sys_pdvfork, .sy_auevent = AUE_PDVFORK, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 580 = pdvfork */ }; Index: sys/compat/freebsd32/freebsd32_systrace_args.c =================================================================== --- sys/compat/freebsd32/freebsd32_systrace_args.c +++ sys/compat/freebsd32/freebsd32_systrace_args.c @@ -3407,6 +3407,14 @@ *n_args = 1; break; } + /* pdvfork */ + case 580: { + struct pdvfork_args *p = params; + uarg[0] = (intptr_t)p->fdp; /* int * */ + iarg[1] = p->flags; /* int */ + *n_args = 2; + break; + } default: *n_args = 0; break; @@ -9183,6 +9191,19 @@ break; }; break; + /* pdvfork */ + case 580: + switch (ndx) { + case 0: + p = "userland int *"; + break; + case 1: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -11102,6 +11123,11 @@ if (ndx == 0 || ndx == 1) p = "int"; break; + /* pdvfork */ + case 580: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; Index: sys/compat/freebsd32/syscalls.master =================================================================== --- sys/compat/freebsd32/syscalls.master +++ sys/compat/freebsd32/syscalls.master @@ -1174,5 +1174,6 @@ struct aiocb32 *aiocbp); } 579 AUE_AIO_READV STD { int freebsd32_aio_readv( \ struct aiocb32 *aiocbp); } +580 AUE_PDVFORK NOPROTO { int pdvfork(int *fdp, int flags); } ; vim: syntax=off Index: sys/kern/init_sysent.c =================================================================== --- sys/kern/init_sysent.c +++ sys/kern/init_sysent.c @@ -635,4 +635,5 @@ { .sy_narg = AS(__specialfd_args), .sy_call = (sy_call_t *)sys___specialfd, .sy_auevent = AUE_SPECIALFD, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 577 = __specialfd */ { .sy_narg = AS(aio_writev_args), .sy_call = (sy_call_t *)sys_aio_writev, .sy_auevent = AUE_AIO_WRITEV, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 578 = aio_writev */ { .sy_narg = AS(aio_readv_args), .sy_call = (sy_call_t *)sys_aio_readv, .sy_auevent = AUE_AIO_READV, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 579 = aio_readv */ + { .sy_narg = AS(pdvfork_args), .sy_call = (sy_call_t *)sys_pdvfork, .sy_auevent = AUE_PDVFORK, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 580 = pdvfork */ }; Index: sys/kern/kern_fork.c =================================================================== --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -98,67 +98,75 @@ }; #endif -/* ARGSUSED */ -int -sys_fork(struct thread *td, struct fork_args *uap) +/** + * Helper for the pd- and v-fork calls containing the shared logic for fork, + * vfork, pdfork, and pdvfork. If `is_vfork` is set, then this does a + * [pd]vfork operation. If `outpid` is not null then this does a pd[v]fork + * operation. `pdfork_flags` contains the flags from a pdfork call and is + * ignured if `outpid` is null. + */ +static int +do_pdvfork(struct thread *td, bool is_vfork, pid_t *outpid, int pdfork_flags) { struct fork_req fr; - int error, pid; + int error, pid, fd; bzero(&fr, sizeof(fr)); - fr.fr_flags = RFFDG | RFPROC; + fr.fr_flags = RFFDG | RFPROC | ((is_vfork) ? RFPPWAIT | RFMEM : 0); + if (outpid) { + fr.fr_flags |= RFPROCDESC; + fr.fr_pd_fd = &fd; + fr.fr_pd_flags = pdfork_flags; + } fr.fr_pidp = &pid; error = fork1(td, &fr); + /* + * It is necessary to return fd by reference because 0 is a valid file + * descriptor number, and the child needs to be able to distinguish + * itself from the parent using the return value. + */ if (error == 0) { td->td_retval[0] = pid; td->td_retval[1] = 0; + if (outpid) { + error = copyout(&fd, outpid, sizeof(fd)); + } } return (error); } +/* ARGSUSED */ +int +sys_fork(struct thread *td, struct fork_args *uap) +{ + + return (do_pdvfork(td, false, NULL, 0)); +} + /* ARGUSED */ int sys_pdfork(struct thread *td, struct pdfork_args *uap) { - struct fork_req fr; - int error, fd, pid; - bzero(&fr, sizeof(fr)); - fr.fr_flags = RFFDG | RFPROC | RFPROCDESC; - fr.fr_pidp = &pid; - fr.fr_pd_fd = &fd; - fr.fr_pd_flags = uap->flags; AUDIT_ARG_FFLAGS(uap->flags); - /* - * It is necessary to return fd by reference because 0 is a valid file - * descriptor number, and the child needs to be able to distinguish - * itself from the parent using the return value. - */ - error = fork1(td, &fr); - if (error == 0) { - td->td_retval[0] = pid; - td->td_retval[1] = 0; - error = copyout(&fd, uap->fdp, sizeof(fd)); - } - return (error); + return (do_pdvfork(td, false, uap->fdp, uap->flags)); } /* ARGSUSED */ int sys_vfork(struct thread *td, struct vfork_args *uap) { - struct fork_req fr; - int error, pid; - bzero(&fr, sizeof(fr)); - fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM; - fr.fr_pidp = &pid; - error = fork1(td, &fr); - if (error == 0) { - td->td_retval[0] = pid; - td->td_retval[1] = 0; - } - return (error); + return (do_pdvfork(td, true, NULL, 0)); +} + +/* ARGSUSED */ +int +sys_pdvfork(struct thread *td, struct pdvfork_args *uap) +{ + + AUDIT_ARG_FFLAGS(uap->flags); + return (do_pdvfork(td, true, uap->fdp, uap->flags)); } int Index: sys/kern/syscalls.c =================================================================== --- sys/kern/syscalls.c +++ sys/kern/syscalls.c @@ -586,4 +586,5 @@ "__specialfd", /* 577 = __specialfd */ "aio_writev", /* 578 = aio_writev */ "aio_readv", /* 579 = aio_readv */ + "pdvfork", /* 580 = pdvfork */ }; Index: sys/kern/syscalls.master =================================================================== --- sys/kern/syscalls.master +++ sys/kern/syscalls.master @@ -3238,6 +3238,12 @@ _Inout_ struct aiocb *aiocbp ); } +580 AUE_PDVFORK STD { + int pdvfork( + _Out_ int *fdp, + int flags + ); + } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master Index: sys/kern/systrace_args.c =================================================================== --- sys/kern/systrace_args.c +++ sys/kern/systrace_args.c @@ -3399,6 +3399,14 @@ *n_args = 1; break; } + /* pdvfork */ + case 580: { + struct pdvfork_args *p = params; + uarg[0] = (intptr_t)p->fdp; /* int * */ + iarg[1] = p->flags; /* int */ + *n_args = 2; + break; + } default: *n_args = 0; break; @@ -9088,6 +9096,19 @@ break; }; break; + /* pdvfork */ + case 580: + switch (ndx) { + case 0: + p = "userland int *"; + break; + case 1: + p = "int"; + break; + default: + break; + }; + break; default: break; }; @@ -11034,6 +11055,11 @@ if (ndx == 0 || ndx == 1) p = "int"; break; + /* pdvfork */ + case 580: + if (ndx == 0 || ndx == 1) + p = "int"; + break; default: break; }; Index: sys/sys/procdesc.h =================================================================== --- sys/sys/procdesc.h +++ sys/sys/procdesc.h @@ -122,6 +122,7 @@ */ __BEGIN_DECLS pid_t pdfork(int *, int); +pid_t pdvfork(int *, int); int pdkill(int, int); int pdgetpid(int, pid_t *); __END_DECLS Index: sys/sys/syscall.h =================================================================== --- sys/sys/syscall.h +++ sys/sys/syscall.h @@ -515,4 +515,5 @@ #define SYS___specialfd 577 #define SYS_aio_writev 578 #define SYS_aio_readv 579 -#define SYS_MAXSYSCALL 580 +#define SYS_pdvfork 580 +#define SYS_MAXSYSCALL 581 Index: sys/sys/syscall.mk =================================================================== --- sys/sys/syscall.mk +++ sys/sys/syscall.mk @@ -420,4 +420,5 @@ rpctls_syscall.o \ __specialfd.o \ aio_writev.o \ - aio_readv.o + aio_readv.o \ + pdvfork.o Index: sys/sys/sysproto.h =================================================================== --- sys/sys/sysproto.h +++ sys/sys/sysproto.h @@ -1847,6 +1847,10 @@ struct aio_readv_args { char aiocbp_l_[PADL_(struct aiocb *)]; struct aiocb * aiocbp; char aiocbp_r_[PADR_(struct aiocb *)]; }; +struct pdvfork_args { + char fdp_l_[PADL_(int *)]; int * fdp; char fdp_r_[PADR_(int *)]; + char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; +}; int nosys(struct thread *, struct nosys_args *); void sys_sys_exit(struct thread *, struct sys_exit_args *); int sys_fork(struct thread *, struct fork_args *); @@ -2241,6 +2245,7 @@ int sys___specialfd(struct thread *, struct __specialfd_args *); int sys_aio_writev(struct thread *, struct aio_writev_args *); int sys_aio_readv(struct thread *, struct aio_readv_args *); +int sys_pdvfork(struct thread *, struct pdvfork_args *); #ifdef COMPAT_43 @@ -3175,6 +3180,7 @@ #define SYS_AUE___specialfd AUE_SPECIALFD #define SYS_AUE_aio_writev AUE_AIO_WRITEV #define SYS_AUE_aio_readv AUE_AIO_READV +#define SYS_AUE_pdvfork AUE_PDVFORK #undef PAD_ #undef PADL_