]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_proc.c
xnu-4570.41.2.tar.gz
[apple/xnu.git] / bsd / kern / kern_proc.c
index 8628e301fd982480966f2ebc6d694b441d558571..249d8c3553db97e05dd327b1e416b8b5d2ade481 100644 (file)
 #include <sys/bsdtask_info.h>
 #include <sys/persona.h>
 
 #include <sys/bsdtask_info.h>
 #include <sys/persona.h>
 
+#ifdef CONFIG_32BIT_TELEMETRY
+#include <sys/kasl.h>
+#endif /* CONFIG_32BIT_TELEMETRY */
+
+#if CONFIG_CSR
+#include <sys/csr.h>
+#endif
+
 #if CONFIG_MEMORYSTATUS
 #include <sys/kern_memorystatus.h>
 #endif
 #if CONFIG_MEMORYSTATUS
 #include <sys/kern_memorystatus.h>
 #endif
 
 #include <libkern/crypto/sha1.h>
 
 
 #include <libkern/crypto/sha1.h>
 
+#ifdef CONFIG_32BIT_TELEMETRY
+#define MAX_32BIT_EXEC_SIG_SIZE 160
+#endif /* CONFIG_32BIT_TELEMETRY */
+
 /*
  * Structure associated with user cacheing.
  */
 /*
  * Structure associated with user cacheing.
  */
@@ -150,13 +162,23 @@ extern struct tty cons;
 
 extern int cs_debug;
 
 
 extern int cs_debug;
 
+#if DEVELOPMENT || DEBUG
+extern int cs_enforcement_enable;
+#endif
+
 #if DEBUG
 #define __PROC_INTERNAL_DEBUG 1
 #endif
 #if CONFIG_COREDUMP
 /* Name to give to core files */
 #if DEBUG
 #define __PROC_INTERNAL_DEBUG 1
 #endif
 #if CONFIG_COREDUMP
 /* Name to give to core files */
+#if defined(XNU_TARGET_OS_BRIDGE)
+__XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN+1] = {"/private/var/internal/%N.core"};
+#elif CONFIG_EMBEDDED
+__XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN+1] = {"/private/var/cores/%N.core"};
+#else
 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN+1] = {"/cores/core.%P"};
 #endif
 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN+1] = {"/cores/core.%P"};
 #endif
+#endif
 
 #if PROC_REF_DEBUG
 #include <kern/backtrace.h>
 
 #if PROC_REF_DEBUG
 #include <kern/backtrace.h>
@@ -488,11 +510,16 @@ proc_t
 proc_ref_locked(proc_t p)
 {
        proc_t p1 = p;
 proc_ref_locked(proc_t p)
 {
        proc_t p1 = p;
+       int pid = proc_pid(p);
        
        
-       /* if process still in creation return failure */
-       if ((p == PROC_NULL) || ((p->p_listflag & P_LIST_INCREATE) != 0))
-                       return (PROC_NULL);
 retry:
 retry:
+       /*
+        * if process still in creation or proc got recycled
+        * during msleep then return failure.
+        */
+       if ((p == PROC_NULL) || (p1 != p) || ((p->p_listflag & P_LIST_INCREATE) != 0))
+                       return (PROC_NULL);
+
        /*
         * Do not return process marked for termination
         * or proc_refdrain called without ref wait.
        /*
         * Do not return process marked for termination
         * or proc_refdrain called without ref wait.
@@ -508,6 +535,11 @@ retry:
             ((p->p_listflag & P_LIST_REFWAIT) != 0))) {
                if ((p->p_listflag & P_LIST_REFWAIT) != 0 && uthread_needs_to_wait_in_proc_refwait()) {
                        msleep(&p->p_listflag, proc_list_mlock, 0, "proc_refwait", 0) ;
             ((p->p_listflag & P_LIST_REFWAIT) != 0))) {
                if ((p->p_listflag & P_LIST_REFWAIT) != 0 && uthread_needs_to_wait_in_proc_refwait()) {
                        msleep(&p->p_listflag, proc_list_mlock, 0, "proc_refwait", 0) ;
+                       /*
+                        * the proc might have been recycled since we dropped
+                        * the proc list lock, get the proc again.
+                        */
+                       p = pfind_locked(pid);
                        goto retry;
                }
                p->p_refcount++;
                        goto retry;
                }
                p->p_refcount++;
@@ -1131,7 +1163,7 @@ proc_getexecutablevnode(proc_t p)
                if (vnode_getwithref(tvp) == 0) {
                        return tvp;
                }
                if (vnode_getwithref(tvp) == 0) {
                        return tvp;
                }
-       }       
+       }
 
        return NULLVP;
 }
 
        return NULLVP;
 }
@@ -1148,6 +1180,7 @@ bsd_set_dependency_capable(task_t task)
 }
 
 
 }
 
 
+#ifndef        __arm__
 int
 IS_64BIT_PROCESS(proc_t p)
 {
 int
 IS_64BIT_PROCESS(proc_t p)
 {
@@ -1156,6 +1189,7 @@ IS_64BIT_PROCESS(proc_t p)
        else
                return(0);
 }
        else
                return(0);
 }
+#endif
 
 /*
  * Locate a process by number
 
 /*
  * Locate a process by number
@@ -1297,6 +1331,7 @@ pinsertchild(proc_t parent, proc_t child)
        child->p_pptr = parent;
        child->p_ppid = parent->p_pid;
        child->p_puniqueid = parent->p_uniqueid;
        child->p_pptr = parent;
        child->p_ppid = parent->p_pid;
        child->p_puniqueid = parent->p_uniqueid;
+       child->p_xhighbits = 0;
 
        pg = proc_pgrp(parent);
        pgrp_add(pg, parent, child);
 
        pg = proc_pgrp(parent);
        pgrp_add(pg, parent, child);
@@ -1949,6 +1984,7 @@ csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user
                case CS_OPS_MARKRESTRICT:
                case CS_OPS_SET_STATUS:
                case CS_OPS_CLEARINSTALLER:
                case CS_OPS_MARKRESTRICT:
                case CS_OPS_SET_STATUS:
                case CS_OPS_CLEARINSTALLER:
+               case CS_OPS_CLEARPLATFORM:
                        if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops)))
                                goto out;
                        break;
                        if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops)))
                                goto out;
                        break;
@@ -2149,7 +2185,7 @@ csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user
                                error = ENOENT;
                                break;
                        }
                                error = ENOENT;
                                break;
                        }
-                       
+
                        length = strlen(identity) + 1; /* include NUL */
                        idlen = htonl(length + sizeof(fakeheader));
                        memcpy(&fakeheader[4], &idlen, sizeof(idlen));
                        length = strlen(identity) + 1; /* include NUL */
                        idlen = htonl(length + sizeof(fakeheader));
                        memcpy(&fakeheader[4], &idlen, sizeof(idlen));
@@ -2168,10 +2204,34 @@ csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user
 
                case CS_OPS_CLEARINSTALLER:
                        proc_lock(pt);
 
                case CS_OPS_CLEARINSTALLER:
                        proc_lock(pt);
-                       pt->p_csflags &= ~(CS_INSTALLER | CS_EXEC_SET_INSTALLER);
+                       pt->p_csflags &= ~(CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_EXEC_INHERIT_SIP);
                        proc_unlock(pt);
                        break;
 
                        proc_unlock(pt);
                        break;
 
+               case CS_OPS_CLEARPLATFORM:
+#if DEVELOPMENT || DEBUG
+                       if (cs_enforcement_enable) {
+                               error = ENOTSUP;
+                               break;
+                       }
+
+#if CONFIG_CSR
+                       if (csr_check(CSR_ALLOW_APPLE_INTERNAL) != 0) {
+                               error = ENOTSUP;
+                               break;
+                       }
+#endif
+
+                       proc_lock(pt);
+                       pt->p_csflags &= ~(CS_PLATFORM_BINARY|CS_PLATFORM_PATH);
+                       csproc_clear_platform_binary(pt);
+                       proc_unlock(pt);
+                       break;
+#else
+                       error = ENOTSUP;
+                       break;
+#endif /* !DEVELOPMENT || DEBUG */
+
                default:
                        error = EINVAL;
                        break;
                default:
                        error = EINVAL;
                        break;
@@ -2201,7 +2261,7 @@ proc_iterate(
        for (;;) {
                proc_list_lock();
 
        for (;;) {
                proc_list_lock();
 
-               pid_count_available = nprocs;
+               pid_count_available = nprocs + 1; //kernel_task is not counted in nprocs
                assert(pid_count_available > 0);
 
                pid_list_size_needed = pid_count_available * sizeof(pid_t);
                assert(pid_count_available > 0);
 
                pid_list_size_needed = pid_count_available * sizeof(pid_t);
@@ -3170,6 +3230,10 @@ extern boolean_t kill_on_no_paging_space;
 #endif /* DEVELOPMENT || DEBUG */
 
 #define MB_SIZE        (1024 * 1024ULL)
 #endif /* DEVELOPMENT || DEBUG */
 
 #define MB_SIZE        (1024 * 1024ULL)
+boolean_t      memorystatus_kill_on_VM_thrashing(boolean_t);
+
+extern int32_t max_kill_priority;
+extern int     memorystatus_get_proccnt_upto_priority(int32_t max_bucket_index);
 
 int
 no_paging_space_action()
 
 int
 no_paging_space_action()
@@ -3235,6 +3299,22 @@ no_paging_space_action()
                }
        }
 
                }
        }
 
+       /*
+        * We have some processes within our jetsam bands of consideration and hence can be killed.
+        * So we will invoke the memorystatus thread to go ahead and kill something.
+        */
+       if (memorystatus_get_proccnt_upto_priority(max_kill_priority) > 0) {
+
+               last_no_space_action = now;
+               memorystatus_kill_on_VM_thrashing(TRUE /* async */);
+               return (1);
+       }
+
+       /*
+        * No eligible processes to kill. So let's suspend/kill the largest
+        * process depending on its policy control specifications.
+        */
+
        if (nps.pcs_max_size > 0) {
                if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) {
 
        if (nps.pcs_max_size > 0) {
                if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) {
 
@@ -3246,22 +3326,6 @@ no_paging_space_action()
                                 */
                                last_no_space_action = now;
                
                                 */
                                last_no_space_action = now;
                
-#if DEVELOPMENT || DEBUG
-                               if (kill_on_no_paging_space == TRUE) {
-                                       /*
-                                        * We found the largest process that has a process policy i.e. one of
-                                        * PC_KILL, PC_SUSP, PC_THROTTLE.
-                                        * But we are in a mode where we will kill it regardless of its policy.
-                                        */
-                                       printf("low swap: killing largest process with pid %d (%s) and size %llu MB\n", p->p_pid, p->p_comm, (nps.pcs_max_size/MB_SIZE));
-                                       psignal(p, SIGKILL);
-
-                                       proc_rele(p);
-
-                                       return 1;
-                               }
-#endif /* DEVELOPMENT || DEBUG */
-
                                proc_dopcontrol(p);
                        
                                proc_rele(p);
                                proc_dopcontrol(p);
                        
                                proc_rele(p);
@@ -3375,3 +3439,80 @@ proc_get_uthread_uu_threadlist(void * uthread_v)
        uthread_t uth = (uthread_t)uthread_v;
        return (uth != NULL) ? uth->uu_threadlist : NULL;
 }
        uthread_t uth = (uthread_t)uthread_v;
        return (uth != NULL) ? uth->uu_threadlist : NULL;
 }
+
+#ifdef CONFIG_32BIT_TELEMETRY
+void
+proc_log_32bit_telemetry(proc_t p)
+{
+       /* Gather info */
+       char signature_buf[MAX_32BIT_EXEC_SIG_SIZE] = { 0 };
+       char * signature_cur_end = &signature_buf[0];
+       char * signature_buf_end = &signature_buf[MAX_32BIT_EXEC_SIG_SIZE - 1];
+       int bytes_printed = 0;
+
+       const char * teamid = NULL;
+       const char * identity = NULL;
+       struct cs_blob * csblob = NULL;
+
+       proc_list_lock();
+
+       /*
+        * Get proc name and parent proc name; if the parent execs, we'll get a
+        * garbled name.
+        */
+       bytes_printed = snprintf(signature_cur_end,
+                                signature_buf_end - signature_cur_end,
+                                "%s,%s,", p->p_name,
+                                (p->p_pptr ? p->p_pptr->p_name : ""));
+
+       if (bytes_printed > 0) {
+               signature_cur_end += bytes_printed;
+       }
+
+       proc_list_unlock();
+
+       /* Get developer info. */
+       vnode_t v = proc_getexecutablevnode(p);
+
+       if (v) {
+               csblob = csvnode_get_blob(v, 0);
+
+               if (csblob) {
+                       teamid = csblob_get_teamid(csblob);
+                       identity = csblob_get_identity(csblob);
+               }
+       }
+
+       if (teamid == NULL) {
+               teamid = "";
+       }
+
+       if (identity == NULL) {
+               identity = "";
+       }
+
+       bytes_printed = snprintf(signature_cur_end,
+                                signature_buf_end - signature_cur_end,
+                                "%s,%s", teamid, identity);
+
+       if (bytes_printed > 0) {
+               signature_cur_end += bytes_printed;
+       }
+
+       if (v) {
+               vnode_put(v);
+       }
+
+       /*
+        * We may want to rate limit here, although the SUMMARIZE key should
+        * help us aggregate events in userspace.
+        */
+
+       /* Emit log */
+       kern_asl_msg(LOG_DEBUG, "messagetracer", 3,
+       /* 0 */ "com.apple.message.domain", "com.apple.kernel.32bit_exec",
+       /* 1 */ "com.apple.message.signature", signature_buf,
+       /* 2 */ "com.apple.message.summarize", "YES",
+               NULL);
+}
+#endif /* CONFIG_32BIT_TELEMETRY */