Page MenuHomeFreeBSD

D54592.diff
No OneTemporary

D54592.diff

diff --git a/contrib/openbsm/sys/bsm/audit_kevents.h b/contrib/openbsm/sys/bsm/audit_kevents.h
--- a/contrib/openbsm/sys/bsm/audit_kevents.h
+++ b/contrib/openbsm/sys/bsm/audit_kevents.h
@@ -655,6 +655,7 @@
#define AUE_SHMRENAME 43263 /* FreeBSD-specific. */
#define AUE_REALPATHAT 43264 /* FreeBSD-specific. */
#define AUE_CLOSERANGE 43265 /* FreeBSD-specific. */
+#define AUE_PDRFORK 43266 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
diff --git a/lib/libc/gen/exterr_cat_filenames.h b/lib/libc/gen/exterr_cat_filenames.h
--- a/lib/libc/gen/exterr_cat_filenames.h
+++ b/lib/libc/gen/exterr_cat_filenames.h
@@ -8,9 +8,11 @@
[EXTERR_CAT_GEOM] = "geom/geom_subr.c",
[EXTERR_CAT_GEOMVFS] = "geom/geom_vfs.c",
[EXTERR_CAT_FILEDESC] = "kern/kern_descrip.c",
- [EXTERR_CAT_INOTIFY] = "kern/vfs_inotify.c",
+ [EXTERR_CAT_PROCEXIT] = "kern/kern_exit.c",
+ [EXTERR_CAT_FORK] = "kern/kern_fork.c",
[EXTERR_CAT_GENIO] = "kern/sys_generic.c",
[EXTERR_CAT_VFSBIO] = "kern/vfs_bio.c",
+ [EXTERR_CAT_INOTIFY] = "kern/vfs_inotify.c",
[EXTERR_CAT_VFSSYSCALL] = "kern/vfs_syscalls.c",
[EXTERR_CAT_BRIDGE] = "net/if_bridge.c",
[EXTERR_CAT_SWAP] = "vm/swap_pager.c",
diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map
--- a/lib/libsys/Symbol.sys.map
+++ b/lib/libsys/Symbol.sys.map
@@ -389,6 +389,11 @@
setgroups;
};
+FBSD_1.9 {
+ pdrfork;
+ pdwait;
+};
+
FBSDprivate_1.0 {
/* Add entries in sort(1) order */
__set_error_selector;
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -472,6 +472,8 @@
typedef int (__sys_jail_attach_jd_t)(int);
typedef int (__sys_jail_remove_jd_t)(int);
typedef int (__sys_kexec_load_t)(uint64_t, u_long, struct kexec_segment *, u_long);
+typedef int (__sys_pdrfork_t)(int *, int, int);
+typedef int (__sys_pdwait_t)(int, int *, int, struct __wrusage *, struct __siginfo *);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -879,6 +881,8 @@
int __sys_jail_attach_jd(int fd);
int __sys_jail_remove_jd(int fd);
int __sys_kexec_load(uint64_t entry, u_long nseg, struct kexec_segment * segments, u_long flags);
+int __sys_pdrfork(int * fdp, int pdflags, int rfflags);
+int __sys_pdwait(int fd, int * status, int options, struct __wrusage * wrusage, struct __siginfo * info);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -819,4 +819,8 @@
__sys_jail_remove_jd;
_kexec_load;
__sys_kexec_load;
+ _pdrfork;
+ __sys_pdrfork;
+ _pdwait;
+ __sys_pdwait;
};
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -664,6 +664,7 @@
#define AUE_TIMERFD 43270 /* FreeBSD/Linux. */
#define AUE_SETCRED 43271 /* FreeBSD-specific. */
#define AUE_INOTIFY 43272 /* FreeBSD/Linux. */
+#define AUE_PDRFORK 43266 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -280,6 +280,37 @@
return (error);
}
+int
+freebsd32_pdwait(struct thread *td, struct freebsd32_pdwait_args *uap)
+{
+ struct __wrusage32 wru32;
+ struct __wrusage wru, *wrup;
+ struct __siginfo32 si32;
+ struct __siginfo si, *sip;
+ int error, status;
+
+ wrup = uap->wrusage != NULL ? &wru : NULL;
+ if (uap->info != NULL) {
+ sip = &si;
+ bzero(sip, sizeof(*sip));
+ } else {
+ sip = NULL;
+ }
+ error = kern_pdwait(td, uap->fd, &status, uap->options, wrup, sip);
+ if (uap->status != NULL && error == 0)
+ error = copyout(&status, uap->status, sizeof(status));
+ if (uap->wrusage != NULL && error == 0) {
+ freebsd32_rusage_out(&wru.wru_self, &wru32.wru_self);
+ freebsd32_rusage_out(&wru.wru_children, &wru32.wru_children);
+ error = copyout(&wru32, uap->wrusage, sizeof(wru32));
+ }
+ if (uap->info != NULL && error == 0) {
+ siginfo_to_siginfo32 (&si, &si32);
+ error = copyout(&si32, uap->info, sizeof(si32));
+ }
+ return (error);
+}
+
#ifdef COMPAT_FREEBSD4
static void
copy_statfs(struct statfs *in, struct ostatfs32 *out)
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -699,6 +699,13 @@
char wcred_l_[PADL_(const struct setcred32 *)]; const struct setcred32 * wcred; char wcred_r_[PADR_(const struct setcred32 *)];
char size_l_[PADL_(size_t)]; size_t size; char size_r_[PADR_(size_t)];
};
+struct freebsd32_pdwait_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)];
+ char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
+ char wrusage_l_[PADL_(struct __wrusage32 *)]; struct __wrusage32 * wrusage; char wrusage_r_[PADR_(struct __wrusage32 *)];
+ char info_l_[PADL_(struct __siginfo32 *)]; struct __siginfo32 * info; char info_r_[PADR_(struct __siginfo32 *)];
+};
int freebsd32_wait4(struct thread *, struct freebsd32_wait4_args *);
int freebsd32_ptrace(struct thread *, struct freebsd32_ptrace_args *);
int freebsd32_recvmsg(struct thread *, struct freebsd32_recvmsg_args *);
@@ -817,6 +824,7 @@
int freebsd32_timerfd_gettime(struct thread *, struct freebsd32_timerfd_gettime_args *);
int freebsd32_timerfd_settime(struct thread *, struct freebsd32_timerfd_settime_args *);
int freebsd32_setcred(struct thread *, struct freebsd32_setcred_args *);
+int freebsd32_pdwait(struct thread *, struct freebsd32_pdwait_args *);
#ifdef COMPAT_43
@@ -1319,6 +1327,7 @@
#define FREEBSD32_SYS_AUE_freebsd32_timerfd_gettime AUE_TIMERFD
#define FREEBSD32_SYS_AUE_freebsd32_timerfd_settime AUE_TIMERFD
#define FREEBSD32_SYS_AUE_freebsd32_setcred AUE_SETCRED
+#define FREEBSD32_SYS_AUE_freebsd32_pdwait AUE_PDWAIT
#undef PAD_
#undef PADL_
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -517,4 +517,6 @@
#define FREEBSD32_SYS_setgroups 596
#define FREEBSD32_SYS_jail_attach_jd 597
#define FREEBSD32_SYS_jail_remove_jd 598
-#define FREEBSD32_SYS_MAXSYSCALL 600
+#define FREEBSD32_SYS_pdrfork 600
+#define FREEBSD32_SYS_freebsd32_pdwait 601
+#define FREEBSD32_SYS_MAXSYSCALL 602
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -605,4 +605,6 @@
"jail_attach_jd", /* 597 = jail_attach_jd */
"jail_remove_jd", /* 598 = jail_remove_jd */
"#599", /* 599 = kexec_load */
+ "pdrfork", /* 600 = pdrfork */
+ "freebsd32_pdwait", /* 601 = freebsd32_pdwait */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -667,4 +667,6 @@
{ .sy_narg = AS(jail_attach_jd_args), .sy_call = (sy_call_t *)sys_jail_attach_jd, .sy_auevent = AUE_JAIL_ATTACH, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 597 = jail_attach_jd */
{ .sy_narg = AS(jail_remove_jd_args), .sy_call = (sy_call_t *)sys_jail_remove_jd, .sy_auevent = AUE_JAIL_REMOVE, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 598 = jail_remove_jd */
{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 599 = freebsd32_kexec_load */
+ { .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
+ { .sy_narg = AS(freebsd32_pdwait_args), .sy_call = (sy_call_t *)freebsd32_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = freebsd32_pdwait */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3427,6 +3427,26 @@
*n_args = 1;
break;
}
+ /* pdrfork */
+ case 600: {
+ struct pdrfork_args *p = params;
+ uarg[a++] = (intptr_t)p->fdp; /* int * */
+ iarg[a++] = p->pdflags; /* int */
+ iarg[a++] = p->rfflags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* freebsd32_pdwait */
+ case 601: {
+ struct freebsd32_pdwait_args *p = params;
+ iarg[a++] = p->fd; /* int */
+ uarg[a++] = (intptr_t)p->status; /* int * */
+ iarg[a++] = p->options; /* int */
+ uarg[a++] = (intptr_t)p->wrusage; /* struct __wrusage32 * */
+ uarg[a++] = (intptr_t)p->info; /* struct __siginfo32 * */
+ *n_args = 5;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9256,6 +9276,44 @@
break;
};
break;
+ /* pdrfork */
+ case 600:
+ switch (ndx) {
+ case 0:
+ p = "userland int *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* freebsd32_pdwait */
+ case 601:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "userland int *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "userland struct __wrusage32 *";
+ break;
+ case 4:
+ p = "userland struct __siginfo32 *";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11174,6 +11232,16 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* pdrfork */
+ case 600:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* freebsd32_pdwait */
+ case 601:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -666,4 +666,6 @@
{ .sy_narg = AS(jail_attach_jd_args), .sy_call = (sy_call_t *)sys_jail_attach_jd, .sy_auevent = AUE_JAIL_ATTACH, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 597 = jail_attach_jd */
{ .sy_narg = AS(jail_remove_jd_args), .sy_call = (sy_call_t *)sys_jail_remove_jd, .sy_auevent = AUE_JAIL_REMOVE, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 598 = jail_remove_jd */
{ .sy_narg = AS(kexec_load_args), .sy_call = (sy_call_t *)sys_kexec_load, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 599 = kexec_load */
+ { .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
+ { .sy_narg = AS(pdwait_args), .sy_call = (sy_call_t *)sys_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = pdwait */
};
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -34,45 +34,45 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include "opt_ddb.h"
#include "opt_ktrace.h"
-#include <sys/param.h>
+#define EXTERR_CATEGORY EXTERR_CAT_PROCEXIT
#include <sys/systm.h>
-#include <sys/sysproto.h>
+#include <sys/acct.h> /* for acct_process() function prototype */
#include <sys/capsicum.h>
#include <sys/eventhandler.h>
+#include <sys/exterrvar.h>
+#include <sys/filedesc.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
-#include <sys/malloc.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/procdesc.h>
-#include <sys/jail.h>
-#include <sys/tty.h>
-#include <sys/wait.h>
-#include <sys/vmmeter.h>
-#include <sys/vnode.h>
+#include <sys/ptrace.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/sbuf.h>
-#include <sys/signalvar.h>
#include <sys/sched.h>
+#include <sys/sdt.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
+#include <sys/signalvar.h>
#include <sys/sx.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
-#include <sys/syslog.h>
-#include <sys/ptrace.h>
-#include <sys/acct.h> /* for acct_process() function prototype */
-#include <sys/filedesc.h>
-#include <sys/sdt.h>
-#include <sys/shm.h>
-#include <sys/sem.h>
#include <sys/sysent.h>
+#include <sys/syslog.h>
+#include <sys/sysproto.h>
#include <sys/timers.h>
+#include <sys/tty.h>
#include <sys/umtxvar.h>
+#include <sys/vmmeter.h>
+#include <sys/vnode.h>
+#include <sys/wait.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@@ -906,6 +906,33 @@
return (error);
}
+int
+sys_pdwait(struct thread *td, struct pdwait_args *uap)
+{
+ struct __wrusage wru, *wrup;
+ siginfo_t si, *sip;
+ int error, status;
+
+ wrup = uap->wrusage != NULL ? &wru : NULL;
+
+ if (uap->info != NULL) {
+ sip = &si;
+ bzero(sip, sizeof(*sip));
+ } else {
+ sip = NULL;
+ }
+
+ error = kern_pdwait(td, uap->fd, &status, uap->options, wrup, sip);
+
+ if (uap->status != NULL && error == 0)
+ error = copyout(&status, uap->status, sizeof(status));
+ if (uap->wrusage != NULL && error == 0)
+ error = copyout(&wru, uap->wrusage, sizeof(wru));
+ if (uap->info != NULL && error == 0)
+ error = copyout(&si, uap->info, sizeof(si));
+ return (error);
+}
+
/*
* Reap the remains of a zombie process and optionally return status and
* rusage. Asserts and will release both the proctree_lock and the process
@@ -924,9 +951,9 @@
q = td->td_proc;
- if (status)
+ if (status != NULL)
*status = KW_EXITCODE(p->p_xexit, p->p_xsig);
- if (options & WNOWAIT) {
+ if ((options & WNOWAIT) != 0) {
/*
* Only poll, returning the status. Caller does not wish to
* release the proc struct just yet.
@@ -1042,13 +1069,75 @@
atomic_add_int(&nprocs, -1);
}
+static void
+wait_fill_siginfo(struct proc *p, siginfo_t *siginfo)
+{
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ if (siginfo == NULL)
+ return;
+
+ bzero(siginfo, sizeof(*siginfo));
+ siginfo->si_errno = 0;
+
+ /*
+ * SUSv4 requires that the si_signo value is always
+ * SIGCHLD. Obey it despite the rfork(2) interface allows to
+ * request other signal for child exit notification.
+ */
+ siginfo->si_signo = SIGCHLD;
+
+ /*
+ * This is still a rough estimate. We will fix the cases
+ * TRAPPED, STOPPED, and CONTINUED later.
+ */
+ if (WCOREDUMP(p->p_xsig)) {
+ siginfo->si_code = CLD_DUMPED;
+ siginfo->si_status = WTERMSIG(p->p_xsig);
+ } else if (WIFSIGNALED(p->p_xsig)) {
+ siginfo->si_code = CLD_KILLED;
+ siginfo->si_status = WTERMSIG(p->p_xsig);
+ } else {
+ siginfo->si_code = CLD_EXITED;
+ siginfo->si_status = p->p_xexit;
+ }
+
+ siginfo->si_pid = p->p_pid;
+ siginfo->si_uid = p->p_ucred->cr_uid;
+
+ /*
+ * The si_addr field would be useful additional detail, but
+ * apparently the PC value may be lost when we reach this
+ * point. bzero() above sets siginfo->si_addr to NULL.
+ */
+}
+
+static void
+wait_fill_wrusage(struct proc *p, struct __wrusage *wrusage)
+{
+ struct rusage *rup;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ if (wrusage == NULL)
+ return;
+
+ rup = &wrusage->wru_self;
+ *rup = p->p_ru;
+ PROC_STATLOCK(p);
+ calcru(p, &rup->ru_utime, &rup->ru_stime);
+ PROC_STATUNLOCK(p);
+
+ rup = &wrusage->wru_children;
+ *rup = p->p_stats->p_cru;
+ calccru(p, &rup->ru_utime, &rup->ru_stime);
+}
+
static int
proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id,
int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo,
int check_only)
{
- struct rusage *rup;
-
sx_assert(&proctree_lock, SA_XLOCKED);
PROC_LOCK(p);
@@ -1114,7 +1203,7 @@
return (0);
}
- if (((options & WEXITED) == 0) && (p->p_state == PRS_ZOMBIE)) {
+ if ((options & WEXITED) == 0 && p->p_state == PRS_ZOMBIE) {
PROC_UNLOCK(p);
return (0);
}
@@ -1133,60 +1222,14 @@
return (0);
}
- if (siginfo != NULL) {
- bzero(siginfo, sizeof(*siginfo));
- siginfo->si_errno = 0;
-
- /*
- * SUSv4 requires that the si_signo value is always
- * SIGCHLD. Obey it despite the rfork(2) interface
- * allows to request other signal for child exit
- * notification.
- */
- siginfo->si_signo = SIGCHLD;
-
- /*
- * This is still a rough estimate. We will fix the
- * cases TRAPPED, STOPPED, and CONTINUED later.
- */
- if (WCOREDUMP(p->p_xsig)) {
- siginfo->si_code = CLD_DUMPED;
- siginfo->si_status = WTERMSIG(p->p_xsig);
- } else if (WIFSIGNALED(p->p_xsig)) {
- siginfo->si_code = CLD_KILLED;
- siginfo->si_status = WTERMSIG(p->p_xsig);
- } else {
- siginfo->si_code = CLD_EXITED;
- siginfo->si_status = p->p_xexit;
- }
-
- siginfo->si_pid = p->p_pid;
- siginfo->si_uid = p->p_ucred->cr_uid;
-
- /*
- * The si_addr field would be useful additional
- * detail, but apparently the PC value may be lost
- * when we reach this point. bzero() above sets
- * siginfo->si_addr to NULL.
- */
- }
+ wait_fill_siginfo(p, siginfo);
/*
* There should be no reason to limit resources usage info to
* exited processes only. A snapshot about any resources used
* by a stopped process may be exactly what is needed.
*/
- if (wrusage != NULL) {
- rup = &wrusage->wru_self;
- *rup = p->p_ru;
- PROC_STATLOCK(p);
- calcru(p, &rup->ru_utime, &rup->ru_stime);
- PROC_STATUNLOCK(p);
-
- rup = &wrusage->wru_children;
- *rup = p->p_stats->p_cru;
- calccru(p, &rup->ru_utime, &rup->ru_stime);
- }
+ wait_fill_wrusage(p, wrusage);
if (p->p_state == PRS_ZOMBIE && !check_only) {
proc_reap(td, p, status, options);
@@ -1267,10 +1310,85 @@
}
if (status != NULL)
*status = cont ? SIGCONT : W_STOPCODE(p->p_xsig);
- td->td_retval[0] = p->p_pid;
PROC_UNLOCK(p);
}
+static int
+wait6_checkopt(int options)
+{
+ /* If we don't know the option, just return. */
+ if ((options & ~(WUNTRACED | WNOHANG | WCONTINUED | WNOWAIT |
+ WEXITED | WTRAPPED | WLINUXCLONE)) != 0)
+ return (EXTERROR(EINVAL, "Unknown options %#jx", options));
+ if ((options & (WEXITED | WUNTRACED | WCONTINUED | WTRAPPED)) == 0) {
+ /*
+ * We will be unable to find any matching processes,
+ * because there are no known events to look for.
+ * Prefer to return error instead of blocking
+ * indefinitely.
+ */
+ return (EXTERROR(EINVAL,
+ "Cannot match processes %#jx", options));
+ }
+ return (0);
+}
+
+/*
+ * Checks and reports status for alive process, according to the
+ * options. Returns true if the process fits one of the requested
+ * options and its status was updated in siginfo.
+ *
+ * If the process was reported (the function result is true), both the
+ * process and proctree locks are unlocked.
+ */
+static bool
+wait6_check_alive(struct thread *td, int options, struct proc *p, int *status,
+ siginfo_t *siginfo)
+{
+ bool report;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ sx_assert(&proctree_lock, SA_XLOCKED);
+
+ if ((options & WTRAPPED) != 0 && (p->p_flag & P_TRACED) != 0) {
+ PROC_SLOCK(p);
+ report = ((p->p_flag & (P_STOPPED_TRACE | P_STOPPED_SIG)) &&
+ p->p_suspcount == p->p_numthreads &&
+ (p->p_flag & P_WAITED) == 0);
+ PROC_SUNLOCK(p);
+ if (report) {
+ CTR4(KTR_PTRACE,
+ "wait: returning trapped pid %d status %#x (xstat %d) xthread %d",
+ p->p_pid, W_STOPCODE(p->p_xsig), p->p_xsig,
+ p->p_xthread != NULL ?
+ p->p_xthread->td_tid : -1);
+ report_alive_proc(td, p, siginfo, status,
+ options, CLD_TRAPPED);
+ return (true);
+ }
+ }
+
+ if ((options & WUNTRACED) != 0 && (p->p_flag & P_STOPPED_SIG) != 0) {
+ PROC_SLOCK(p);
+ report = (p->p_suspcount == p->p_numthreads &&
+ ((p->p_flag & P_WAITED) == 0));
+ PROC_SUNLOCK(p);
+ if (report) {
+ report_alive_proc(td, p, siginfo, status, options,
+ CLD_STOPPED);
+ return (true);
+ }
+ }
+
+ if ((options & WCONTINUED) != 0 && (p->p_flag & P_CONTINUED) != 0) {
+ report_alive_proc(td, p, siginfo, status, options,
+ CLD_CONTINUED);
+ return (true);
+ }
+
+ return (false);
+}
+
int
kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
int options, struct __wrusage *wrusage, siginfo_t *siginfo)
@@ -1278,7 +1396,6 @@
struct proc *p, *q;
pid_t pid;
int error, nfound, ret;
- bool report;
AUDIT_ARG_VALUE((int)idtype); /* XXX - This is likely wrong! */
AUDIT_ARG_PID((pid_t)id); /* XXX - This may be wrong! */
@@ -1293,20 +1410,9 @@
idtype = P_PGID;
}
- /* If we don't know the option, just return. */
- if ((options & ~(WUNTRACED | WNOHANG | WCONTINUED | WNOWAIT |
- WEXITED | WTRAPPED | WLINUXCLONE)) != 0)
- return (EINVAL);
- if ((options & (WEXITED | WUNTRACED | WCONTINUED | WTRAPPED)) == 0) {
- /*
- * We will be unable to find any matching processes,
- * because there are no known events to look for.
- * Prefer to return error instead of blocking
- * indefinitely.
- */
- return (EINVAL);
- }
-
+ error = wait6_checkopt(options);
+ if (error != 0)
+ return (error);
loop:
if (q->p_flag & P_STATCHILD) {
PROC_LOCK(q);
@@ -1342,44 +1448,11 @@
nfound++;
PROC_LOCK_ASSERT(p, MA_OWNED);
- if ((options & WTRAPPED) != 0 &&
- (p->p_flag & P_TRACED) != 0) {
- PROC_SLOCK(p);
- report =
- ((p->p_flag & (P_STOPPED_TRACE | P_STOPPED_SIG)) &&
- p->p_suspcount == p->p_numthreads &&
- (p->p_flag & P_WAITED) == 0);
- PROC_SUNLOCK(p);
- if (report) {
- CTR4(KTR_PTRACE,
- "wait: returning trapped pid %d status %#x "
- "(xstat %d) xthread %d",
- p->p_pid, W_STOPCODE(p->p_xsig), p->p_xsig,
- p->p_xthread != NULL ?
- p->p_xthread->td_tid : -1);
- report_alive_proc(td, p, siginfo, status,
- options, CLD_TRAPPED);
- return (0);
- }
- }
- if ((options & WUNTRACED) != 0 &&
- (p->p_flag & P_STOPPED_SIG) != 0) {
- PROC_SLOCK(p);
- report = (p->p_suspcount == p->p_numthreads &&
- ((p->p_flag & P_WAITED) == 0));
- PROC_SUNLOCK(p);
- if (report) {
- report_alive_proc(td, p, siginfo, status,
- options, CLD_STOPPED);
- return (0);
- }
- }
- if ((options & WCONTINUED) != 0 &&
- (p->p_flag & P_CONTINUED) != 0) {
- report_alive_proc(td, p, siginfo, status, options,
- CLD_CONTINUED);
+ if (wait6_check_alive(td, options, p, status, siginfo)) {
+ td->td_retval[0] = p->p_pid;
return (0);
}
+
PROC_UNLOCK(p);
}
@@ -1412,24 +1485,102 @@
sx_xunlock(&proctree_lock);
return (ECHILD);
}
- if (options & WNOHANG) {
+ if ((options & WNOHANG) != 0) {
sx_xunlock(&proctree_lock);
td->td_retval[0] = 0;
return (0);
}
PROC_LOCK(q);
- if (q->p_flag & P_STATCHILD) {
+ if ((q->p_flag & P_STATCHILD) != 0) {
q->p_flag &= ~P_STATCHILD;
PROC_UNLOCK(q);
goto loop_locked;
}
sx_xunlock(&proctree_lock);
error = msleep(q, &q->p_mtx, PWAIT | PCATCH | PDROP, "wait", 0);
- if (error)
+ if (error != 0)
return (error);
goto loop;
}
+int
+kern_pdwait(struct thread *td, int fd, int *status,
+ int options, struct __wrusage *wrusage, siginfo_t *siginfo)
+{
+ struct proc *p;
+ struct file *fp;
+ struct procdesc *pd;
+ int error;
+
+ AUDIT_ARG_FD(fd);
+ AUDIT_ARG_VALUE(options);
+
+ error = wait6_checkopt(options);
+ if (error != 0)
+ return (error);
+
+ error = fget(td, fd, &cap_pdwait_rights, &fp);
+ if (error != 0)
+ return (error);
+ if (fp->f_type != DTYPE_PROCDESC) {
+ error = EINVAL;
+ goto exit_unlocked;
+ }
+ pd = fp->f_data;
+
+ for (;;) {
+ sx_xlock(&proctree_lock);
+ p = pd->pd_proc;
+ if (p == NULL) {
+ error = ESRCH;
+ goto exit_tree_locked;
+ }
+ PROC_LOCK(p);
+
+ error = p_canwait(td, p);
+ if (error != 0)
+ break;
+ if ((options & WEXITED) == 0 && p->p_state == PRS_ZOMBIE) {
+ error = ESRCH;
+ break;
+ }
+
+ wait_fill_siginfo(p, siginfo);
+ wait_fill_wrusage(p, wrusage);
+
+ if (p->p_state == PRS_ZOMBIE) {
+ proc_reap(td, p, status, options);
+ goto exit_unlocked;
+ }
+
+ if (wait6_check_alive(td, options, p, status, siginfo))
+ goto exit_unlocked;
+
+ if (p->p_state == PRS_ZOMBIE) {
+ if (status != NULL)
+ *status = KW_EXITCODE(p->p_xexit, p->p_xsig);
+ break;
+ }
+ if ((options & WNOHANG) != 0) {
+ error = EWOULDBLOCK;
+ break;
+ }
+
+ PROC_UNLOCK(p);
+ error = sx_sleep(&p->p_procdesc, &proctree_lock,
+ PWAIT | PCATCH | PDROP, "pdwait", 0);
+ if (error != 0)
+ return (error);
+ }
+
+ PROC_UNLOCK(p);
+exit_tree_locked:
+ sx_xunlock(&proctree_lock);
+exit_unlocked:
+ fdrop(fp, td);
+ return (error);
+}
+
void
proc_add_orphan(struct proc *child, struct proc *parent)
{
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -34,20 +34,22 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
#include "opt_ktrace.h"
#include "opt_kstack_pages.h"
-#include <sys/param.h>
+#define EXTERR_CATEGORY EXTERR_CAT_FORK
#include <sys/systm.h>
+#include <sys/acct.h>
#include <sys/bitstring.h>
-#include <sys/sysproto.h>
#include <sys/eventhandler.h>
+#include <sys/exterrvar.h>
#include <sys/fcntl.h>
#include <sys/filedesc.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
+#include <sys/ktr.h>
+#include <sys/ktrace.h>
#include <sys/sysctl.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -60,17 +62,15 @@
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/sched.h>
+#include <sys/sdt.h>
+#include <sys/signalvar.h>
+#include <sys/sx.h>
#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
-#include <sys/acct.h>
-#include <sys/ktr.h>
-#include <sys/ktrace.h>
#include <sys/unistd.h>
-#include <sys/sdt.h>
-#include <sys/sx.h>
-#include <sys/sysent.h>
-#include <sys/signalvar.h>
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -166,10 +166,11 @@
/* Don't allow kernel-only flags. */
if ((uap->flags & RFKERNELONLY) != 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Kernel-only flags %#jx", uap->flags));
/* RFSPAWN must not appear with others */
if ((uap->flags & RFSPAWN) != 0 && uap->flags != RFSPAWN)
- return (EINVAL);
+ return (EXTERROR(EINVAL, "RFSPAWN must be the only flag %#jx",
+ uap->flags));
AUDIT_ARG_FFLAGS(uap->flags);
bzero(&fr, sizeof(fr));
@@ -188,6 +189,61 @@
return (error);
}
+int
+sys_pdrfork(struct thread *td, struct pdrfork_args *uap)
+{
+ struct fork_req fr;
+ struct proc *p;
+ int error, fd, pid;
+
+ bzero(&fr, sizeof(fr));
+ fd = -1;
+
+ AUDIT_ARG_FFLAGS(uap->pdflags);
+ AUDIT_ARG_CMD(uap->rfflags);
+
+ if ((uap->rfflags & (RFSTOPPED | RFHIGHPID)) != 0)
+ return (EXTERROR(EINVAL,
+ "Kernel-only flags %#jx", uap->rfflags));
+
+ /* RFSPAWN must not appear with others */
+ if ((uap->rfflags & RFSPAWN) != 0) {
+ if (uap->rfflags != RFSPAWN)
+ return (EXTERROR(EINVAL,
+ "RFSPAWN must be the only flag %#jx",
+ uap->rfflags));
+ fr.fr_flags = RFFDG | RFPROC | RFPPWAIT | RFMEM | RFPROCDESC;
+ fr.fr_flags2 = FR2_DROPSIG_CAUGHT;
+ } else {
+ if ((uap->rfflags & (RFPROC | RFPROCDESC)) == RFPROCDESC) {
+ error = copyin(uap->fdp, &fd, sizeof(fd));
+ if (error != 0)
+ return (error);
+ error = procdesc_find(td, fd, &cap_pdkill_rights, &p);
+ if (error != 0)
+ return (error);
+ PROC_UNLOCK(p);
+ if (p != curproc)
+ return (EXTERROR(EBUSY, "Target must be me"));
+ pid = curproc->p_pid;
+ }
+ fr.fr_flags = uap->rfflags;
+ }
+
+ fr.fr_pidp = &pid;
+ fr.fr_pd_fd = &fd;
+ fr.fr_pd_flags = uap->pdflags;
+ error = fork1(td, &fr);
+ if (error == 0) {
+ td->td_retval[0] = pid;
+ td->td_retval[1] = 0;
+ if ((fr.fr_flags & (RFPROC | RFPROCDESC)) ==
+ (RFPROC | RFPROCDESC) || uap->rfflags == RFSPAWN)
+ error = copyout(&fd, uap->fdp, sizeof(fd));
+ }
+ return (error);
+}
+
int __exclusive_cache_line nprocs = 1; /* process 0 */
int lastpid = 0;
SYSCTL_INT(_kern, OID_AUTO, lastpid, CTLFLAG_RD, &lastpid, 0,
@@ -871,34 +927,32 @@
else
MPASS(fr->fr_procp == NULL);
- /* Check for the undefined or unimplemented flags. */
if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "Undef or unimplemented flags %#jx", flags));
- /* Signal value requires RFTSIGZMB. */
if ((flags & RFTSIGFLAGS(RFTSIGMASK)) != 0 && (flags & RFTSIGZMB) == 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "Signal value requires RFTSIGZMB", flags));
- /* Can't copy and clear. */
- if ((flags & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
- return (EINVAL);
+ if ((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG))
+ return (EXTERROR(EINVAL, "Can not copy and clear"));
- /* Check the validity of the signal number. */
if ((flags & RFTSIGZMB) != 0 && (u_int)RFTSIGNUM(flags) > _SIG_MAXSIG)
- return (EINVAL);
+ return (EXTERROR(EINVAL, "Invalid signal", RFTSIGNUM(flags)));
if ((flags & RFPROCDESC) != 0) {
- /* Can't not create a process yet get a process descriptor. */
if ((flags & RFPROC) == 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "Can not not create a process yet get a process descriptor"));
- /* Must provide a place to put a procdesc if creating one. */
if (fr->fr_pd_fd == NULL)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "Must provide a place to put a procdesc if creating one"));
- /* Check if we are using supported flags. */
if ((fr->fr_pd_flags & ~PD_ALLOWED_AT_FORK) != 0)
- return (EINVAL);
+ return (EXTERROR(EINVAL,
+ "Invallid pdflags at fork %#jx", fr->fr_pd_flags));
}
p1 = td->td_proc;
diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c
--- a/sys/kern/subr_capability.c
+++ b/sys/kern/subr_capability.c
@@ -90,6 +90,7 @@
const cap_rights_t cap_mknodat_rights = CAP_RIGHTS_INITIALIZER(CAP_MKNODAT);
const cap_rights_t cap_pdgetpid_rights = CAP_RIGHTS_INITIALIZER(CAP_PDGETPID);
const cap_rights_t cap_pdkill_rights = CAP_RIGHTS_INITIALIZER(CAP_PDKILL);
+const cap_rights_t cap_pdwait_rights = CAP_RIGHTS_INITIALIZER(CAP_PDWAIT);
const cap_rights_t cap_pread_rights = CAP_RIGHTS_INITIALIZER(CAP_PREAD);
const cap_rights_t cap_pwrite_rights = CAP_RIGHTS_INITIALIZER(CAP_PWRITE);
const cap_rights_t cap_read_rights = CAP_RIGHTS_INITIALIZER(CAP_READ);
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -75,6 +75,7 @@
#include <sys/procdesc.h>
#include <sys/resourcevar.h>
#include <sys/stat.h>
+#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
@@ -318,6 +319,9 @@
}
KNOTE_LOCKED(&pd->pd_selinfo.si_note, NOTE_EXIT);
PROCDESC_UNLOCK(pd);
+
+ /* Wakeup all waiters for this procdesc' process exit. */
+ wakeup(&p->p_procdesc);
return (0);
}
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -605,4 +605,6 @@
"jail_attach_jd", /* 597 = jail_attach_jd */
"jail_remove_jd", /* 598 = jail_remove_jd */
"kexec_load", /* 599 = kexec_load */
+ "pdrfork", /* 600 = pdrfork */
+ "pdwait", /* 601 = pdwait */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3402,4 +3402,23 @@
u_long flags
);
}
+
+600 AUE_PDRFORK STD|CAPENABLED {
+ int pdrfork(
+ _Out_ int *fdp,
+ int pdflags,
+ int rfflags
+ );
+ }
+
+601 AUE_PDWAIT STD|CAPENABLED {
+ int pdwait(
+ int fd,
+ _Out_opt_ int *status,
+ int options,
+ _Out_opt_ _Contains_long_ struct __wrusage *wrusage,
+ _Out_opt_ _Contains_long_ptr_ struct __siginfo *info
+ );
+ }
+
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3524,6 +3524,26 @@
*n_args = 4;
break;
}
+ /* pdrfork */
+ case 600: {
+ struct pdrfork_args *p = params;
+ uarg[a++] = (intptr_t)p->fdp; /* int * */
+ iarg[a++] = p->pdflags; /* int */
+ iarg[a++] = p->rfflags; /* int */
+ *n_args = 3;
+ break;
+ }
+ /* pdwait */
+ case 601: {
+ struct pdwait_args *p = params;
+ iarg[a++] = p->fd; /* int */
+ uarg[a++] = (intptr_t)p->status; /* int * */
+ iarg[a++] = p->options; /* int */
+ uarg[a++] = (intptr_t)p->wrusage; /* struct __wrusage * */
+ uarg[a++] = (intptr_t)p->info; /* struct __siginfo * */
+ *n_args = 5;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9430,6 +9450,44 @@
break;
};
break;
+ /* pdrfork */
+ case 600:
+ switch (ndx) {
+ case 0:
+ p = "userland int *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* pdwait */
+ case 601:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "userland int *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "userland struct __wrusage *";
+ break;
+ case 4:
+ p = "userland struct __siginfo *";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11443,6 +11501,16 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* pdrfork */
+ case 600:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* pdwait */
+ case 601:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -1115,6 +1115,16 @@
}
break;
+ case AUE_PDWAIT:
+ if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
+ tok = au_to_arg32(1, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FD)) {
+ tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
+ kau_write(rec, tok);
+ }
+
case AUE_IOCTL:
if (ARG_IS_VALID(kar, ARG_CMD)) {
tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd);
@@ -1365,6 +1375,24 @@
kau_write(rec, tok);
}
break;
+ case AUE_PDRFORK:
+ if (ARG_IS_VALID(kar, ARG_PID)) {
+ tok = au_to_arg32(0, "child PID", ar->ar_arg_pid);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_CMD)) {
+ tok = au_to_arg32(2, "fflags", ar->ar_arg_cmd);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
+ tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_FD)) {
+ tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
+ kau_write(rec, tok);
+ }
+ break;
case AUE_PDGETPID:
if (ARG_IS_VALID(kar, ARG_FD)) {
tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
diff --git a/sys/sys/caprights.h b/sys/sys/caprights.h
--- a/sys/sys/caprights.h
+++ b/sys/sys/caprights.h
@@ -92,6 +92,7 @@
extern const cap_rights_t cap_no_rights;
extern const cap_rights_t cap_pdgetpid_rights;
extern const cap_rights_t cap_pdkill_rights;
+extern const cap_rights_t cap_pdwait_rights;
extern const cap_rights_t cap_pread_rights;
extern const cap_rights_t cap_pwrite_rights;
extern const cap_rights_t cap_read_rights;
diff --git a/sys/sys/exterr_cat.h b/sys/sys/exterr_cat.h
--- a/sys/sys/exterr_cat.h
+++ b/sys/sys/exterr_cat.h
@@ -37,6 +37,8 @@
#define EXTERR_CAT_GEOM 12
#define EXTERR_CAT_FUSE_VFS 13
#define EXTERR_CAT_FUSE_DEVICE 14
+#define EXTERR_CAT_FORK 15
+#define EXTERR_CAT_PROCEXIT 16
#endif
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -122,9 +122,14 @@
* Process descriptor system calls.
*/
__BEGIN_DECLS
+struct __wrusage;
+struct __siginfo;
+
pid_t pdfork(int *, int);
+pid_t pdrfork(int *, int, int);
int pdkill(int, int);
int pdgetpid(int, pid_t *);
+pid_t pdwait(int, int, int *, struct __wrusage *, struct __siginfo *);
__END_DECLS
#endif /* _KERNEL */
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -538,4 +538,6 @@
#define SYS_jail_attach_jd 597
#define SYS_jail_remove_jd 598
#define SYS_kexec_load 599
-#define SYS_MAXSYSCALL 600
+#define SYS_pdrfork 600
+#define SYS_pdwait 601
+#define SYS_MAXSYSCALL 602
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -441,4 +441,6 @@
setgroups.o \
jail_attach_jd.o \
jail_remove_jd.o \
- kexec_load.o
+ kexec_load.o \
+ pdrfork.o \
+ pdwait.o
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -286,6 +286,8 @@
off_t len);
int kern_fspacectl(struct thread *td, int fd, int cmd,
const struct spacectl_range *, int flags, struct spacectl_range *);
+int kern_pdwait(struct thread *td, int fd, int *status,
+ int options, struct __wrusage *wrusage, siginfo_t *sip);
int kern_procctl(struct thread *td, enum idtype idtype, id_t id, int com,
void *data);
int kern_pread(struct thread *td, int fd, void *buf, size_t nbyte,
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1913,6 +1913,18 @@
char segments_l_[PADL_(struct kexec_segment *)]; struct kexec_segment * segments; char segments_r_[PADR_(struct kexec_segment *)];
char flags_l_[PADL_(u_long)]; u_long flags; char flags_r_[PADR_(u_long)];
};
+struct pdrfork_args {
+ char fdp_l_[PADL_(int *)]; int * fdp; char fdp_r_[PADR_(int *)];
+ char pdflags_l_[PADL_(int)]; int pdflags; char pdflags_r_[PADR_(int)];
+ char rfflags_l_[PADL_(int)]; int rfflags; char rfflags_r_[PADR_(int)];
+};
+struct pdwait_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char status_l_[PADL_(int *)]; int * status; char status_r_[PADR_(int *)];
+ char options_l_[PADL_(int)]; int options; char options_r_[PADR_(int)];
+ char wrusage_l_[PADL_(struct __wrusage *)]; struct __wrusage * wrusage; char wrusage_r_[PADR_(struct __wrusage *)];
+ char info_l_[PADL_(struct __siginfo *)]; struct __siginfo * info; char info_r_[PADR_(struct __siginfo *)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2320,6 +2332,8 @@
int sys_jail_attach_jd(struct thread *, struct jail_attach_jd_args *);
int sys_jail_remove_jd(struct thread *, struct jail_remove_jd_args *);
int sys_kexec_load(struct thread *, struct kexec_load_args *);
+int sys_pdrfork(struct thread *, struct pdrfork_args *);
+int sys_pdwait(struct thread *, struct pdwait_args *);
#ifdef COMPAT_43
@@ -3319,6 +3333,8 @@
#define SYS_AUE_jail_attach_jd AUE_JAIL_ATTACH
#define SYS_AUE_jail_remove_jd AUE_JAIL_REMOVE
#define SYS_AUE_kexec_load AUE_NULL
+#define SYS_AUE_pdrfork AUE_PDRFORK
+#define SYS_AUE_pdwait AUE_PDWAIT
#undef PAD_
#undef PADL_
diff --git a/tools/build/make_libc_exterr_cat_filenames.sh b/tools/build/make_libc_exterr_cat_filenames.sh
--- a/tools/build/make_libc_exterr_cat_filenames.sh
+++ b/tools/build/make_libc_exterr_cat_filenames.sh
@@ -14,7 +14,7 @@
echo " * tools/build/make_libc_exterr_cat_filenames.sh" >>"${target}"
echo " */" >>"${target}"
-(find sys -type f -name '*.c' | \
+(find sys -type f -name '*.c' | sort | \
xargs grep -E '^#define[[:space:]]+EXTERR_CATEGORY[[:space:]]+EXTERR_CAT_' | \
sed -E 's/[[:space:]]+/:/g' | \
awk -F ':' '{filename = $1; sub(/^sys\//, "", filename);

File Metadata

Mime Type
text/plain
Expires
Mon, Jan 12, 11:28 PM (9 h, 28 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27622419
Default Alt Text
D54592.diff (38 KB)

Event Timeline