xnu-2782.30.5.tar.gz
[apple/xnu.git] / bsd / kern / proc_info.c
index 482f83e0e529f47becd3897cd8a9ad6f3ec91ce7..a2b82a6e4280951e9bb32fad0a7aec1ef2f59fa0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2005-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -56,7 +56,6 @@
 #include <mach/mach_types.h>
 #include <mach/vm_param.h>
 #include <kern/task.h>
-#include <kern/lock.h>
 #include <kern/kalloc.h>
 #include <kern/assert.h>
 #include <vm/vm_kern.h>
@@ -72,8 +71,9 @@
 #include <sys/kdebug.h>
 #include <sys/sysproto.h>
 #include <sys/msgbuf.h>
+#include <sys/priv.h>
 
-#include <sys/msgbuf.h>
+#include <sys/guarded.h>
 
 #include <machine/machine_routines.h>
 
 
 #include <vm/vm_protos.h>
 
+/* Needed by proc_pidnoteexit() */
+#include <sys/event.h>
+#include <sys/codesign.h>
+
 struct pshmnode;
 struct psemnode;
 struct pipe;
@@ -88,57 +92,94 @@ struct kqueue;
 struct atalk;
 
 uint64_t get_dispatchqueue_offset_from_proc(void *);
+uint64_t get_dispatchqueue_serialno_offset_from_proc(void *);
 int proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
 
+/*
+ * TODO: Replace the noinline attribute below.  Currently, it serves
+ * to avoid stack bloat caused by inlining multiple functions that
+ * have large stack footprints; when the functions are independent
+ * of each other (will not both be called in any given call to the
+ * caller), this only serves to bloat the stack, as we allocate
+ * space for both functions, despite the fact that we only need a
+ * fraction of that space.
+ *
+ * Long term, these functions should not be allocating everything on
+ * the stack, and should move large allocations (the huge structs
+ * that proc info deals in) to the heap, or eliminate them if
+ * possible.
+ *
+ * The functions that most desperately need to improve stack usage
+ * (starting with the worst offenders):
+ *   proc_pidvnodepathinfo
+ *   proc_pidinfo
+ *   proc_pidregionpathinfo
+ *   pid_vnodeinfopath
+ *   pid_pshminfo
+ *   pid_pseminfo
+ *   pid_socketinfo
+ *   proc_pid_rusage
+ *   proc_pidoriginatorinfo
+ */
+
 /* protos for proc_info calls */
-int proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
-int proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
-int proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
-int proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval);
-int proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
-int proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t * retval);
-int proc_terminate(int pid, int32_t * retval);
+int __attribute__ ((noinline)) proc_listpids(uint32_t type, uint32_t tyoneinfo, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) proc_pidfdinfo(int pid, int flavor,int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) proc_kernmsgbuf(user_addr_t buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t * retval);
+int __attribute__ ((noinline)) proc_terminate(int pid, int32_t * retval);
+int __attribute__ ((noinline)) proc_pid_rusage(int pid, int flavor, user_addr_t buffer, int32_t * retval);
+int __attribute__ ((noinline)) proc_pidoriginatorinfo(int pid, int flavor, user_addr_t buffer, uint32_t buffersize, int32_t * retval);
 
 /* protos for procpidinfo calls */
-int proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd, int zombie);
-int proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo *pbsd_shortp, int zombie);
-int proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
-int proc_pidallinfo(proc_t p, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_pidthreadinfo(proc_t p, uint64_t arg,  int thuniqueid, struct proc_threadinfo *pthinfo);
-int proc_pidthreadpathinfo(proc_t p, uint64_t arg,  struct proc_threadwithpathinfo *pinfo);
-int proc_pidlistthreads(proc_t p,  user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_pidregionpathinfo(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_pidvnodepathinfo(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
-int proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo);
-int proc_pidfileportlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidbsdinfo(proc_t p, struct proc_bsdinfo *pbsd, int zombie);
+int __attribute__ ((noinline)) proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo *pbsd_shortp, int zombie);
+int __attribute__ ((noinline)) proc_pidtaskinfo(proc_t p, struct proc_taskinfo *ptinfo);
+int __attribute__ ((noinline)) proc_pidthreadinfo(proc_t p, uint64_t arg,  int thuniqueid, struct proc_threadinfo *pthinfo);
+int __attribute__ ((noinline)) proc_pidthreadpathinfo(proc_t p, uint64_t arg,  struct proc_threadwithpathinfo *pinfo);
+int __attribute__ ((noinline)) proc_pidlistthreads(proc_t p,  user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidregioninfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidregionpathinfo(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidregionpathinfo2(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidregionpathinfo3(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidvnodepathinfo(proc_t p,  uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+int __attribute__ ((noinline)) proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo);
+int __attribute__ ((noinline)) proc_pidfileportlist(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval);
+void __attribute__ ((noinline)) proc_piduniqidentifierinfo(proc_t p, struct proc_uniqidentifierinfo *p_uniqidinfo);
+void __attribute__ ((noinline)) proc_archinfo(proc_t p, struct proc_archinfo *pai);
+void __attribute__ ((noinline)) proc_pidcoalitioninfo(proc_t p, struct proc_pidcoalitioninfo *pci);
+int __attribute__ ((noinline)) proc_pidnoteexit(proc_t p, uint64_t arg,  uint32_t *data);
 
 
 /* protos for proc_pidfdinfo calls */
-int pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
-int pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
-int pid_socketinfo(socket_t  so, struct fileproc *fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
-int pid_pseminfo(struct psemnode * psem, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
-int pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
-int pid_pipeinfo(struct pipe * p, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
-int pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
-int pid_atalkinfo(struct atalk  * at, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_socketinfo(socket_t  so, struct fileproc *fp, int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_pseminfo(struct psemnode * psem, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_pshminfo(struct pshmnode * pshm, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_pipeinfo(struct pipe * p, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_kqueueinfo(struct kqueue * kq, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
+int __attribute__ ((noinline)) pid_atalkinfo(struct atalk  * at, struct fileproc * fp,  int closeonexec, user_addr_t  buffer, uint32_t buffersize, int32_t * retval);
 
 
 /* protos for misc */
 
-void proc_dirty_start(struct proc *p);
-void proc_dirty_end(struct proc *p);
-
 int fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo);
 void  fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * finfo);
-static int proc_security_policy(proc_t p);
+int proc_security_policy(proc_t targetp, int callnum, int flavor, boolean_t check_same_user);
 static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp);
+static int proc_piduuidinfo(pid_t pid, uuid_t uuid_buf, uint32_t buffersize);
 
 extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int, int);
+extern int proc_get_rusage(proc_t proc, int flavor, user_addr_t buffer, int is_zombie);
+
+#define CHECK_SAME_USER         TRUE
+#define NO_CHECK_SAME_USER      FALSE
 
 uint64_t get_dispatchqueue_offset_from_proc(void *p)
 {
@@ -150,6 +191,16 @@ uint64_t get_dispatchqueue_offset_from_proc(void *p)
        }
 }
 
+uint64_t get_dispatchqueue_serialno_offset_from_proc(void *p)
+{
+       if(p != NULL) {
+               proc_t pself = (proc_t)p;
+               return (pself->p_dispatchqueue_serialno_offset);
+       } else {
+               return (uint64_t)0;
+       }
+}
+
 /***************************** proc_info ********************/
 
 int
@@ -164,23 +215,27 @@ proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t b
 {
 
        switch(callnum) {
-               case 1: /* proc_listpids */
+               case PROC_INFO_CALL_LISTPIDS:
                        /* pid contains type and flavor contains typeinfo */
                        return(proc_listpids(pid, flavor, buffer, buffersize, retval));
-               case 2: /* proc_pidinfo */
+               case PROC_INFO_CALL_PIDINFO:
                        return(proc_pidinfo(pid, flavor, arg, buffer, buffersize, retval));
-               case 3: /* proc_pidfdinfo */
+               case PROC_INFO_CALL_PIDFDINFO:
                        return(proc_pidfdinfo(pid, flavor, (int)arg, buffer, buffersize, retval));
-               case 4: /* proc_kernmsgbuf */
+               case PROC_INFO_CALL_KERNMSGBUF:
                        return(proc_kernmsgbuf(buffer, buffersize, retval));
-               case 5: /* set on self properties  proc_setcontrol */
+               case PROC_INFO_CALL_SETCONTROL:
                        return(proc_setcontrol(pid, flavor, arg, buffer, buffersize, retval));
-               case 6: /* proc_pidfileportinfo */
+               case PROC_INFO_CALL_PIDFILEPORTINFO:
                        return(proc_pidfileportinfo(pid, flavor, (mach_port_name_t)arg, buffer, buffersize, retval));
-               case 7: /* proc_terminate */
+               case PROC_INFO_CALL_TERMINATE:
                        return(proc_terminate(pid, retval));
-               case 8: /* proc_dirtycontrol */
+               case PROC_INFO_CALL_DIRTYCONTROL:
                        return(proc_dirtycontrol(pid, flavor, arg, retval));
+               case PROC_INFO_CALL_PIDRUSAGE:
+                       return (proc_pid_rusage(pid, flavor, buffer, retval));
+               case PROC_INFO_CALL_PIDORIGINATORINFO:
+                       return (proc_pidoriginatorinfo(pid, flavor, buffer, buffersize, retval));
                default:
                                return(EINVAL);
        }
@@ -201,6 +256,10 @@ proc_listpids(uint32_t type, uint32_t typeinfo, user_addr_t buffer, uint32_t  bu
        int error = 0;
        struct proclist *current_list;
 
+       /* Do we have permission to look into this? */
+       if ((error = proc_security_policy(PROC_NULL, PROC_INFO_CALL_LISTPIDS, type, NO_CHECK_SAME_USER)))
+               return (error);
+
        /* if the buffer is null, return num of procs */
        if (buffer == (user_addr_t)0) {
                *retval = ((nprocs+20) * sizeof(int));
@@ -308,7 +367,7 @@ proc_loop:
 }
 
 
-/********************************** proc_pidinfo routines ********************************/
+/********************************** proc_pidfdlist routines ********************************/
 
 int 
 proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t  buffersize, int32_t *retval)
@@ -347,8 +406,10 @@ proc_pidfdlist(proc_t p, user_addr_t buffer, uint32_t  buffersize, int32_t *retv
                for (n = 0; ((n < numfds) && (n < p->p_fd->fd_nfiles)); n++) {
                        if (((fp = p->p_fd->fd_ofiles[n]) != 0) 
                             && ((p->p_fd->fd_ofileflags[n] & UF_RESERVED) == 0)) {
+                               file_type_t fdtype = FILEGLOB_DTYPE(fp->f_fglob);
                                pfd->proc_fd = n;
-                               pfd->proc_fdtype = fp->f_fglob->fg_type;        
+                               pfd->proc_fdtype = (fdtype != DTYPE_ATALK) ?
+                                       fdtype : PROX_FDTYPE_ATALK;
                                count++;
                                pfd++;
                        }
@@ -386,7 +447,10 @@ proc_fileport_fdtype(mach_port_name_t name, struct fileglob *fg, void *arg)
        struct fileport_fdtype_args *ffa = arg;
 
        if (ffa->ffa_pfi != ffa->ffa_pfi_end) {
-               ffa->ffa_pfi->proc_fdtype = fg->fg_type;
+               file_type_t fdtype = FILEGLOB_DTYPE(fg);
+
+               ffa->ffa_pfi->proc_fdtype = (fdtype != DTYPE_ATALK) ?
+                       fdtype : PROX_FDTYPE_ATALK;
                ffa->ffa_pfi->proc_fileport = name;
                ffa->ffa_pfi++;
                return (0);             /* keep walking */
@@ -536,10 +600,8 @@ proc_pidbsdinfo(proc_t p, struct proc_bsdinfo * pbsd, int zombie)
                        pbsd->pbi_flags |= PROC_FLAG_CTTY;
        }
 
-#if !CONFIG_EMBEDDED
        if ((p->p_flag & P_DELAYIDLESLEEP) == P_DELAYIDLESLEEP) 
                pbsd->pbi_flags |= PROC_FLAG_DELAYIDLESLEEP;
-#endif /* !CONFIG_EMBEDDED */
 
        switch(PROC_CONTROL_STATE(p)) {
                case P_PCTHROTTLE:
@@ -617,10 +679,8 @@ proc_pidshortbsdinfo(proc_t p, struct proc_bsdshortinfo * pbsd_shortp, int zombi
                pbsd_shortp->pbsi_flags |= PROC_FLAG_PSUGID;
        if ((p->p_flag & P_EXEC) == P_EXEC) 
                pbsd_shortp->pbsi_flags |= PROC_FLAG_EXEC;
-#if !CONFIG_EMBEDDED
        if ((p->p_flag & P_DELAYIDLESLEEP) == P_DELAYIDLESLEEP) 
                pbsd_shortp->pbsi_flags |= PROC_FLAG_DELAYIDLESLEEP;
-#endif /* !CONFIG_EMBEDDED */
 
        switch(PROC_CONTROL_STATE(p)) {
                case P_PCTHROTTLE:
@@ -827,6 +887,105 @@ proc_pidregionpathinfo(proc_t p, uint64_t arg, user_addr_t buffer, __unused uint
        return(error);
 }
 
+int
+proc_pidregionpathinfo2(proc_t p,  uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
+{
+       struct proc_regionwithpathinfo preginfo;
+       int ret, error = 0;
+       uintptr_t vnodeaddr= 0;
+       uint32_t vnodeid= 0;
+       vnode_t vp;
+       int count;
+
+       bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
+
+       ret = fill_procregioninfo_onlymappedvnodes( p->task, arg, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
+       if (ret == 0)
+               return(EINVAL);
+       if (!vnodeaddr)
+               return(EINVAL);
+
+       vp = (vnode_t)vnodeaddr;
+       if ((vnode_getwithvid(vp, vnodeid)) == 0) {
+               /* FILL THE VNODEINFO */
+               error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
+               count = MAXPATHLEN;
+               vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
+               /* Always make sure it is null terminated */
+               preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
+               vnode_put(vp);
+       } else {
+               return(EINVAL);
+       }
+
+       error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
+       if (error == 0)
+               *retval = sizeof(struct proc_regionwithpathinfo);
+       return(error);
+}
+
+int
+proc_pidregionpathinfo3(proc_t p,  uint64_t arg, user_addr_t buffer, __unused uint32_t buffersize, int32_t *retval)
+{
+       struct proc_regionwithpathinfo preginfo;
+       int ret, error = 0;
+       uintptr_t vnodeaddr;
+       uint32_t vnodeid;
+       vnode_t vp;
+       int count;
+       uint64_t addr = 0;
+
+       /* Loop while looking for vnodes that match dev_t filter */
+       do {
+               bzero(&preginfo, sizeof(struct proc_regionwithpathinfo));
+               vnodeaddr = 0;
+               vnodeid = 0;
+
+               ret = fill_procregioninfo_onlymappedvnodes( p->task, addr, (struct proc_regioninfo_internal *)&preginfo.prp_prinfo, (uintptr_t *)&vnodeaddr, (uint32_t *)&vnodeid);
+               if (ret == 0)
+                       return(EINVAL);
+               if (!vnodeaddr)
+                       return(EINVAL);
+
+               vp = (vnode_t)vnodeaddr;
+               if ((vnode_getwithvid(vp, vnodeid)) == 0) {
+                       /* Check if the vnode matches the filter, otherwise loop looking for the next memory region backed by a vnode */
+                       struct vnode_attr va;
+                       
+                       memset(&va, 0, sizeof(va));
+                       VATTR_INIT(&va);
+                       VATTR_WANTED(&va, va_fsid);
+
+                       ret = vnode_getattr(vp, &va, vfs_context_current());
+                       if (ret) {
+                               vnode_put(vp);
+                               return(EINVAL);
+                       }
+
+                       if (va.va_fsid == arg) {
+                               /* FILL THE VNODEINFO */
+                               error = fill_vnodeinfo(vp, &preginfo.prp_vip.vip_vi);
+                               count = MAXPATHLEN;
+                               vn_getpath(vp, &preginfo.prp_vip.vip_path[0], &count);
+                               /* Always make sure it is null terminated */
+                               preginfo.prp_vip.vip_path[MAXPATHLEN-1] = 0;
+                               vnode_put(vp);
+                               break;
+                       }
+                       vnode_put(vp);
+               } else {
+                       return(EINVAL);
+               }
+
+               addr = preginfo.prp_prinfo.pri_address + preginfo.prp_prinfo.pri_size;
+       } while (1);
+
+       error = copyout(&preginfo, buffer, sizeof(struct proc_regionwithpathinfo));
+       if (error == 0)
+               *retval = sizeof(struct proc_regionwithpathinfo);
+       return(error);
+}
+
 /*
  * Path is relative to current process directory; may different from current
  * thread directory.
@@ -945,6 +1104,135 @@ proc_pidworkqueueinfo(proc_t p, struct proc_workqueueinfo *pwqinfo)
                return(0);
 
 }
+
+
+void
+proc_piduniqidentifierinfo(proc_t p, struct proc_uniqidentifierinfo *p_uniqidinfo)
+{
+       p_uniqidinfo->p_uniqueid = proc_uniqueid(p);
+       proc_getexecutableuuid(p, (unsigned char *)&p_uniqidinfo->p_uuid, sizeof(p_uniqidinfo->p_uuid));
+       p_uniqidinfo->p_puniqueid = proc_puniqueid(p);
+       p_uniqidinfo->p_reserve2 = 0;
+       p_uniqidinfo->p_reserve3 = 0;
+       p_uniqidinfo->p_reserve4 = 0;
+}
+
+
+static int
+proc_piduuidinfo(pid_t pid, uuid_t uuid_buf, uint32_t buffersize)
+{
+       struct proc * p = PROC_NULL;
+       int zombref = 0;
+
+       if (buffersize < sizeof(uuid_t))
+               return EINVAL;
+
+       if ((p = proc_find(pid)) == PROC_NULL) {
+               p = proc_find_zombref(pid);
+               zombref = 1;
+       }
+       if (p == PROC_NULL) {
+               return ESRCH;
+       }
+
+       proc_getexecutableuuid(p, (unsigned char *)uuid_buf, buffersize);
+
+       if (zombref)
+               proc_drop_zombref(p);
+       else
+               proc_rele(p);
+
+       return 0;
+}
+
+/*
+ * Function to get the uuid of the originator of the voucher.
+ */
+int
+proc_pidoriginatoruuid(uuid_t uuid, uint32_t buffersize)
+{
+       pid_t originator_pid;
+       kern_return_t kr;
+       int error;
+
+       /* 
+        * Get the current voucher origin pid. The pid returned here 
+        * might not be valid or may have been recycled.
+        */
+       kr = thread_get_current_voucher_origin_pid(&originator_pid);
+       /* If errors, convert errors to appropriate format */
+       if (kr) {
+               if (kr == KERN_INVALID_TASK)
+                       error = ESRCH;
+               else if (kr == KERN_INVALID_VALUE)
+                       error = ENOATTR;
+               else
+                       error = EINVAL;
+               return error;
+       }
+
+       error = proc_piduuidinfo(originator_pid, uuid, buffersize);
+       return error;
+}
+
+/***************************** proc_pidoriginatorinfo ***************************/
+
+int
+proc_pidoriginatorinfo(int pid, int flavor, user_addr_t buffer, uint32_t  buffersize, int32_t * retval)
+{
+       int error = ENOTSUP;
+       uint32_t size;
+
+       switch (flavor) {
+               case PROC_PIDORIGINATOR_UUID:
+                       size = PROC_PIDORIGINATOR_UUID_SIZE;
+                       break;
+               case PROC_PIDORIGINATOR_BGSTATE:
+                       size = PROC_PIDORIGINATOR_BGSTATE_SIZE;
+                       break;
+               default:
+                       return(EINVAL);
+       }
+
+       if (buffersize < size) 
+               return(ENOMEM);
+
+       if (pid != 0 && pid != proc_selfpid())
+               return (EINVAL);
+
+       switch (flavor) {
+               case PROC_PIDORIGINATOR_UUID: {
+                       uuid_t uuid;
+
+                       error = proc_pidoriginatoruuid(uuid, sizeof(uuid));
+                       if (error != 0)
+                               goto out;
+
+                       error = copyout(uuid, buffer, size);
+                       if (error == 0)
+                               *retval = size;
+               }
+               break;
+
+               case PROC_PIDORIGINATOR_BGSTATE: {
+                       uint32_t is_backgrounded;
+                       error = proc_get_originatorbgstate(&is_backgrounded);
+                       if (error)
+                               goto out;
+
+                       error = copyout(&is_backgrounded, buffer, size);
+                       if (error == 0)
+                               *retval = size;
+               }
+               break;
+
+               default:
+                       error = ENOTSUP;
+       }
+out:
+       return error;
+}
+
 /********************************** proc_pidinfo ********************************/
 
 
@@ -955,10 +1243,12 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t  bu
        int error = ENOTSUP;
        int gotref = 0;
        int findzomb = 0;
-       int refheld = 0, shortversion = 0;
+       int shortversion = 0;
        uint32_t size;
        int zombie = 0;
        int thuniqueid = 0;
+       int uniqidversion = 0;
+       boolean_t check_same_user;
 
        switch (flavor) {
                case PROC_PIDLISTFDS:
@@ -1014,6 +1304,32 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t  bu
                case PROC_PIDTHREADID64INFO:
                        size = PROC_PIDTHREADID64INFO_SIZE;
                        break;
+               case PROC_PIDUNIQIDENTIFIERINFO:
+                       size = PROC_PIDUNIQIDENTIFIERINFO_SIZE;
+                       break;
+               case PROC_PIDT_BSDINFOWITHUNIQID:
+                       size = PROC_PIDT_BSDINFOWITHUNIQID_SIZE;
+                       break;
+               case PROC_PIDARCHINFO:
+                       size = PROC_PIDARCHINFO_SIZE;
+                       break;
+               case PROC_PIDCOALITIONINFO:
+                       size = PROC_PIDCOALITIONINFO_SIZE;
+                       break;
+               case PROC_PIDNOTEEXIT:
+                       /* 
+                        * Set findzomb explicitly because arg passed
+                        * in is used as note exit status bits.
+                        */
+                       size = PROC_PIDNOTEEXIT_SIZE;
+                       findzomb = 1;
+                       break;
+               case PROC_PIDREGIONPATHINFO2:
+                       size = PROC_PIDREGIONPATHINFO2_SIZE;
+                       break;
+               case PROC_PIDREGIONPATHINFO3:
+                       size = PROC_PIDREGIONPATHINFO3_SIZE;
+                       break;
                default:
                        return(EINVAL);
        }
@@ -1025,72 +1341,88 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t  bu
                return(EOVERFLOW);
        }
 
-       if ((flavor != PROC_PIDTBSDINFO) && (flavor != PROC_PIDPATHINFO) && (flavor != PROC_PIDT_SHORTBSDINFO)) {
-               if ((p = proc_find(pid)) == PROC_NULL) {
-                               error = ESRCH;
-                               goto out;
-                       } else {
-                               gotref = 1;
+       /* Check if we need to look for zombies */
+       if ((flavor == PROC_PIDTBSDINFO) || (flavor == PROC_PIDT_SHORTBSDINFO) || (flavor == PROC_PIDT_BSDINFOWITHUNIQID) 
+           || (flavor == PROC_PIDUNIQIDENTIFIERINFO)) {
+               if (arg)
+                       findzomb = 1;
+       }
 
-                               /* Do we have permission to look into this ? */
-                               if ((error = proc_security_policy(p)) != 0) {
-                                       goto out;
-                               }
-                       }
+       if ((p = proc_find(pid)) == PROC_NULL) {
+               if (findzomb)
+                       p = proc_find_zombref(pid);
+               if (p == PROC_NULL) {
+                       error = ESRCH;
+                       goto out;
+               }
+               zombie = 1;
+       } else {
+               gotref = 1;
        }
+
+       /* Certain operations don't require privileges */
+       switch (flavor) {
+               case PROC_PIDT_SHORTBSDINFO:
+               case PROC_PIDUNIQIDENTIFIERINFO:
+               case PROC_PIDPATHINFO:
+                       check_same_user = NO_CHECK_SAME_USER;
+                       break;
+               default:
+                       check_same_user = CHECK_SAME_USER;
+                       break;
+       }
+
+       /* Do we have permission to look into this? */
+       if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDINFO, flavor, check_same_user)))
+               goto out;
+
        switch (flavor) {
                case PROC_PIDLISTFDS: {
                        error = proc_pidfdlist(p, buffer, buffersize, retval);
                }
                break;
 
+               case PROC_PIDUNIQIDENTIFIERINFO: {
+                       struct proc_uniqidentifierinfo p_uniqidinfo;
+
+                       proc_piduniqidentifierinfo(p, &p_uniqidinfo);
+                       error = copyout(&p_uniqidinfo, buffer, sizeof(struct proc_uniqidentifierinfo));
+                       if (error == 0)
+                               *retval = sizeof(struct proc_uniqidentifierinfo);
+               }
+               break;
+
                case PROC_PIDT_SHORTBSDINFO:
                        shortversion = 1;
+               case PROC_PIDT_BSDINFOWITHUNIQID: 
                case PROC_PIDTBSDINFO: {
                        struct proc_bsdinfo pbsd;
                        struct proc_bsdshortinfo pbsd_short;
-
-                       zombie = 0;
-                       if (arg)
-                               findzomb = 1;
-                       p = proc_find(pid);
-                       if (p == PROC_NULL) {
-                               if (findzomb)  
-                                       p = proc_find_zombref(pid);
-                               if (p == NULL) {
-                                       error = ESRCH;
-                                       goto out;       
-                               }
-                               zombie = 1;
-                       }  
-                       refheld = 1;
-                       /* Do we have permission to look into this ? */
-                       if ((flavor != PROC_PIDT_SHORTBSDINFO) && ((error = proc_security_policy(p)) != 0)) {
-                               if (refheld != 0) {
-                                       if (zombie != 0)
-                                               proc_drop_zombref(p);
-                                       else
-                                               proc_rele(p);
-                               }
-                               goto out;
-                       }
+                       struct proc_bsdinfowithuniqid pbsd_uniqid;
+               
+                       if (flavor == PROC_PIDT_BSDINFOWITHUNIQID)
+                               uniqidversion = 1;
+                       
                        if (shortversion != 0) {
                                error = proc_pidshortbsdinfo(p, &pbsd_short, zombie);
                        } else {
                                error = proc_pidbsdinfo(p, &pbsd, zombie);
+                               if (uniqidversion != 0) { 
+                                       proc_piduniqidentifierinfo(p, &pbsd_uniqid.p_uniqidentifier);
+                                       pbsd_uniqid.pbsd = pbsd;
+                               }
                        }
-                       if (refheld != 0) {
-                               if (zombie != 0)
-                                       proc_drop_zombref(p);
-                               else
-                                       proc_rele(p);
-                       }
+                       
                        if (error == 0) {
                                if (shortversion != 0) {
                                        error = copyout(&pbsd_short, buffer, sizeof(struct proc_bsdshortinfo));
                                        if (error == 0)
                                                *retval = sizeof(struct proc_bsdshortinfo);
-                                } else {
+                                } else if (uniqidversion != 0) {
+                                       error = copyout(&pbsd_uniqid, buffer, sizeof(struct proc_bsdinfowithuniqid));
+                                       if (error == 0)
+                                               *retval = sizeof(struct proc_bsdinfowithuniqid);
+                               } else {
                                        error = copyout(&pbsd, buffer, sizeof(struct proc_bsdinfo));
                                        if (error == 0)
                                                *retval = sizeof(struct proc_bsdinfo);
@@ -1154,6 +1486,16 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t  bu
                }
                break;
 
+               case PROC_PIDREGIONPATHINFO2:{
+                       error =  proc_pidregionpathinfo2(p, arg, buffer, buffersize, retval);
+               }
+               break;
+
+               case PROC_PIDREGIONPATHINFO3:{
+                       error =  proc_pidregionpathinfo3(p, arg, buffer, buffersize, retval);
+               }
+               break;
+
                case PROC_PIDVNODEPATHINFO:{
                        error =  proc_pidvnodepathinfo(p, arg, buffer, buffersize, retval);
                }
@@ -1173,12 +1515,6 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t  bu
                break;
 
                case PROC_PIDPATHINFO: {
-                       p = proc_find(pid);
-                       if (p == PROC_NULL) {
-                               error = ESRCH;
-                               goto out;
-                       }
-                       gotref = 1;
                        error =  proc_pidpathinfo(p, arg, buffer, buffersize, retval);
                }
                break;
@@ -1202,6 +1538,37 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t  bu
                }
                break;
 
+               case PROC_PIDARCHINFO: {        
+                       struct proc_archinfo pai;
+                       proc_archinfo(p, &pai);
+                       error = copyout(&pai, buffer, sizeof(struct proc_archinfo));
+                       if (error == 0) {
+                               *retval = sizeof(struct proc_archinfo);
+                       }
+               }
+
+               case PROC_PIDCOALITIONINFO: {
+                       struct proc_pidcoalitioninfo pci;
+                       proc_pidcoalitioninfo(p, &pci);
+                       error = copyout(&pci, buffer, sizeof(struct proc_pidcoalitioninfo));
+                       if (error == 0) {
+                               *retval = sizeof(struct proc_pidcoalitioninfo);
+                       }
+               }
+               break;
+
+               case PROC_PIDNOTEEXIT: {
+                       uint32_t data;
+                       error = proc_pidnoteexit(p, arg, &data);
+                       if (error == 0) {
+                               error = copyout(&data, buffer, sizeof(data));
+                               if (error == 0) {
+                                       *retval = sizeof(data);
+                               }
+                       }
+               }
+               break;
+
                default:
                        error = ENOTSUP;
        }
@@ -1209,6 +1576,8 @@ proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t  bu
 out:
        if (gotref)
                proc_rele(p);
+       else if (zombie)
+               proc_drop_zombref(p);
        return(error);
 }
 
@@ -1262,14 +1631,27 @@ pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp, int closeonexe
 void  
 fill_fileinfo(struct fileproc * fp, int closeonexec, struct proc_fileinfo * fproc)
 {
-               fproc->fi_openflags = fp->f_fglob->fg_flag;
-               fproc->fi_status = 0;
-               fproc->fi_offset = fp->f_fglob->fg_offset;
-               fproc->fi_type = fp->f_fglob->fg_type;
-               if (fp->f_fglob->fg_count)
-                       fproc->fi_status |= PROC_FP_SHARED;
-               if (closeonexec != 0)
-                       fproc->fi_status |= PROC_FP_CLEXEC;
+       fproc->fi_openflags = fp->f_fglob->fg_flag;
+       fproc->fi_status = 0;
+       fproc->fi_offset = fp->f_fglob->fg_offset;
+       fproc->fi_type = FILEGLOB_DTYPE(fp->f_fglob);
+       if (fp->f_fglob->fg_count > 1)
+               fproc->fi_status |= PROC_FP_SHARED;
+       if (closeonexec != 0)
+               fproc->fi_status |= PROC_FP_CLEXEC;
+
+       if (FILEPROC_TYPE(fp) == FTYPE_GUARDED) {
+               fproc->fi_status |= PROC_FP_GUARDED;
+               fproc->fi_guardflags = 0;
+               if (fp_isguarded(fp, GUARD_CLOSE))
+                       fproc->fi_guardflags |= PROC_FI_GUARD_CLOSE;
+               if (fp_isguarded(fp, GUARD_DUP))
+                       fproc->fi_guardflags |= PROC_FI_GUARD_DUP;
+               if (fp_isguarded(fp, GUARD_SOCKET_IPC))
+                       fproc->fi_guardflags |= PROC_FI_GUARD_SOCKET_IPC;
+               if (fp_isguarded(fp, GUARD_FILEPORT))
+                       fproc->fi_guardflags |= PROC_FI_GUARD_FILEPORT;
+       }
 }
 
 
@@ -1281,6 +1663,7 @@ fill_vnodeinfo(vnode_t vp, struct vnode_info *vinfo)
                struct stat64 sb;
                int error = 0;
 
+               bzero(&sb, sizeof(struct stat64));
                context = vfs_context_create((vfs_context_t)0);
                error = vn_stat(vp, &sb, NULL, 1, context);
                (void)vfs_context_rele(context);
@@ -1316,6 +1699,7 @@ pid_socketinfo(socket_t so, struct fileproc *fp, int closeonexec, user_addr_t  b
        }
        return (error);
 #else
+#pragma unused(so, fp, closeonexec, buffer)
        *retval = 0;
        return (ENOTSUP);
 #endif
@@ -1445,10 +1829,10 @@ proc_pidfdinfo(int pid, int flavor,  int fd, user_addr_t buffer, uint32_t buffer
                error = ESRCH;
                goto out;
        }
-       /* Do we have permission to look into this ? */
-       if ((error = proc_security_policy(p)) != 0) {
+
+       /* Do we have permission to look into this? */
+       if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDFDINFO, flavor, CHECK_SAME_USER)))
                goto out1;
-       }
 
        switch (flavor) {
                case PROC_PIDFDVNODEINFO: {
@@ -1538,20 +1922,6 @@ proc_pidfdinfo(int pid, int flavor,  int fd, user_addr_t buffer, uint32_t buffer
                }
                break;
 
-#if NETAT
-               case PROC_PIDFDATALKINFO: {
-                       struct atalk * at;
-
-                       if ((error = fp_getfatalk(p, fd, &fp,  &at)) !=0) {
-                               goto out1;
-                       }
-
-                       /* no need to be under the fdlock */
-                       closeonexec = p->p_fd->fd_ofileflags[fd] & UF_EXCLOSE;
-                       error =  pid_atalkinfo(at, fp, closeonexec, buffer, buffersize, retval);
-               }
-               break;
-#endif /* NETAT */
                default: {
                        error = EINVAL;
                        goto out1;
@@ -1591,7 +1961,7 @@ proc_fileport_info(__unused mach_port_name_t name,
        case PROC_PIDFILEPORTVNODEPATHINFO: {
                vnode_t vp;
 
-               if (fg->fg_type != DTYPE_VNODE) {
+               if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE) {
                        error = ENOTSUP;
                        break;
                }
@@ -1603,7 +1973,7 @@ proc_fileport_info(__unused mach_port_name_t name,
        case PROC_PIDFILEPORTSOCKETINFO: {
                socket_t so;
 
-               if (fg->fg_type != DTYPE_SOCKET) {
+               if (FILEGLOB_DTYPE(fg) != DTYPE_SOCKET) {
                        error = EOPNOTSUPP;
                        break;
                }
@@ -1615,7 +1985,7 @@ proc_fileport_info(__unused mach_port_name_t name,
        case PROC_PIDFILEPORTPSHMINFO: {
                struct pshmnode *pshm;
 
-               if (fg->fg_type != DTYPE_PSXSHM) {
+               if (FILEGLOB_DTYPE(fg) != DTYPE_PSXSHM) {
                        error = EBADF;          /* ick - mirror fp_getfpshm */
                        break;
                }
@@ -1627,7 +1997,7 @@ proc_fileport_info(__unused mach_port_name_t name,
        case PROC_PIDFILEPORTPIPEINFO: {
                struct pipe *cpipe;
 
-               if (fg->fg_type != DTYPE_PIPE) {
+               if (FILEGLOB_DTYPE(fg) != DTYPE_PIPE) {
                        error = EBADF;          /* ick - mirror fp_getfpipe */
                        break;
                }
@@ -1679,9 +2049,10 @@ proc_pidfileportinfo(int pid, int flavor, mach_port_name_t name,
                error = ESRCH;
                goto out;
        }
-       if ((error = proc_security_policy(p)) != 0) {
+
+       /* Do we have permission to look into this? */
+       if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDFILEPORTINFO, flavor, CHECK_SAME_USER)))
                goto out1;
-       }
 
        fia.fia_flavor = flavor;
        fia.fia_buffer = buffer;
@@ -1697,20 +2068,40 @@ out:
        return (error);
 }
 
-static int
-proc_security_policy(proc_t p)
+int
+proc_security_policy(proc_t targetp, __unused int callnum, __unused int flavor, boolean_t check_same_user)
 {
-       kauth_cred_t my_cred;
-       uid_t uid;
+#if CONFIG_MACF
+       int error = 0;
 
-       my_cred = kauth_cred_proc_ref(p);
-       uid = kauth_cred_getuid(my_cred) ;
-       kauth_cred_unref(&my_cred);
-       
-       if ((uid != kauth_cred_getuid(kauth_cred_get())) 
-               && suser(kauth_cred_get(), (u_short *)0)) {
+       if ((error = mac_proc_check_proc_info(current_proc(), targetp, callnum, flavor)))
+               return (error);
+#endif
+
+       /* The 'listpids' call doesn't have a target proc */
+       if (targetp == PROC_NULL) {
+               assert(callnum == PROC_INFO_CALL_LISTPIDS && check_same_user == NO_CHECK_SAME_USER);
+               return (0);
+       }
+
+       /*
+        * Check for 'get information for processes owned by other users' privilege
+        * root has this privilege by default
+        */
+       if (priv_check_cred(kauth_cred_get(), PRIV_GLOBAL_PROC_INFO, 0) == 0)
+               check_same_user = FALSE;
+
+       if (check_same_user) {
+               kauth_cred_t target_cred;
+               uid_t        target_uid;
+
+               target_cred = kauth_cred_proc_ref(targetp);
+               target_uid  = kauth_cred_getuid(target_cred);
+               kauth_cred_unref(&target_cred);
+
+               if (kauth_getuid() != target_uid)
                        return(EPERM);
-               }
+       }
 
        return(0);
 }
@@ -1738,6 +2129,9 @@ proc_setcontrol(int pid, int flavor, uint64_t arg, user_addr_t buffer, uint32_t
        if (pid != pself->p_pid)
                return(EINVAL);
 
+       /* Do we have permission to look into this? */
+       if ((error = proc_security_policy(pself, PROC_INFO_CALL_SETCONTROL, flavor, NO_CHECK_SAME_USER)))
+               goto out;
 
        switch (flavor) {
                case PROC_SELFSET_PCONTROL: {
@@ -1800,42 +2194,7 @@ out:
        return(error);
 }
 
-void
-proc_dirty_start(struct proc *p)
-{
-       proc_lock(p);
-       while (p->p_dirty & P_DIRTY_BUSY) {
-               msleep(&p->p_dirty, &p->p_mlock, 0, "proc_dirty_start", NULL);
-       }
-       p->p_dirty |= P_DIRTY_BUSY;
-       proc_unlock(p);
-}
-
-void
-proc_dirty_end(struct proc *p)
-{
-       proc_lock(p);
-       if (p->p_dirty & P_DIRTY_BUSY) {
-               p->p_dirty &= ~P_DIRTY_BUSY;
-               wakeup(&p->p_dirty);
-       }
-       proc_unlock(p);
-}
-
-static boolean_t
-proc_validate_track_flags(uint32_t pcontrol, struct proc *target_p) {
-       /* Check idle exit isn't specified independently */
-       if ((pcontrol & PROC_DIRTY_TRACK_MASK) == PROC_DIRTY_ALLOW_IDLE_EXIT) {
-               return false;           
-       }
-       
-       /* See that the process isn't marked for termination */
-       if (target_p->p_dirty & P_DIRTY_TERMINATED) {
-               return false;           
-       }
-       
-       return true;
-}
+#if CONFIG_MEMORYSTATUS
 
 int
 proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t *retval) {
@@ -1845,16 +2204,29 @@ proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t *retval) {
        kauth_cred_t my_cred, target_cred;
        boolean_t self = FALSE;
        boolean_t child = FALSE;
+       boolean_t zombref = FALSE;
        pid_t selfpid;
 
        target_p = proc_find(pid);
+
        if (target_p == PROC_NULL) {
-               return(ESRCH);
+               if (flavor == PROC_DIRTYCONTROL_GET) {
+                       target_p = proc_find_zombref(pid);
+                       zombref = 1;
+               }
+
+               if (target_p == PROC_NULL)
+                       return(ESRCH);
+
        }
-       
+
        my_cred = kauth_cred_get();
        target_cred = kauth_cred_proc_ref(target_p);
-       
+
+       /* Do we have permission to look into this? */
+       if ((error = proc_security_policy(target_p, PROC_INFO_CALL_DIRTYCONTROL, flavor, NO_CHECK_SAME_USER)))
+               goto out;
+
        selfpid = proc_selfpid();
        if (pid == selfpid) {
                self = TRUE;
@@ -1869,109 +2241,62 @@ proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t *retval) {
                                error = EPERM;
                                goto out;
                        }
-                       
-                       proc_dirty_start(target_p);     
 
-                       if (proc_validate_track_flags(pcontrol, target_p)) {
-                               /* Cumulative, as per <rdar://problem/11159924> */
-                               target_p->p_dirty |= 
-                                       ((pcontrol & PROC_DIRTY_TRACK) ? P_DIRTY_TRACK : 0) |
-                                       ((pcontrol & PROC_DIRTY_ALLOW_IDLE_EXIT) ? P_DIRTY_ALLOW_IDLE_EXIT : 0);        
-#if CONFIG_MEMORYSTATUS
-                               if ((target_p->p_dirty & P_DIRTY_CAN_IDLE_EXIT) == P_DIRTY_CAN_IDLE_EXIT) {
-                                       memorystatus_on_track_dirty(pid, TRUE);
-                               }
-#endif
-                       } else {
-                               error = EINVAL;
-                       }
-                       
-                       proc_dirty_end(target_p);
+                       error = memorystatus_dirty_track(target_p, pcontrol);
                }
                break;
 
-               case PROC_DIRTYCONTROL_SET: {
-                       boolean_t kill = false;
-                       
+               case PROC_DIRTYCONTROL_SET: {                   
                        /* Check privileges; use cansignal() here since the process could be terminated */
                        if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) {
                                error = EPERM;
                                goto out;
                        }
                        
-                       proc_dirty_start(target_p);
-                       
-                       if (!(target_p->p_dirty & P_DIRTY_TRACK)) {
-                               /* Dirty tracking not enabled */
-                               error = EINVAL;                 
-                       } else if (pcontrol && (target_p->p_dirty & P_DIRTY_TERMINATED)) {
-                               /* 
-                                * Process is set to be terminated and we're attempting to mark it dirty.
-                                * Set for termination and marking as clean is OK - see <rdar://problem/10594349>.
-                                */
-                               error = EBUSY;          
-                       } else {
-                               int flag = (self == TRUE) ? P_DIRTY : P_DIRTY_SHUTDOWN;
-                       if (pcontrol && !(target_p->p_dirty & flag)) {
-                                       target_p->p_dirty |= flag;
-                               } else if ((pcontrol == 0) && (target_p->p_dirty & flag)) {
-                                       if ((flag == P_DIRTY_SHUTDOWN) && (!target_p->p_dirty & P_DIRTY)) {
-                                               /* Clearing the dirty shutdown flag, and the process is otherwise clean - kill */
-                                               target_p->p_dirty |= P_DIRTY_TERMINATED;
-                                               kill = true;
-                                       } else if ((flag == P_DIRTY) && (target_p->p_dirty & P_DIRTY_TERMINATED)) {
-                                               /* Kill previously terminated processes if set clean */
-                                               kill = true;                                            
-                                       }
-                                       target_p->p_dirty &= ~flag;
-                               } else {
-                                       /* Already set */
-                                       error = EALREADY;
-                               }
-                       }
-#if CONFIG_MEMORYSTATUS
-                       if ((error == 0) && ((target_p->p_dirty & P_DIRTY_CAN_IDLE_EXIT) == P_DIRTY_CAN_IDLE_EXIT)) {
-                               memorystatus_on_dirty(pid, pcontrol ? TRUE : FALSE);
-                       }
-#endif
-                       proc_dirty_end(target_p);
-
-                       if ((error == 0) && (kill == true)) {
-                               psignal(target_p, SIGKILL);
-                       }
+                       error = memorystatus_dirty_set(target_p, self, pcontrol);       
                }
                break;
                
                case PROC_DIRTYCONTROL_GET: {
                        /* No permissions check - dirty state is freely available */
                        if (retval) {
-                               proc_dirty_start(target_p);
-                               
-                               *retval = 0;
-                               if (target_p->p_dirty & P_DIRTY_TRACK) {
-                                       *retval |= PROC_DIRTY_TRACKED;
-                                       if (target_p->p_dirty & P_DIRTY_ALLOW_IDLE_EXIT) {
-                                               *retval |= PROC_DIRTY_ALLOWS_IDLE_EXIT;
-                                       }
-                                       if (target_p->p_dirty & P_DIRTY) {
-                                               *retval |= PROC_DIRTY_IS_DIRTY;
-                                       }
-                               }
-                               
-                               proc_dirty_end(target_p);
+                               *retval = memorystatus_dirty_get(target_p);
                        } else {
                                error = EINVAL;
                        }
                }
                break;
+               
+               case PROC_DIRTYCONTROL_CLEAR: {                 
+                       /* Check privileges; use cansignal() here since the process could be terminated */
+                       if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) {
+                               error = EPERM;
+                               goto out;
+                       }
+                       
+                       error = memorystatus_dirty_clear(target_p, pcontrol);   
+               }
+               break;
        }
 
 out:
-       proc_rele(target_p);
-    kauth_cred_unref(&target_cred);
+       if (zombref)
+               proc_drop_zombref(target_p);
+       else
+               proc_rele(target_p);
+
+       kauth_cred_unref(&target_cred);
        
        return(error);  
 }
+#else
+
+int
+proc_dirtycontrol(__unused int pid, __unused int flavor, __unused uint64_t arg, __unused int32_t *retval) {
+        return ENOTSUP;
+}
+
+#endif /* CONFIG_MEMORYSTATUS */
 
 /*
  * proc_terminate() provides support for sudden termination.
@@ -2011,22 +2336,22 @@ proc_terminate(int pid, int32_t *retval)
                error = EPERM;
                goto out;
        }
-       
-       proc_dirty_start(p);
-       
-       p->p_dirty |= P_DIRTY_TERMINATED;
-       
-       if ((p->p_dirty & (P_DIRTY_TRACK|P_DIRTY_IS_DIRTY)) == P_DIRTY_TRACK) {
-               /* Clean; mark as terminated and issue SIGKILL */
-               sig = SIGKILL;
-       } else {
-               /* Dirty, terminated, or state tracking is unsupported; issue SIGTERM to allow cleanup */
-               sig = SIGTERM;
+
+       /* Not allowed to sudden terminate yourself */
+       if (p == current_proc()) {
+               error = EPERM;
+               goto out;
        }
 
-       proc_dirty_end(p);
+#if CONFIG_MEMORYSTATUS
+       /* Determine requisite signal to issue */
+       sig = memorystatus_on_terminate(p);
+#else
+       sig = SIGTERM;
+#endif
 
-       proc_removethrottle(p);
+       proc_set_task_policy(p->task, THREAD_NULL, TASK_POLICY_ATTRIBUTE,
+                            TASK_POLICY_TERMINATED, TASK_POLICY_ENABLE);
 
        psignal(p, sig);
        *retval = sig;
@@ -2037,26 +2362,6 @@ out:
        return error;
 }
 
-void
-proc_removethrottle(proc_t p)
-
-{
-       /* remove throttled states in all threads; process is going to terminate soon */
-       proc_lock(p);
-
-       /* if already marked marked for proc_termiantion.. */
-       if ((p->p_lflag & P_LPTERMINATE) != 0) {
-               proc_unlock(p);
-               return;
-       }
-       p->p_lflag |= P_LPTERMINATE;
-       proc_unlock(p);
-
-       (void)proc_task_remove_throttle(p->task);
-
-}
-
-
 /*
  * copy stat64 structure into vinfo_stat structure.
  */
@@ -2088,3 +2393,134 @@ munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp)
        vsbp->vst_qspare[0] = sbp->st_qspare[0];
        vsbp->vst_qspare[1] = sbp->st_qspare[1];
 }
+
+int
+proc_pid_rusage(int pid, int flavor, user_addr_t buffer, __unused int32_t *retval)
+{
+       proc_t          p;
+       int             error;
+       int             zombie = 0;
+
+       if ((p = proc_find(pid)) == PROC_NULL) {
+               if ((p = proc_find_zombref(pid)) == PROC_NULL) {
+                       return (ESRCH);
+               }
+               zombie = 1;
+       }
+
+       /* Do we have permission to look into this? */
+       if ((error = proc_security_policy(p, PROC_INFO_CALL_PIDRUSAGE, flavor, CHECK_SAME_USER)))
+               goto out;
+
+       error = proc_get_rusage(p, flavor, buffer, zombie);
+
+out:
+       if (zombie)
+               proc_drop_zombref(p);
+       else
+               proc_rele(p);
+
+       return (error);
+}
+
+void 
+proc_archinfo(proc_t p, struct proc_archinfo *pai)
+{
+       proc_lock(p);
+       pai->p_cputype = p->p_cputype;
+       pai->p_cpusubtype = p->p_cpusubtype;
+       proc_unlock(p);
+}
+
+void
+proc_pidcoalitioninfo(proc_t p, struct proc_pidcoalitioninfo *ppci)
+{
+       bzero(ppci, sizeof(*ppci));
+       ppci->coalition_id = proc_coalitionid(p);
+}
+
+
+
+/* 
+ * Wrapper to provide NOTE_EXIT_DETAIL and NOTE_EXITSTATUS
+ * It mimics the data that is typically captured by the 
+ * EVFILT_PROC, NOTE_EXIT event mechanism.
+ * See filt_proc() in kern_event.c.
+ */
+int
+proc_pidnoteexit(proc_t p, uint64_t flags, uint32_t *data)
+{
+       uint32_t exit_data = 0;
+       uint32_t exit_flags = (uint32_t)flags;
+
+       proc_lock(p);
+
+       /*
+        * Allow access to the parent of the exiting
+        * child or the parent debugger only.
+        */
+       do {
+               pid_t selfpid = proc_selfpid();
+
+               if (p->p_ppid == selfpid)
+                       break;  /* parent => ok */
+       
+               if ((p->p_lflag & P_LTRACED) != 0 &&
+                   (p->p_oppid == selfpid))
+                       break;  /* parent-in-waiting => ok */
+
+               proc_unlock(p);
+               return (EACCES);
+       } while (0);
+       
+       if ((exit_flags & NOTE_EXITSTATUS) != 0) {
+               /* The signal and exit status */
+               exit_data |= (p->p_xstat & NOTE_PDATAMASK);
+       }
+
+       if ((exit_flags & NOTE_EXIT_DETAIL) != 0) {
+               /* The exit detail */
+               if ((p->p_lflag & P_LTERM_DECRYPTFAIL) != 0) {
+                       exit_data |= NOTE_EXIT_DECRYPTFAIL;
+               }
+
+               if ((p->p_lflag & P_LTERM_JETSAM) != 0) {
+                       exit_data |= NOTE_EXIT_MEMORY;
+
+                       switch (p->p_lflag & P_JETSAM_MASK) {
+                       case P_JETSAM_VMPAGESHORTAGE:
+                               exit_data |= NOTE_EXIT_MEMORY_VMPAGESHORTAGE;
+                               break;
+                       case P_JETSAM_VMTHRASHING:
+                               exit_data |= NOTE_EXIT_MEMORY_VMTHRASHING;
+                               break;
+                       case P_JETSAM_FCTHRASHING:
+                               exit_data |= NOTE_EXIT_MEMORY_FCTHRASHING;
+                               break;
+                       case P_JETSAM_VNODE:
+                               exit_data |= NOTE_EXIT_MEMORY_VNODE;
+                               break;
+                       case P_JETSAM_HIWAT:
+                               exit_data |= NOTE_EXIT_MEMORY_HIWAT;
+                               break;
+                       case P_JETSAM_PID:
+                               exit_data |= NOTE_EXIT_MEMORY_PID;
+                               break;
+                       case P_JETSAM_IDLEEXIT:
+                               exit_data |= NOTE_EXIT_MEMORY_IDLE;
+                               break;
+                       }
+               }
+
+               if ((p->p_csflags & CS_KILLED) != 0) {
+                       exit_data |= NOTE_EXIT_CSERROR;
+               }
+       }
+
+       proc_unlock(p);
+
+       *data = exit_data;
+
+       return (0);
+}
+