Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F141883464
D54592.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
38 KB
Referenced Files
None
Subscribers
None
D54592.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D54592: Add pdrfork(2) and pdwait(2)
Attached
Detach File
Event Timeline
Log In to Comment