]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_fork.c
xnu-2050.24.15.tar.gz
[apple/xnu.git] / bsd / kern / kern_fork.c
index 7746398bf7ec742b7d380318037451eeb0b61645..2f09ba8eed297bf3f50b492a6272e59df3d710a9 100644 (file)
@@ -109,6 +109,7 @@ extern void dtrace_lazy_dofs_duplicate(proc_t, proc_t);
 #include <kern/kalloc.h>
 #include <kern/mach_param.h>
 #include <kern/task.h>
+#include <kern/thread.h>
 #include <kern/thread_call.h>
 #include <kern/zalloc.h>
 
@@ -129,6 +130,10 @@ extern void dtrace_lazy_dofs_duplicate(proc_t, proc_t);
 
 #include <sys/sdt.h>
 
+#if CONFIG_MEMORYSTATUS
+#include <sys/kern_memorystatus.h>
+#endif
+
 /* XXX routines which should have Mach prototypes, but don't */
 void thread_set_parent(thread_t parent, int pid);
 extern void act_thread_catt(void *ctx);
@@ -158,8 +163,8 @@ void proc_vfork_end(proc_t parent_proc);
  * Notes:      Although this function increments a count, a count in
  *             excess of 1 is not currently supported.  According to the
  *             POSIX standard, calling anything other than execve() or
- *             _exit() fillowing a vfork(), including calling vfork()
- *             itself again, will result in undefned behaviour
+ *             _exit() following a vfork(), including calling vfork()
+ *             itself again, will result in undefined behaviour
  */
 void
 proc_vfork_begin(proc_t parent_proc)
@@ -179,7 +184,7 @@ proc_vfork_begin(proc_t parent_proc)
  *
  * Returns:    (void)
  *
- * Notes:      Decerements the count; currently, reentrancy of vfork()
+ * Notes:      Decrements the count; currently, reentrancy of vfork()
  *             is unsupported on the current process
  */
 void
@@ -189,7 +194,6 @@ proc_vfork_end(proc_t parent_proc)
        parent_proc->p_vforkcnt--;
        if (parent_proc->p_vforkcnt < 0)
                panic("vfork cnt is -ve");
-       /* resude the vfork count; clear the flag when it goes to 0 */
        if (parent_proc->p_vforkcnt == 0)
                parent_proc->p_lflag  &= ~P_LVFORK;
        proc_unlock(parent_proc);
@@ -650,6 +654,12 @@ fork1(proc_t parent_proc, thread_t *child_threadp, int kind)
        /* return the thread pointer to the caller */
        *child_threadp = child_thread;
 
+#if CONFIG_MEMORYSTATUS
+       if (!err) {
+               memorystatus_list_add(child_proc->p_pid, DEFAULT_JETSAM_PRIORITY, -1);
+       }
+#endif
+
 bad:
        /*
         * In the error case, we return a 0 value for the returned pid (but
@@ -671,48 +681,53 @@ bad:
  *             this is done by reassociating the parent process structure
  *             with the task, thread, and uthread.
  *
+ *             Refer to the ASCII art above vfork() to figure out the
+ *             state we're undoing.
+ *
  * Parameters: child_proc              Child process
  *             retval                  System call return value array
  *             rval                    Return value to present to parent
  *
  * Returns:    void
  *
- * Note      The caller resumes or exits the parent, as appropriate, after
- *             callling this function.
+ * Notes:      The caller resumes or exits the parent, as appropriate, after
+ *             calling this function.
  */
 void
 vfork_return(proc_t child_proc, int32_t *retval, int rval)
 {
-       proc_t parent_proc = child_proc->p_pptr;
-       thread_t parent_thread = (thread_t)current_thread();
-       uthread_t parent_uthread = (uthread_t)get_bsdthread_info(parent_thread);
+       task_t parent_task = get_threadtask(child_proc->p_vforkact);
+       proc_t parent_proc = get_bsdtask_info(parent_task);
+       thread_t th = current_thread();
+       uthread_t uth = get_bsdthread_info(th);
        
-       act_thread_catt(parent_uthread->uu_userstate);
+       act_thread_catt(uth->uu_userstate);
 
-       /* end vfork in parent */
+       /* clear vfork state in parent proc structure */
        proc_vfork_end(parent_proc);
 
        /* REPATRIATE PARENT TASK, THREAD, UTHREAD */
-       parent_uthread->uu_userstate = 0;
-       parent_uthread->uu_flag &= ~UT_VFORK;
+       uth->uu_userstate = 0;
+       uth->uu_flag &= ~UT_VFORK;
        /* restore thread-set-id state */
-       if (parent_uthread->uu_flag & UT_WASSETUID) {
-               parent_uthread->uu_flag |= UT_SETUID;
-               parent_uthread->uu_flag &= UT_WASSETUID;
+       if (uth->uu_flag & UT_WASSETUID) {
+               uth->uu_flag |= UT_SETUID;
+               uth->uu_flag &= UT_WASSETUID;
        }
-       parent_uthread->uu_proc = 0;
-       parent_uthread->uu_sigmask = parent_uthread->uu_vforkmask;
-       child_proc->p_lflag  &= ~P_LINVFORK;
-       child_proc->p_vforkact = (void *)0;
+       uth->uu_proc = 0;
+       uth->uu_sigmask = uth->uu_vforkmask;
+
+       proc_lock(child_proc);
+       child_proc->p_lflag &= ~P_LINVFORK;
+       child_proc->p_vforkact = 0;
+       proc_unlock(child_proc);
 
-       thread_set_parent(parent_thread, rval);
+       thread_set_parent(th, rval);
 
        if (retval) {
                retval[0] = rval;
                retval[1] = 0;                  /* mark parent */
        }
-
-       return;
 }
 
 
@@ -798,6 +813,12 @@ fork_create_child(task_t parent_task, proc_t child_proc, int inherit_memory, int
                task_deallocate(child_task);
                child_task = NULL;
        }
+
+       /*
+        * Tag thread as being the first thread in its task.
+        */
+       thread_set_tag(child_thread, THREAD_TAG_MAINTHREAD);
+
 bad:
        thread_yield_internal(1);
 
@@ -1006,6 +1027,12 @@ forkproc_free(proc_t p)
        /* Need to undo the effects of the fdcopy(), if any */
        fdfree(p);
 
+#if !CONFIG_EMBEDDED
+       if (p->p_legacy_behavior & PROC_LEGACY_BEHAVIOR_IOTHROTTLE) {
+               throttle_legacy_process_decr();
+       }
+#endif
+
        /*
         * Drop the reference on a text vnode pointer, if any
         * XXX This code is broken in forkproc(); see <rdar://4256419>;
@@ -1174,9 +1201,20 @@ retry:
         * Increase reference counts on shared objects.
         * The p_stats and p_sigacts substructs are set in vm_fork.
         */
+#if !CONFIG_EMBEDDED
+       child_proc->p_flag = (parent_proc->p_flag & (P_LP64 | P_TRANSLATED | P_AFFINITY | P_DISABLE_ASLR | P_DELAYIDLESLEEP));
+#else /*  !CONFIG_EMBEDDED */
        child_proc->p_flag = (parent_proc->p_flag & (P_LP64 | P_TRANSLATED | P_AFFINITY | P_DISABLE_ASLR));
+#endif /* !CONFIG_EMBEDDED */
        if (parent_proc->p_flag & P_PROFIL)
                startprofclock(child_proc);
+
+#if !CONFIG_EMBEDDED
+       if (child_proc->p_legacy_behavior & PROC_LEGACY_BEHAVIOR_IOTHROTTLE) {
+               throttle_legacy_process_incr();
+       }
+#endif
+
        /*
         * Note that if the current thread has an assumed identity, this
         * credential will be granted to the new process.
@@ -1319,6 +1357,9 @@ retry:
        }
 #endif
 
+       /* Default to no tracking of dirty state */
+       child_proc->p_dirty = 0;
+
 bad:
        return(child_proc);
 }
@@ -1373,8 +1414,6 @@ uthread_zone_init(void)
                                        THREAD_CHUNK * sizeof(struct uthread),
                                        "uthreads");
                uthread_zone_inited = 1;
-
-               zone_change(uthread_zone, Z_NOENCRYPT, TRUE);
        }
 }
 
@@ -1395,6 +1434,7 @@ uthread_alloc(task_t task, thread_t thread, int noinherit)
        p = (proc_t) get_bsdtask_info(task);
        uth = (uthread_t)ut;
        uth->uu_kwe.kwe_uth = uth;
+       uth->uu_thread = thread;
 
        /*
         * Thread inherits credential from the creating thread, if both
@@ -1447,6 +1487,9 @@ uthread_alloc(task_t task, thread_t thread, int noinherit)
                if (p->p_dtrace_ptss_pages != NULL) {
                        uth->t_dtrace_scratch = dtrace_ptss_claim_entry(p);
                }
+#endif
+#if CONFIG_MACF
+               mac_thread_label_init(uth);
 #endif
        }
 
@@ -1534,6 +1577,9 @@ uthread_cleanup(task_t task, void *uthread, void * bsd_info)
                if (tmpptr != NULL) {
                        dtrace_ptss_release_entry(p, tmpptr);
                }
+#endif
+#if CONFIG_MACF
+               mac_thread_label_destroy(uth);
 #endif
        }
 }