X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..e5568f75972dfc723778653c11cb6b4dc825716a:/bsd/kern/kern_fork.c

diff --git a/bsd/kern/kern_fork.c b/bsd/kern/kern_fork.c
index b67a66906..f8b8cf3d8 100644
--- a/bsd/kern/kern_fork.c
+++ b/bsd/kern/kern_fork.c
@@ -1,24 +1,21 @@
 /*
- * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
@@ -63,6 +60,7 @@
  *	@(#)kern_fork.c	8.8 (Berkeley) 2/14/95
  */
 
+#include <kern/assert.h>
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/filedesc.h>
@@ -74,8 +72,13 @@
 #include <sys/vnode.h>
 #include <sys/file.h>
 #include <sys/acct.h>
+#include <sys/wait.h>
+
+#include <bsm/audit_kernel.h>
+
 #if KTRACE
 #include <sys/ktrace.h>
+#include <sys/ubc.h>
 #endif
 
 #include <mach/mach_types.h>
@@ -146,6 +149,7 @@ vfork(p, uap, retval)
 	ut = (struct uthread *)get_bsdthread_info(cur_act);
 	if (ut->uu_flag & P_VFORK) {
 		printf("vfork called recursively by %s\n", p->p_comm);
+		(void)chgproccnt(uid, -1);
 		return (EINVAL);
 	}
 	p->p_flag  |= P_VFORK;
@@ -154,6 +158,8 @@ vfork(p, uap, retval)
 	/* The newly created process comes with signal lock held */
 	newproc = (struct proc *)forkproc(p,1);
 
+	AUDIT_ARG(pid, newproc->p_pid);
+
 	LIST_INSERT_AFTER(p, newproc, p_pglist);
 	newproc->p_pptr = p;
 	newproc->task = p->task;
@@ -204,22 +210,22 @@ vfork_return(th_act, p, p2, retval)
 {
 	long flags;
 	register uid_t uid;
-	thread_t newth, self = current_thread();
-	thread_act_t cur_act = (thread_act_t)current_act();
 	int s, count;
 	task_t t;
 	uthread_t ut;
 	
-	ut = (struct uthread *)get_bsdthread_info(cur_act);
+	ut = (struct uthread *)get_bsdthread_info(th_act);
 
 	act_thread_catt(ut->uu_userstate);
 
 	/* Make sure only one at this time */
-	p->p_vforkcnt--;
-	if (p->p_vforkcnt <0)
-		panic("vfork cnt is -ve");
-	if (p->p_vforkcnt <=0)
-		p->p_flag  &= ~P_VFORK;
+	if (p) {
+		p->p_vforkcnt--;
+		if (p->p_vforkcnt <0)
+			panic("vfork cnt is -ve");
+		if (p->p_vforkcnt <=0)
+			p->p_flag  &= ~P_VFORK;
+	}
 	ut->uu_userstate = 0;
 	ut->uu_flag &= ~P_VFORK;
 	ut->uu_proc = 0;
@@ -227,7 +233,7 @@ vfork_return(th_act, p, p2, retval)
 	p2->p_flag  &= ~P_INVFORK;
 	p2->p_vforkact = (void *)0;
 
-	thread_set_parent(cur_act, p2->p_pid);
+	thread_set_parent(th_act, p2->p_pid);
 
 	if (retval) {
 		retval[0] = p2->p_pid;
@@ -245,12 +251,13 @@ procdup(
 	thread_act_t		thread;
 	task_t			task;
  	kern_return_t	result;
+ 	pmap_t			pmap;
 	extern task_t kernel_task;
 
 	if (parent->task == kernel_task)
-		result = task_create_local(TASK_NULL, FALSE, FALSE, &task);
+		result = task_create_internal(TASK_NULL, FALSE, &task);
 	else
-		result = task_create_local(parent->task, TRUE, FALSE, &task);
+		result = task_create_internal(parent->task, TRUE, &task);
 	if (result != KERN_SUCCESS)
 	    printf("fork/procdup: task_create failed. Code: 0x%x\n", result);
 	child->task = task;
@@ -258,6 +265,7 @@ procdup(
 	set_bsdtask_info(task, child);
 	if (child->p_nice != 0)
 		resetpriority(child);
+		
 	result = thread_create(task, &thread);
 	if (result != KERN_SUCCESS)
 	    printf("fork/procdup: thread_create failed. Code: 0x%x\n", result);
@@ -308,6 +316,8 @@ fork1(p1, flags, retval)
 	/* p2 = newth->task->proc; */
 	p2 = (struct proc *)(get_bsdtask_info(get_threadtask(newth)));
 
+	AUDIT_ARG(pid, p2->p_pid);
+
 	thread_set_child(newth, p2->p_pid);
 
 	s = splhigh();
@@ -333,6 +343,8 @@ fork1(p1, flags, retval)
         }
         act_deallocate(newth);
 
+	KNOTE(&p1->p_klist, NOTE_FORK | p2->p_pid);
+
 	while (p2->p_flag & P_PPWAIT)
 		tsleep(p1, PWAIT, "ppwait", 0);
 
@@ -453,6 +465,7 @@ again:
 	p2->p_stat = SIDL;
 	p2->p_pid = nextpid;
 
+	p2->p_shutdownstate = 0;
 	/*
 	 * Make a proc table entry for the new process.
 	 * Start by zeroing the section of proc that is zero-initialized,
@@ -464,18 +477,26 @@ again:
 	    (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy));
 	p2->vm_shm = (void *)NULL; /* Make sure it is zero */
 
+	/*
+	 * Copy the audit info.
+	 */
+	audit_proc_fork(p1, p2);
+
 	/*
 	 * Duplicate sub-structures as needed.
 	 * Increase reference counts on shared objects.
 	 * The p_stats and p_sigacts substructs are set in vm_fork.
 	 */
 	p2->p_flag = P_INMEM;
+	p2->p_flag |= (p1->p_flag & P_CLASSIC); // copy from parent
+	p2->p_flag |= (p1->p_flag & P_AFFINITY); // copy from parent
 	if (p1->p_flag & P_PROFIL)
 		startprofclock(p2);
 	bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred));
 	p2->p_cred->p_refcnt = 1;
 	crhold(p1->p_ucred);
 	lockinit(&p2->p_cred->pc_lock, PLOCK, "proc cred", 0, 0);
+	klist_init(&p2->p_klist);
 
 	/* bump references to the text vnode */
 	p2->p_textvp = p1->p_textvp;
@@ -515,6 +536,8 @@ again:
 	if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
 		p2->p_flag |= P_CONTROLT;
 
+	p2->p_argslen = p1->p_argslen;
+	p2->p_argc = p1->p_argc;
 	p2->p_xstat = 0;
 	p2->p_ru = NULL;
 
@@ -527,10 +550,13 @@ again:
 	p2->sigwait_thread = NULL;
 	p2->exit_thread = NULL;
 	p2->user_stack = p1->user_stack;
-	p2->p_xxxsigpending = 0;
 	p2->p_vforkcnt = 0;
 	p2->p_vforkact = 0;
 	TAILQ_INIT(&p2->p_uthlist);
+	TAILQ_INIT(&p2->aio_activeq);
+	TAILQ_INIT(&p2->aio_doneq);
+	p2->aio_active_count = 0;
+	p2->aio_done_count = 0;
 
 #if KTRACE
 	/*
@@ -539,8 +565,11 @@ again:
 	 */
 	if (p1->p_traceflag&KTRFAC_INHERIT) {
 		p2->p_traceflag = p1->p_traceflag;
-		if ((p2->p_tracep = p1->p_tracep) != NULL)
+		if ((p2->p_tracep = p1->p_tracep) != NULL) {
+			if (UBCINFOEXISTS(p2->p_tracep))
+			        ubc_hold(p2->p_tracep);
 			VREF(p2->p_tracep);
+		}
 	}
 #endif
 	return(p2);
@@ -581,7 +610,7 @@ uthread_alloc(task_t task, thread_act_t thr_act )
 
 	if (task != kernel_task) {
 		uth = (struct uthread *)ut;
-		p = get_bsdtask_info(task);
+		p = (struct proc *) get_bsdtask_info(task);
 
 		funnel_state = thread_funnel_set(kernel_flock, TRUE);
 		uth_parent = (struct uthread *)get_bsdthread_info(current_act());
@@ -604,7 +633,7 @@ uthread_alloc(task_t task, thread_act_t thr_act )
 
 
 void
-uthread_free(task_t task, void *uthread, void * bsd_info)
+uthread_free(task_t task, thread_t act, void *uthread, void * bsd_info)
 {
 	struct _select *sel;
 	struct uthread *uth = (struct uthread *)uthread;
@@ -612,6 +641,16 @@ uthread_free(task_t task, void *uthread, void * bsd_info)
 	extern task_t kernel_task;
 	int size;
 	boolean_t funnel_state;
+	struct nlminfo *nlmp;
+	struct proc * vproc;
+
+	/*
+	 * Per-thread audit state should never last beyond system
+	 * call return.  Since we don't audit the thread creation/
+	 * removal, the thread state pointer should never be
+	 * non-NULL when we get here.
+	 */
+	assert(uth->uu_ar == NULL);
 
 	sel = &uth->uu_state.ss_select;
 	/* cleanup the select bit space */
@@ -628,11 +667,23 @@ uthread_free(task_t task, void *uthread, void * bsd_info)
 		sel->wql = 0;
 	}
 
-	if ((task != kernel_task) && p) {
+	if ((nlmp = uth->uu_nlminfo)) {
+		uth->uu_nlminfo = 0;
+		FREE(nlmp, M_LOCKF);
+	}
+
+	if ((task != kernel_task) ) {
+		int vfork_exit(struct proc *, int);
+
 		funnel_state = thread_funnel_set(kernel_flock, TRUE);
-		//signal_lock(p);
-		TAILQ_REMOVE(&p->p_uthlist, uth, uu_list);
-		//signal_unlock(p);
+		if (p)
+			TAILQ_REMOVE(&p->p_uthlist, uth, uu_list);
+		if ((uth->uu_flag & P_VFORK) && (vproc = uth->uu_proc) 
+					&& (vproc->p_flag & P_INVFORK)) {
+			if (!vfork_exit(vproc, W_EXITCODE(0, SIGKILL)))	
+				vfork_return(act, p, vproc, NULL);
+
+		}
 		(void)thread_funnel_set(kernel_flock, funnel_state);
 	}
 	/* and free the uthread itself */