--- old/usr/src/uts/common/os/fork.c	Wed Oct  5 00:32:26 2016
+++ new/usr/src/uts/common/os/fork.c	Wed Oct  5 00:32:26 2016
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2013, Joyent, Inc. All rights reserved.
+ * Copyright 2016, Joyent, Inc.
  */
 
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
@@ -84,6 +84,7 @@
 static int getproc(proc_t **, pid_t, uint_t);
 #define	GETPROC_USER	0x0
 #define	GETPROC_KERNEL	0x1
+#define	GETPROC_ZSCHED	0x2
 
 static void fork_fail(proc_t *);
 static void forklwp_fail(proc_t *);
@@ -125,6 +126,29 @@
 	}
 }
 
+/*
+ * Remove the associations of a child process from its parent and siblings.
+ */
+static void
+disown_proc(proc_t *pp, proc_t *cp)
+{
+	proc_t **orphpp;
+
+	ASSERT(MUTEX_HELD(&pidlock));
+
+	orphpp = &pp->p_orphan;
+	while (*orphpp != cp)
+		orphpp = &(*orphpp)->p_nextorph;
+	*orphpp = cp->p_nextorph;
+
+	if (pp->p_child == cp)
+		pp->p_child = cp->p_sibling;
+	if (cp->p_sibling)
+		cp->p_sibling->p_psibling = cp->p_psibling;
+	if (cp->p_psibling)
+		cp->p_psibling->p_sibling = cp->p_sibling;
+}
+
 /* ARGSUSED */
 static int64_t
 cfork(int isvfork, int isfork1, int flags)
@@ -131,7 +155,7 @@
 {
 	proc_t *p = ttoproc(curthread);
 	struct as *as;
-	proc_t *cp, **orphpp;
+	proc_t *cp;
 	klwp_t *clone;
 	kthread_t *t;
 	task_t *tk;
@@ -266,16 +290,7 @@
 			sprunlock(p);
 			fork_fail(cp);
 			mutex_enter(&pidlock);
-			orphpp = &p->p_orphan;
-			while (*orphpp != cp)
-				orphpp = &(*orphpp)->p_nextorph;
-			*orphpp = cp->p_nextorph;
-			if (p->p_child == cp)
-				p->p_child = cp->p_sibling;
-			if (cp->p_sibling)
-				cp->p_sibling->p_psibling = cp->p_psibling;
-			if (cp->p_psibling)
-				cp->p_psibling->p_sibling = cp->p_sibling;
+			disown_proc(p, cp);
 			mutex_enter(&cp->p_lock);
 			tk = cp->p_task;
 			task_detach(cp);
@@ -640,16 +655,7 @@
 	atomic_dec_32(&cp->p_pool->pool_ref);
 	mutex_exit(&cp->p_lock);
 
-	orphpp = &p->p_orphan;
-	while (*orphpp != cp)
-		orphpp = &(*orphpp)->p_nextorph;
-	*orphpp = cp->p_nextorph;
-	if (p->p_child == cp)
-		p->p_child = cp->p_sibling;
-	if (cp->p_sibling)
-		cp->p_sibling->p_psibling = cp->p_psibling;
-	if (cp->p_psibling)
-		cp->p_psibling->p_sibling = cp->p_sibling;
+	disown_proc(p, cp);
 	pid_exit(cp, tk);
 	mutex_exit(&pidlock);
 
@@ -696,7 +702,7 @@
 	if (PTOU(curproc)->u_cwd)
 		refstr_rele(PTOU(curproc)->u_cwd);
 	if (PROC_IS_BRANDED(cp)) {
-		brand_clearbrand(cp, B_TRUE);
+		brand_clearbrand(cp, B_FALSE);
 	}
 }
 
@@ -745,7 +751,7 @@
 			kmem_free(t->t_door, sizeof (door_data_t));
 			t->t_door = NULL;
 		}
-		lwp_ctmpl_clear(ttolwp(t));
+		lwp_ctmpl_clear(ttolwp(t), B_FALSE);
 
 		/*
 		 * Remove the thread from the all threads list.
@@ -782,6 +788,9 @@
 
 /*
  * fork a kernel process.
+ *
+ * Passing a pid argument of -1 indicates that the new process should be
+ * launched as a child of 'zsched' within the zone.
  */
 int
 newproc(void (*pc)(), caddr_t arg, id_t cid, int pri, struct contract **ct,
@@ -800,6 +809,7 @@
 		rctl_set_t *init_set;
 
 		ASSERT(pid != 1);
+		ASSERT(pid >= 0);
 
 		if (getproc(&p, pid, GETPROC_KERNEL) < 0)
 			return (EAGAIN);
@@ -843,8 +853,18 @@
 		rctl_set_t *init_set;
 		task_t *tk, *tk_old;
 		klwp_t *lwp;
+		boolean_t pzsched = B_FALSE;
+		int flag = GETPROC_USER;
 
-		if (getproc(&p, pid, GETPROC_USER) < 0)
+		/* Handle a new user-level thread as child of zsched. */
+		if (pid < 0) {
+			VERIFY(curzone != global_zone);
+			flag = GETPROC_ZSCHED;
+			pzsched = B_TRUE;
+			pid = 0;
+		}
+
+		if (getproc(&p, pid, flag) < 0)
 			return (EAGAIN);
 		/*
 		 * init creates a new task, distinct from the task
@@ -886,8 +906,11 @@
 		if ((lwp = lwp_create(pc, arg, 0, p, TS_STOPPED, pri,
 		    &curthread->t_hold, cid, 1)) == NULL) {
 			task_t *tk;
+
 			fork_fail(p);
 			mutex_enter(&pidlock);
+			disown_proc(p->p_parent, p);
+
 			mutex_enter(&p->p_lock);
 			tk = p->p_task;
 			task_detach(p);
@@ -894,15 +917,16 @@
 			ASSERT(p->p_pool->pool_ref > 0);
 			atomic_add_32(&p->p_pool->pool_ref, -1);
 			mutex_exit(&p->p_lock);
+
 			pid_exit(p, tk);
 			mutex_exit(&pidlock);
 			task_rele(tk);
-
 			return (EAGAIN);
 		}
 		t = lwptot(lwp);
 
-		ctp = contract_process_fork(sys_process_tmpl, p, curproc,
+		ctp = contract_process_fork(sys_process_tmpl, p,
+		    (pzsched ? curproc->p_zone->zone_zsched : curproc),
 		    B_FALSE);
 		ASSERT(ctp != NULL);
 		if (ct != NULL)
@@ -943,7 +967,11 @@
 	if (zone_status_get(curproc->p_zone) >= ZONE_IS_SHUTTING_DOWN)
 		return (-1);	/* no point in starting new processes */
 
-	pp = (flags & GETPROC_KERNEL) ? &p0 : curproc;
+	if (flags & GETPROC_ZSCHED) {
+		pp = curproc->p_zone->zone_zsched;
+	} else {
+		pp = (flags & GETPROC_KERNEL) ? &p0 : curproc;
+	}
 	task = pp->p_task;
 	proj = task->tk_proj;
 	zone = pp->p_zone;
@@ -1004,6 +1032,9 @@
 	cp->p_t1_lgrpid = LGRP_NONE;
 	cp->p_tr_lgrpid = LGRP_NONE;
 
+	/* Default to native brand initially */
+	cp->p_brand = &native_brand;
+
 	if ((newpid = pid_allocate(cp, pid, PID_ALLOC_PROC)) == -1) {
 		if (nproc == v.v_proc) {
 			CPU_STATS_ADDQ(CPU, sys, procovf, 1);
@@ -1071,9 +1102,6 @@
 	cp->p_flag = pp->p_flag & (SJCTL|SNOWAIT|SNOCD);
 	cp->p_sessp = pp->p_sessp;
 	sess_hold(pp);
-	cp->p_brand = pp->p_brand;
-	if (PROC_IS_BRANDED(pp))
-		BROP(pp)->b_copy_procdata(cp, pp);
 	cp->p_bssbase = pp->p_bssbase;
 	cp->p_brkbase = pp->p_brkbase;
 	cp->p_brksize = pp->p_brksize;
@@ -1153,6 +1181,18 @@
 	mutex_exit(&cp->p_lock);
 	mutex_exit(&pidlock);
 
+	if (PROC_IS_BRANDED(pp)) {
+		/*
+		 * The only reason why process branding should fail is when
+		 * the procedure is complicated by multiple LWPs on the scene.
+		 * With an LWP count of 0, this newly allocated process has no
+		 * reason to fail branding.
+		 */
+		VERIFY0(brand_setbrand(cp, B_FALSE));
+
+		BROP(pp)->b_copy_procdata(cp, pp);
+	}
+
 	avl_create(&cp->p_ct_held, contract_compar, sizeof (contract_t),
 	    offsetof(contract_t, ct_ctlist));
 
