[launchd-changes] [23717] branches/PR-6046664/launchd/src

source_changes at macosforge.org source_changes at macosforge.org
Tue Sep 30 15:33:13 PDT 2008


Revision: 23717
          http://trac.macosforge.org/projects/launchd/changeset/23717
Author:   dsorresso at apple.com
Date:     2008-09-30 15:33:12 -0700 (Tue, 30 Sep 2008)
Log Message:
-----------
Initial set of changes for flattening of the per-user Mach namespace.
Some highlights:
Per-user launchd's now consult the root job manager's MachServices hash for all lookups.
The root user now gets a per-user launchd, no longer uses a sub-manager of the system launchd.
There is now a bstree launchctl subcommand that displays the entire Mach bootstrap tree.
Added bootstrap_lookup_per_user_context() to libbootstrap (private). 
Changed to job_mig_lookup_per_user_context() to forward requests from root-owned processes onto the system launchd if they come through to a per-user launchd first. This will let root processes under a per-user bootstrap look up another per-user bootstrap (i.e. login(1)). This SPI is intended to replace vproc_move_subset_to_user() in the launchd PAM module.
Changed job_mig_lookup_per_user_context() to return the current per-user context if the request's UID matches that of the per-user launchd it went to.
Added bootstrap_lookup_children() to libbootstrap (private).
Added bootstrap_root() to libbootstrap (private). Untested.

Modified Paths:
--------------
    branches/PR-6046664/launchd/src/launchctl.c
    branches/PR-6046664/launchd/src/launchd.c
    branches/PR-6046664/launchd/src/launchd_core_logic.c
    branches/PR-6046664/launchd/src/launchd_runtime.c
    branches/PR-6046664/launchd/src/launchd_runtime.h
    branches/PR-6046664/launchd/src/launchproxy.c
    branches/PR-6046664/launchd/src/libbootstrap.c
    branches/PR-6046664/launchd/src/libbootstrap_private.h
    branches/PR-6046664/launchd/src/libbootstrap_public.h
    branches/PR-6046664/launchd/src/libvproc.c
    branches/PR-6046664/launchd/src/protocol_job.defs
    branches/PR-6046664/launchd/src/protocol_job_forward.defs
    branches/PR-6046664/launchd/src/protocol_job_reply.defs

Modified: branches/PR-6046664/launchd/src/launchctl.c
===================================================================
--- branches/PR-6046664/launchd/src/launchctl.c	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/launchctl.c	2008-09-30 22:33:12 UTC (rev 23717)
@@ -22,6 +22,7 @@
 
 #include "liblaunch_public.h"
 #include "liblaunch_private.h"
+#include "libbootstrap_private.h"
 #include "libbootstrap_public.h"
 #include "libvproc_public.h"
 #include "libvproc_private.h"
@@ -42,7 +43,12 @@
 #include <sys/time.h>
 #include <sys/sysctl.h>
 #include <sys/stat.h>
+
+#ifndef SO_EXECPATH
+	#define SO_EXECPATH 0x1085
+#endif
 #include <sys/socket.h>
+
 #include <sys/un.h>
 #include <sys/fcntl.h>
 #include <sys/event.h>
@@ -180,7 +186,11 @@
 static int getrusage_cmd(int argc, char *const argv[]);
 static int bsexec_cmd(int argc, char *const argv[]);
 static int bslist_cmd(int argc, char *const argv[]);
+static int bstree_cmd(int argc, char * const argv[]);
 
+static int _bslist_cmd(mach_port_t bsport, unsigned int depth);
+static int _bstree_cmd(mach_port_t bsport, unsigned int depth);
+
 static int exit_cmd(int argc, char *const argv[]) __attribute__((noreturn));
 static int help_cmd(int argc, char *const argv[]);
 
@@ -212,9 +222,10 @@
 	{ "umask",	umask_cmd,		"Change launchd's umask" },
 	{ "bsexec",	bsexec_cmd,		"Execute a process within a different Mach bootstrap subset" },
 	{ "bslist",	bslist_cmd,		"List Mach bootstrap services and optional servers" },
+	{ "bstree",	bstree_cmd,		"Show the entire Mach bootstrap tree." },
 	{ "exit",	exit_cmd,		"Exit the interactive invocation of launchctl" },
 	{ "quit",	exit_cmd,		"Quit the interactive invocation of launchctl" },
-	{ "help",	help_cmd,		"This help output" },
+	{ "help",	help_cmd,		"This help output" }
 };
 
 static bool istty;
@@ -1646,7 +1657,7 @@
 
 		if (strcasecmp(session_type, VPROCMGR_SESSION_BACKGROUND) == 0) {
 			read_launchd_conf();
-#if HAVE_SECURITY
+#if 0
 			assumes(SessionCreate(sessionKeepCurrentBootstrap, 0) == 0);
 #endif
 		}
@@ -2546,6 +2557,8 @@
 				return 1;
 			}
 		} while (getrootbs && last_bport != bport);
+	} else if( strcmp(s, "0") == 0 ) {
+		bport = MACH_PORT_NULL;
 	} else {
 		int pid = atoi(s);
 
@@ -2599,18 +2612,14 @@
 }
 
 int
-bslist_cmd(int argc, char *const argv[])
+_bslist_cmd(mach_port_t bport, unsigned int depth)
 {
 	kern_return_t result;
-	mach_port_t bport = bootstrap_port;
 	name_array_t service_names;
 	mach_msg_type_number_t service_cnt, service_active_cnt;
 	bootstrap_status_array_t service_actives;
 	unsigned int i;
 
-	if (argc == 2)
-		bport = str2bsport(argv[1]);
-
 	if (bport == MACH_PORT_NULL) {
 		fprintf(stderr, "Invalid bootstrap port\n");
 		return 1;
@@ -2624,12 +2633,67 @@
 
 #define bport_state(x)	(((x) == BOOTSTRAP_STATUS_ACTIVE) ? "A" : ((x) == BOOTSTRAP_STATUS_ON_DEMAND) ? "D" : "I")
 
-	for (i = 0; i < service_cnt ; i++)
-		fprintf(stdout, "%-3s%s\n", bport_state((service_actives[i])), service_names[i]);
+	for (i = 0; i < service_cnt ; i++) {
+		fprintf(stdout, "%*s%-3s%s\n", depth, "", bport_state((service_actives[i])), service_names[i]);
+	}
 
 	return 0;
 }
 
+int
+bslist_cmd(int argc, char *const argv[])
+{
+	mach_port_t bport = bootstrap_port;
+	if( argc == 2 ) {
+		bport = str2bsport(argv[1]);
+	}
+	
+	if( bport == MACH_PORT_NULL ) {
+		fprintf(stderr, "Invalid bootstrap port\n");
+		return 1;
+	}
+	
+	return _bslist_cmd(bport, 0);
+}
+
+int
+_bstree_cmd(mach_port_t bsport, unsigned int depth)
+{
+	if( bsport == MACH_PORT_NULL ) {
+		fprintf(stderr, "No root port!\n");
+		return 1;
+	}
+
+	mach_port_array_t child_ports = NULL;
+	name_array_t child_names = NULL;
+	unsigned int cnt = 0;
+
+	kern_return_t kr = bootstrap_lookup_children(bsport, &child_ports, &child_names, (mach_msg_type_number_t *)&cnt);
+	if( kr != BOOTSTRAP_SUCCESS && kr != BOOTSTRAP_NO_CHILDREN ) {
+		fprintf(stderr, "%s(): bootstrap_lookup_children(): %d\n", __func__, kr);
+		return 1;
+	}
+
+	unsigned int i = 0;
+	_bslist_cmd(bsport, depth);
+	
+	for( i = 0; i < cnt; i++ ) {
+		fprintf(stdout, "%*s%s/\n", depth, "", child_names[i]);
+		if( child_ports[i] != MACH_PORT_NULL ) {
+			_bstree_cmd(child_ports[i], depth + 4);
+		}
+	}
+	
+	return 0;
+}
+
+int
+bstree_cmd(int argc __attribute__((unused)), char * const argv[] __attribute__((unused)))
+{	
+	fprintf(stdout, "System/\n");
+	return _bstree_cmd(str2bsport("/"), 4);
+}
+
 bool
 is_legacy_mach_job(launch_data_t obj)
 {

Modified: branches/PR-6046664/launchd/src/launchd.c
===================================================================
--- branches/PR-6046664/launchd/src/launchd.c	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/launchd.c	2008-09-30 22:33:12 UTC (rev 23717)
@@ -106,11 +106,15 @@
 bool shutdown_in_progress;
 bool fake_shutdown_in_progress;
 bool network_up;
-char g_username[128] = "__UnknownUserToLaunchd_DontPanic_NotImportant__";
+char *g_username = "__UninitializedUser__";
 
 int
 main(int argc, char *const *argv)
 {
+	if( getpid() == 1 ) {
+		printf("launchd[1] is starting.\n");
+	}
+	
 	const char *stdouterr_path = low_level_debug ? _PATH_CONSOLE : _PATH_DEVNULL;
 	bool sflag = false;
 	int ch;
@@ -162,12 +166,9 @@
 
 		int64_t now = runtime_get_wall_time();
 		
-		struct passwd *pwent = getpwuid(getuid());
-		if( pwent ) {
-			strlcpy(g_username, pwent->pw_name, sizeof(g_username) - 1);
-		}
+		g_username = getenv("LOGNAME");
 		
-		runtime_syslog(LOG_NOTICE, "Per-user launchd for UID %u (%s) began at: %lld.%06llu", getuid(), g_username, now / USEC_PER_SEC, now % USEC_PER_SEC);
+		runtime_syslog(LOG_DEBUG, "Per-user launchd for UID %u (%s) began at: %lld.%06llu", getuid(), g_username, now / USEC_PER_SEC, now % USEC_PER_SEC);
 	}
 
 	monitor_networking_state();
@@ -313,7 +314,7 @@
 	now = runtime_get_wall_time();
 
 	char *term_who = pid1_magic ? "System shutdown" : "Per-user launchd termination";
-	runtime_syslog(LOG_NOTICE, "%s began at: %lld.%06llu", term_who, now / USEC_PER_SEC, now % USEC_PER_SEC);
+	runtime_syslog(LOG_DEBUG, "%s began at: %lld.%06llu", term_who, now / USEC_PER_SEC, now % USEC_PER_SEC);
 
 	launchd_assert(jobmgr_shutdown(root_jobmgr) != NULL);
 }
@@ -336,6 +337,7 @@
 launchd_SessionCreate(void)
 {
 #if HAVE_SECURITY
+	runtime_syslog(LOG_NOTICE, "%s(): Called.", __func__);
 	OSStatus (*sescr)(SessionCreationFlags flags, SessionAttributeBits attributes);
 	void *seclib;
 

Modified: branches/PR-6046664/launchd/src/launchd_core_logic.c
===================================================================
--- branches/PR-6046664/launchd/src/launchd_core_logic.c	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/launchd_core_logic.c	2008-09-30 22:33:12 UTC (rev 23717)
@@ -289,9 +289,9 @@
 	kq_callback kqjobmgr_callback;
 	SLIST_ENTRY(jobmgr_s) sle;
 	SLIST_HEAD(, jobmgr_s) submgrs;
+	LIST_HEAD(, machservice) ms_hash[MACHSERVICE_HASH_SIZE];
 	LIST_HEAD(, job_s) jobs;
 	LIST_HEAD(, job_s) active_jobs[ACTIVE_JOB_HASH_SIZE];
-	LIST_HEAD(, machservice) ms_hash[MACHSERVICE_HASH_SIZE];
 	LIST_HEAD(, job_s) global_env_jobs;
 	mach_port_t jm_port;
 	mach_port_t req_port;
@@ -308,7 +308,7 @@
 };
 
 #define jobmgr_assumes(jm, e)	\
-	(unlikely(!(e)) ? jobmgr_log_bug(jm, __LINE__), false : true)
+	(unlikely(!(e)) ? jobmgr_log_bug(jm, __LINE__, #e), false : true)
 
 static jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name);
 static job_t jobmgr_import2(jobmgr_t jm, launch_data_t pload);
@@ -331,7 +331,7 @@
 static void jobmgr_logv(jobmgr_t jm, int pri, int err, const char *msg, va_list ap) __attribute__((format(printf, 4, 0)));
 static void jobmgr_log(jobmgr_t jm, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4)));
 /* static void jobmgr_log_error(jobmgr_t jm, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); */
-static void jobmgr_log_bug(jobmgr_t jm, unsigned int line);
+static void jobmgr_log_bug(jobmgr_t jm, unsigned int line, const char *test);
 
 #define AUTO_PICK_LEGACY_LABEL (const char *)(~0)
 
@@ -453,7 +453,7 @@
 
 
 #define job_assumes(j, e)	\
-	(unlikely(!(e)) ? job_log_bug(j, __LINE__), false : true)
+	(unlikely(!(e)) ? job_log_bug(j, __LINE__, #e), false : true)
 
 static void job_import_keys(launch_data_t obj, const char *key, void *context);
 static void job_import_bool(job_t j, const char *key, bool value);
@@ -480,7 +480,6 @@
 static void job_log_pids_with_weird_uids(job_t j);
 static void job_force_sampletool(job_t j);
 static void job_setup_exception_port(job_t j, task_t target_task);
-static void job_reparent_hack(job_t j, const char *where);
 INTERNAL_ABI static void job_callback(void *obj, struct kevent *kev);
 static void job_callback_proc(job_t j, int fflags);
 static void job_callback_timer(job_t j, void *ident);
@@ -495,7 +494,7 @@
 static void job_log_stdouterr(job_t j);
 static void job_logv(job_t j, int pri, int err, const char *msg, va_list ap) __attribute__((format(printf, 4, 0)));
 static void job_log_error(job_t j, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4)));
-static void job_log_bug(job_t j, unsigned int line);
+static void job_log_bug(job_t j, unsigned int line, const char *test);
 static void job_log_stdouterr2(job_t j, const char *msg, ...);
 static void job_set_exeception_port(job_t j, mach_port_t port);
 static kern_return_t job_handle_mpm_wait(job_t j, mach_port_t srp, int *waitstatus);
@@ -526,7 +525,6 @@
 
 /* miscellaneous file local functions */
 static size_t get_kern_max_proc(void);
-static void ensure_root_bkgd_setup(void);
 static int dir_has_files(job_t j, const char *path);
 static char **mach_cmd2argv(const char *string);
 static size_t our_strhash(const char *s) __attribute__((pure));
@@ -540,7 +538,6 @@
 static mach_port_t the_exception_server;
 static bool did_first_per_user_launchd_BootCache_hack;
 #define JOB_BOOTCACHE_HACK_CHECK(j)	(unlikely(j->per_user && !did_first_per_user_launchd_BootCache_hack && (j->mach_uid >= 500) && (j->mach_uid != (uid_t)-2)))
-static jobmgr_t background_jobmgr;
 static job_t workaround_5477111;
 
 /* process wide globals */
@@ -871,7 +868,7 @@
 	jobmgr_t jmi;
 	job_t ji;
 
-	jobmgr_log(jm, LOG_DEBUG, "Removed job manager");
+	jobmgr_log(jm, LOG_NOTICE, "Removed job manager");
 
 	if (!jobmgr_assumes(jm, SLIST_EMPTY(&jm->submgrs))) {
 		while ((jmi = SLIST_FIRST(&jm->submgrs))) {
@@ -893,10 +890,6 @@
 		jobmgr_assumes(jm, launchd_mport_close_recv(jm->jm_port) == KERN_SUCCESS);
 	}
 
-	if (jm == background_jobmgr) {
-		background_jobmgr = NULL;
-	}
-
 	if (jm->parentmgr) {
 		runtime_del_weak_ref();
 		SLIST_REMOVE(&jm->parentmgr->submgrs, jm, jobmgr_s, sle);
@@ -1283,8 +1276,7 @@
 	}
 
 	if (jp && !jp->anonymous && unlikely(!(kp.kp_proc.p_flag & P_EXEC))) {
-		job_log(jp, LOG_APPLEONLY, "Called *fork(). Please switch to posix_spawn*(), pthreads or launchd. Child PID %u",
-				kp.kp_proc.p_pid);
+		job_log(jp, LOG_APPLEONLY, "Called *fork(). Please switch to posix_spawn*(), pthreads or launchd. Child PID %u", kp.kp_proc.p_pid);
 	}
 
 
@@ -1358,6 +1350,7 @@
 			strlcpy(tmp_path, argv[0], sizeof(tmp_path));
 			bn = basename(tmp_path); /* prog for auto labels is kp.kp_kproc.p_comm */
 		}
+		
 		snprintf(auto_label, sizeof(auto_label), "%s.%s", sizeof(void *) == 8 ? "0xdeadbeeffeedface" : "0xbabecafe", bn);
 		label = auto_label;
 		/* This is so we can do gross things later. See NOTE_EXEC for anonymous jobs */
@@ -1625,7 +1618,6 @@
 		} else if (strcasecmp(key, LAUNCH_JOBKEY_LIMITLOADFROMHOSTS) == 0) {
 			return;
 		} else if (strcasecmp(key, LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE) == 0) {
-			job_reparent_hack(j, value);
 			return;
 		}
 		break;
@@ -2199,7 +2191,6 @@
 	struct ldcred *ldc = runtime_get_caller_creds();
 	job_t jr;
 
-
 	jr = job_mig_intran2(root_jobmgr, p, ldc->pid);
 
 	if (!jobmgr_assumes(root_jobmgr, jr != NULL)) {
@@ -3624,7 +3615,7 @@
 }
 
 void
-jobmgr_log_bug(jobmgr_t jm, unsigned int line)
+jobmgr_log_bug(jobmgr_t jm, unsigned int line, const char *test)
 {
 	static const char *file;
 	int saved_errno = errno;
@@ -3645,14 +3636,14 @@
 
 	/* the only time 'jm' should not be set is if setting up the first bootstrap fails for some reason */
 	if (likely(jm)) {
-		jobmgr_log(jm, LOG_NOTICE, "Bug: %s:%u (%s):%u", file, line, buf, saved_errno);
+		jobmgr_log(jm, LOG_NOTICE, "Bug: %s:%u (%s):%u %s", file, line, buf, saved_errno, test);
 	} else {
-		runtime_syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u", file, line, buf, saved_errno);
+		runtime_syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u %s", file, line, buf, saved_errno, test);
 	}
 }
 
 void
-job_log_bug(job_t j, unsigned int line)
+job_log_bug(job_t j, unsigned int line, const char *test)
 {
 	static const char *file;
 	int saved_errno = errno;
@@ -3673,9 +3664,9 @@
 
 	/* I cannot think of any reason why 'j' should ever be NULL, nor have I ever seen the case in the wild */
 	if (likely(j)) {
-		job_log(j, LOG_NOTICE, "Bug: %s:%u (%s):%u", file, line, buf, saved_errno);
+		job_log(j, LOG_NOTICE, "Bug: %s:%u (%s):%u %s", file, line, buf, saved_errno, test);
 	} else {
-		runtime_syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u", file, line, buf, saved_errno);
+		runtime_syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u %s", file, line, buf, saved_errno, test);
 	}
 }
 
@@ -4553,10 +4544,16 @@
 	}
 
 	SLIST_INSERT_HEAD(&j->machservices, ms, sle);
-	LIST_INSERT_HEAD(&j->mgr->ms_hash[hash_ms(ms->name)], ms, name_hash_sle);
+	
+	if( pid1_magic ) {
+		LIST_INSERT_HEAD(&j->mgr->ms_hash[hash_ms(ms->name)], ms, name_hash_sle);
+	} else {
+		LIST_INSERT_HEAD(&root_jobmgr->ms_hash[hash_ms(ms->name)], ms, name_hash_sle);
+	}
+	
 	LIST_INSERT_HEAD(&port_hash[HASH_PORT(ms->port)], ms, port_hash_sle);
 
-	job_log(j, LOG_INFO, "Mach service added: %s", name);
+	jobmgr_log(j->mgr, LOG_NOTICE, "Mach service %s added.", name);
 
 	return ms;
 out_bad2:
@@ -4998,7 +4995,7 @@
 		}
 	}
 
-	jobmgr_log(jmr, LOG_DEBUG, "Created job manager%s%s", jm ? " with parent: " : ".", jm ? jm->name : "");
+	jobmgr_log(jmr, LOG_NOTICE, "Created job manager%s%s", jm ? " with parent: " : ".", jm ? jm->name : "");
 
 	if (bootstrapper) {
 		jobmgr_assumes(jmr, job_dispatch(bootstrapper, true) != NULL);
@@ -5020,6 +5017,8 @@
 job_t
 jobmgr_init_session(jobmgr_t jm, const char *session_type, bool sflag)
 {
+	jobmgr_log(jm, LOG_NOTICE, "%s(): Bootstrapping %s.", __func__, session_type);
+	
 	const char *bootstrap_tool[] = { "/bin/launchctl", "bootstrap", "-S", session_type, sflag ? "-s" : NULL, NULL };
 	char thelabel[1000];
 	job_t bootstrapper;
@@ -5087,37 +5086,60 @@
 
 struct machservice *
 jobmgr_lookup_service(jobmgr_t jm, const char *name, bool check_parent, pid_t target_pid)
-{
+{	
 	struct machservice *ms;
 	job_t target_j;
 
+	jobmgr_log(jm, LOG_DEBUG, "%s(): Got lookup request for \"%s\"", __func__, name);
+
 	if (target_pid) {
-		//jobmgr_assumes(jm, !check_parent);
+		jobmgr_assumes(jm, !check_parent);
 
 		if (unlikely((target_j = jobmgr_find_by_pid(jm, target_pid, false)) == NULL)) {
+			jobmgr_log(jm, LOG_DEBUG, "%s(): Couldn't find PID %u in this bootstrap.", __func__, target_pid);
 			return NULL;
 		}
 
+		job_log(target_j, LOG_DEBUG, "%s(): Found target job.", __func__);
+
 		SLIST_FOREACH(ms, &target_j->machservices, sle) {
 			if (ms->per_pid && strcmp(name, ms->name) == 0) {
 				return ms;
 			}
 		}
 
+		job_log(target_j, LOG_DEBUG, "%s(): Couldn't find service \"%s\" in job, giving up.", __func__, name);
 		return NULL;
 	}
+	
+	if( pid1_magic ) {
+		LIST_FOREACH(ms, &jm->ms_hash[hash_ms(name)], name_hash_sle) {
+			if (!ms->per_pid && strcmp(name, ms->name) == 0) {
+				return ms;
+			}
+		}
+		
+		if (jm->parentmgr == NULL || !check_parent) {
+			jobmgr_log(jm, LOG_DEBUG, "%s(): Couldn't find \"%s\" in this bootstrap, giving up.", __func__, name);
+			return NULL;
+		}
 
-	LIST_FOREACH(ms, &jm->ms_hash[hash_ms(name)], name_hash_sle) {
-		if (!ms->per_pid && strcmp(name, ms->name) == 0) {
-			return ms;
+		jobmgr_log(jm, LOG_DEBUG, "%s(): Couldn't find \"%s\" in this bootstrap, recursing...", __func__, name);
+		
+		return jobmgr_lookup_service(jm->parentmgr, name, true, 0);
+	} else {
+		LIST_FOREACH(ms, &root_jobmgr->ms_hash[hash_ms(name)], name_hash_sle) {
+			if (!ms->per_pid && strcmp(name, ms->name) == 0) {
+				return ms;
+			}
 		}
-	}
-
-	if (jm->parentmgr == NULL || !check_parent) {
+		
+		jobmgr_log(jm, LOG_DEBUG, "%s(): Couldn't find \"%s\" in this (flat) bootstrap.", __func__, name);
+		
 		return NULL;
 	}
-
-	return jobmgr_lookup_service(jm->parentmgr, name, true, 0);
+	
+	return NULL;
 }
 
 mach_port_t
@@ -5901,9 +5923,7 @@
 }
 
 kern_return_t
-job_mig_swap_complex(job_t j, vproc_gsk_t inkey, vproc_gsk_t outkey,
-		vm_offset_t inval, mach_msg_type_number_t invalCnt,
-		vm_offset_t *outval, mach_msg_type_number_t *outvalCnt) 
+job_mig_swap_complex(job_t j, vproc_gsk_t inkey, vproc_gsk_t outkey, vm_offset_t inval, mach_msg_type_number_t invalCnt, vm_offset_t *outval, mach_msg_type_number_t *outvalCnt) 
 {
 	const char *action;
 	launch_data_t input_obj, output_obj;
@@ -6272,23 +6292,8 @@
 	return 0;
 }
 
-void
-ensure_root_bkgd_setup(void)
-{
-	if (likely(background_jobmgr) || !pid1_magic) {
-		return;
-	}
-
-	if (!jobmgr_assumes(root_jobmgr, (background_jobmgr = jobmgr_new(root_jobmgr, mach_task_self(), MACH_PORT_NULL, false, VPROCMGR_SESSION_BACKGROUND)) != NULL)) {
-		return;
-	}
-
-	background_jobmgr->req_port = 0;
-	jobmgr_assumes(root_jobmgr, launchd_mport_make_send(background_jobmgr->jm_port) == KERN_SUCCESS);
-}
-
 kern_return_t
-job_mig_lookup_per_user_context(job_t j, uid_t which_user, mach_port_t *up_cont)
+job_mig_lookup_per_user_context(job_t j, mach_port_t srp, uid_t which_user, mach_port_t *up_cont)
 {
 	struct ldcred *ldc = runtime_get_caller_creds();
 	job_t ji;
@@ -6297,27 +6302,40 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	job_log(j, LOG_DEBUG, "Looking up per user launchd for UID: %u", which_user);
+	if( j->per_user ) {
+		job_log(j, LOG_NOTICE, "Got per-user lookup request from per-user launchd %u.", j->mach_uid);
+	}
 
 	if (unlikely(!pid1_magic)) {
-		job_log(j, LOG_ERR, "Only PID 1 supports per user launchd lookups.");
+		if( which_user == getuid() ) {
+			job_log(j, LOG_NOTICE, "Request for local per-user bootstrap (%u). Returning bootstrap port.", which_user);
+			
+			launchd_mport_make_send(root_jobmgr->jm_port);
+			*up_cont = root_jobmgr->jm_port;
+			return BOOTSTRAP_SUCCESS;
+		} else if( ldc->euid == 0 ) {
+			job_log(j, LOG_NOTICE, "Forwarding request for %u's per-user launchd to system launchd.", which_user);
+			/* Forward the request onto the system launchd. */
+			job_assumes(j, vproc_mig_lookup_per_user_context_forward(inherited_bootstrap_port, srp, which_user) == 0);
+			
+			/* Have the client wait for the system launchd to get back to it. */
+			return MIG_NO_REPLY;
+		} else {
+			job_log(j, LOG_ERR, "Only PID 1 supports non-local per user launchd lookups.");
+		}
+		
 		return BOOTSTRAP_NOT_PRIVILEGED;
 	}
 
-	if (ldc->euid || ldc->uid) {
+	/* If the request came from a per-user launchd, it was forwarded on behalf of a root-owned client. */
+	if( !j->per_user && (ldc->euid || ldc->uid) ) {
 		which_user = ldc->euid ?: ldc->uid;
 	}
 
+	job_log(j, LOG_NOTICE, "Looking up per user launchd for UID: %u", which_user);
+
 	*up_cont = MACH_PORT_NULL;
 
-	if (which_user == 0) {
-		ensure_root_bkgd_setup();
-
-		*up_cont = background_jobmgr->jm_port;
-
-		return 0;
-	}
-
 	LIST_FOREACH(ji, &root_jobmgr->jobs, sle) {
 		if (!ji->per_user) {
 			continue;
@@ -6366,6 +6384,7 @@
 	}
 
 	if (job_assumes(j, ji != NULL)) {
+		launchd_mport_copy_send(machservice_port(SLIST_FIRST(&ji->machservices)));
 		*up_cont = machservice_port(SLIST_FIRST(&ji->machservices));
 	}
 
@@ -6384,12 +6403,15 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
+	job_log(j, LOG_NOTICE, "%s(): Checking in service \"%s\"%s.", __func__, servicename, per_pid_service ? " as a per-PID service" : "");
 	ms = jobmgr_lookup_service(j->mgr, servicename, false, per_pid_service ? ldc->pid : 0);
 
 	if (ms == NULL) {
+		job_log(j, LOG_NOTICE, "%s(): Service \"%s\" not found.", __func__, servicename);
 		*serviceportp = MACH_PORT_NULL;
 
 		if (unlikely((ms = machservice_new(j, servicename, serviceportp, per_pid_service)) == NULL)) {
+			job_log(j, LOG_NOTICE, "%s(): Creating service \"%s\" failed.", __func__, servicename);
 			return BOOTSTRAP_NO_MEMORY;
 		}
 
@@ -6438,7 +6460,7 @@
 		job_log(j, LOG_APPLEONLY, "Performance: bootstrap_register() is deprecated. Service: %s", servicename);
 	}
 
-	job_log(j, LOG_DEBUG, "%sMach service registration attempt: %s", flags & BOOTSTRAP_PER_PID_SERVICE ? "Per PID " : "", servicename);
+	job_log(j, LOG_NOTICE, "%sMach service registration attempt: %s", flags & BOOTSTRAP_PER_PID_SERVICE ? "Per PID " : "", servicename);
 
 	/* 5641783 for the embedded hack */
 #if !TARGET_OS_EMBEDDED
@@ -6583,54 +6605,52 @@
 }
 
 kern_return_t
-job_mig_info(job_t j, name_array_t *servicenamesp, unsigned int *servicenames_cnt,
-		bootstrap_status_array_t *serviceactivesp, unsigned int *serviceactives_cnt)
+job_mig_info(job_t j, name_array_t *servicenamesp, unsigned int *servicenames_cnt, bootstrap_status_array_t *serviceactivesp, unsigned int *serviceactives_cnt)
 {
-	name_array_t service_names = NULL;
-	bootstrap_status_array_t service_actives = NULL;
-	unsigned int cnt = 0, cnt2 = 0;
-	struct machservice *ms;
-	jobmgr_t jm;
-	job_t ji;
-
-	if (!launchd_assumes(j != NULL)) {
+	if( !launchd_assumes(j != NULL) ) {
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	jm = j->mgr;
-
-	LIST_FOREACH(ji, &jm->jobs, sle) {
-		SLIST_FOREACH(ms, &ji->machservices, sle) {
-			if (!ms->per_pid) {
+	jobmgr_t jm = j->mgr;
+	struct machservice *msi = NULL;
+	unsigned int cnt = 0;
+	
+	unsigned int i = 0;
+	for( i = 0; i < MACHSERVICE_HASH_SIZE; i++ ) {
+		LIST_FOREACH( msi, &jm->ms_hash[i], name_hash_sle ) {
+			if( !msi->per_pid ) {
 				cnt++;
 			}
 		}
 	}
 
-	if (cnt == 0) {
+	if( cnt == 0 ) {
 		goto out;
 	}
 
+	name_array_t service_names = NULL;
 	mig_allocate((vm_address_t *)&service_names, cnt * sizeof(service_names[0]));
-	if (!job_assumes(j, service_names != NULL)) {
+	if( !job_assumes(j, service_names != NULL) ) {
 		goto out_bad;
 	}
 
+	bootstrap_status_array_t service_actives = NULL;
 	mig_allocate((vm_address_t *)&service_actives, cnt * sizeof(service_actives[0]));
-	if (!job_assumes(j, service_actives != NULL)) {
+	if( !job_assumes(j, service_actives != NULL) ) {
 		goto out_bad;
 	}
 
-	LIST_FOREACH(ji, &jm->jobs, sle) {
-		SLIST_FOREACH(ms, &ji->machservices, sle) {
-			if (!ms->per_pid) {
-				strlcpy(service_names[cnt2], machservice_name(ms), sizeof(service_names[0]));
-				service_actives[cnt2] = machservice_status(ms);
+	unsigned int cnt2 = 0;
+	for( i = 0; i < MACHSERVICE_HASH_SIZE; i++ ) {
+		LIST_FOREACH( msi, &jm->ms_hash[i], name_hash_sle ) {
+			if( !msi->per_pid ) {
+				strlcpy(service_names[cnt2], machservice_name(msi), sizeof(service_names[0]));
+				service_actives[cnt2] = machservice_status(msi);
 				cnt2++;
 			}
 		}
 	}
-
+	
 	job_assumes(j, cnt == cnt2);
 
 out:
@@ -6651,59 +6671,6 @@
 	return BOOTSTRAP_NO_MEMORY;
 }
 
-void
-job_reparent_hack(job_t j, const char *where)
-{
-	jobmgr_t jmi, jmi2;
-
-	ensure_root_bkgd_setup();
-
-	/* NULL is only passed for our custom API for LaunchServices. If that is the case, we do magic. */
-	if (where == NULL) {
-		if (strcasecmp(j->mgr->name, VPROCMGR_SESSION_LOGINWINDOW) == 0) {
-			where = VPROCMGR_SESSION_LOGINWINDOW;
-		} else {
-			where = VPROCMGR_SESSION_AQUA;
-		}
-	}
-
-	if (strcasecmp(j->mgr->name, where) == 0) {
-		return;
-	}
-
-	SLIST_FOREACH(jmi, &root_jobmgr->submgrs, sle) {
-		if (unlikely(jmi->shutting_down)) {
-			continue;
-		} else if (strcasecmp(jmi->name, where) == 0) {
-			goto jm_found;
-		} else if (strcasecmp(jmi->name, VPROCMGR_SESSION_BACKGROUND) == 0 && pid1_magic) {
-			SLIST_FOREACH(jmi2, &jmi->submgrs, sle) {
-				if (strcasecmp(jmi2->name, where) == 0) {
-					jmi = jmi2;
-					goto jm_found;
-				}
-			}
-		}
-	}
-
-jm_found:
-	if (job_assumes(j, jmi != NULL)) {
-		struct machservice *msi;
-
-		SLIST_FOREACH(msi, &j->machservices, sle) {
-			LIST_REMOVE(msi, name_hash_sle);
-		}
-
-		LIST_REMOVE(j, sle);
-		LIST_INSERT_HEAD(&jmi->jobs, j, sle);
-		j->mgr = jmi;
-
-		SLIST_FOREACH(msi, &j->machservices, sle) {
-			LIST_INSERT_HEAD(&j->mgr->ms_hash[hash_ms(msi->name)], msi, name_hash_sle);
-		}
-	}
-}
-
 kern_return_t
 job_mig_move_subset(job_t j, mach_port_t target_subset, name_t session_type)
 {
@@ -6723,50 +6690,9 @@
 		job_t j2;
 
 		if (j->mgr->session_initialized) {
-			if (ldc->uid == 0 && pid1_magic) {
-				if (strcmp(j->mgr->name, VPROCMGR_SESSION_LOGINWINDOW) == 0) {
-					job_t ji, jn;
-
-					LIST_FOREACH_SAFE(ji, &j->mgr->jobs, sle, jn) {
-						if (!ji->anonymous) {
-							job_remove(ji);
-						}
-					}
-
-					ensure_root_bkgd_setup();
-
-					SLIST_REMOVE(&j->mgr->parentmgr->submgrs, j->mgr, jobmgr_s, sle);
-					j->mgr->parentmgr = background_jobmgr;
-					SLIST_INSERT_HEAD(&j->mgr->parentmgr->submgrs, j->mgr, sle);
-
-					/*
-					 * We really should wait for all the jobs to die before proceeding. See 5351245 for more info.
-					 *
-					 * We have hacked around this in job_find() by ignoring jobs that are pending removal.
-					 */
-
-				} else if (strcmp(j->mgr->name, VPROCMGR_SESSION_AQUA) == 0) {
-					job_log(j, LOG_DEBUG, "Tried to move the Aqua session.");
-					return 0;
-				} else if (strcmp(j->mgr->name, VPROCMGR_SESSION_BACKGROUND) == 0) {
-					job_log(j, LOG_DEBUG, "Tried to move the background session.");
-					return 0;
-				} else {
-					job_log(j, LOG_ERR, "Tried to initialize an already setup session!");
-					kr = BOOTSTRAP_NOT_PRIVILEGED;
-					goto out;
-				}
-			} else {
-				job_log(j, LOG_ERR, "Tried to initialize an already setup session!");
-				kr = BOOTSTRAP_NOT_PRIVILEGED;
-				goto out;
-			}
-		} else if (ldc->uid == 0 && pid1_magic && strcmp(session_type, VPROCMGR_SESSION_STANDARDIO) == 0) {
-			ensure_root_bkgd_setup();
-
-			SLIST_REMOVE(&j->mgr->parentmgr->submgrs, j->mgr, jobmgr_s, sle);
-			j->mgr->parentmgr = background_jobmgr;
-			SLIST_INSERT_HEAD(&j->mgr->parentmgr->submgrs, j->mgr, sle);
+			job_log(j, LOG_ERR, "Tried to initialize an already setup session!");
+			kr = BOOTSTRAP_NOT_PRIVILEGED;
+			goto out;
 		} else if (strcmp(session_type, VPROCMGR_SESSION_LOGINWINDOW) == 0) {
 			jobmgr_t jmi;
 
@@ -6794,7 +6720,7 @@
 			}
 		}
 
-		jobmgr_log(j->mgr, LOG_DEBUG, "Renaming to: %s", session_type);
+		jobmgr_log(j->mgr, LOG_NOTICE, "Renaming to: %s", session_type);
 		strcpy(j->mgr->name_init, session_type);
 
 		if (job_assumes(j, (j2 = jobmgr_init_session(j->mgr, session_type, false)))) {
@@ -6810,7 +6736,7 @@
 		goto out;
 	}
 
-	job_log(j, LOG_DEBUG, "Move subset attempt: 0x%x", target_subset);
+	job_log(j, LOG_NOTICE, "Move subset attempt: 0x%x", target_subset);
 
 	kr = _vproc_grab_subset(target_subset, &reqport, &rcvright, &out_obj_array, &l2l_ports, &l2l_port_cnt);
 
@@ -6877,9 +6803,7 @@
 }
 
 kern_return_t
-job_mig_take_subset(job_t j, mach_port_t *reqport, mach_port_t *rcvright,
-		vm_offset_t *outdata, mach_msg_type_number_t *outdataCnt,
-		mach_port_array_t *portsp, unsigned int *ports_cnt)
+job_mig_take_subset(job_t j, mach_port_t *reqport, mach_port_t *rcvright, vm_offset_t *outdata, mach_msg_type_number_t *outdataCnt, mach_port_array_t *portsp, unsigned int *ports_cnt)
 {
 	launch_data_t tmp_obj, tmp_dict, outdata_obj_array = NULL;
 	mach_port_array_t ports = NULL;
@@ -6889,7 +6813,10 @@
 	jobmgr_t jm;
 	job_t ji;
 
+	jobmgr_log(j->mgr, LOG_NOTICE, "%s(): Called from %s.", __func__, j->label);
+
 	if (!launchd_assumes(j != NULL)) {
+		runtime_syslog(LOG_NOTICE, "%s(): Called with NULL job.", __func__);
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
@@ -6912,7 +6839,7 @@
 		return BOOTSTRAP_NOT_PRIVILEGED;
 	}
 
-	job_log(j, LOG_DEBUG, "Transferring sub-bootstrap to the per session launchd.");
+	job_log(j, LOG_NOTICE, "Transferring sub-bootstrap to the per session launchd.");
 
 	outdata_obj_array = launch_data_alloc(LAUNCH_DATA_ARRAY);
 	if (!job_assumes(j, outdata_obj_array)) {
@@ -6944,6 +6871,8 @@
 			continue;
 		}
 
+		jobmgr_log(j->mgr, LOG_NOTICE, "%s(%s, ...): Packing up %s for transfer...", __func__, j->label, ji->label);
+
 		SLIST_FOREACH(ms, &ji->machservices, sle) {
 			if (job_assumes(j, (tmp_dict = launch_data_alloc(LAUNCH_DATA_DICTIONARY)))) {
 				job_assumes(j, launch_data_array_set_index(outdata_obj_array, tmp_dict, cnt2));
@@ -7013,6 +6942,7 @@
 		mig_deallocate((vm_address_t)ports, cnt * sizeof(ports[0]));
 	}
 
+	
 	return BOOTSTRAP_NO_MEMORY;
 }
 
@@ -7160,7 +7090,7 @@
 		uid_t kp_uid = kp.kp_eproc.e_pcred.p_ruid;
 
 		if( ldc->euid == kp_euid ) {
-			job_log(j, LOG_WARNING, "Working around rdar://problem/5982485 and allowing job to set policy for PID %u. We should discuss having %s run under a per-user launchd.", target_pid, target_j->label);
+			job_log(j, LOG_DEBUG, "Working around rdar://problem/5982485 and allowing job to set policy for PID %u.", target_pid);
 		} else {
 			job_log(j, LOG_ERR, "Denied Mach service policy update requested by UID/EUID %u/%u against PID %u with UID/EUID %u/%u due to mismatched credentials.", ldc->uid, ldc->euid, target_pid, kp_uid, kp_euid);
 
@@ -7236,8 +7166,6 @@
 		}
 	}
 
-	job_reparent_hack(jr, NULL);
-
 	if (pid1_magic) {
 		jr->mach_uid = ldc->uid;
 	}
@@ -7352,6 +7280,102 @@
 	return true;
 }
 
+kern_return_t
+job_mig_lookup_children(job_t j, mach_port_array_t *child_ports, unsigned int *child_ports_cnt, name_array_t *child_names, unsigned int *child_names_cnt)
+{
+	kern_return_t kr = BOOTSTRAP_NO_MEMORY;
+	if( !launchd_assumes(j != NULL) ) {
+		return BOOTSTRAP_NO_MEMORY;
+	}
+
+	unsigned int cnt = 0;
+
+	jobmgr_t jmr = j->mgr;
+	jobmgr_t jmi = NULL;
+	SLIST_FOREACH( jmi, &jmr->submgrs, sle ) {
+		cnt++;
+	}
+	
+	job_t ji = NULL;
+	LIST_FOREACH( ji, &jmr->jobs, sle ) {
+		if( ji->per_user ) {
+			cnt++;
+		}
+	}
+	
+	if( cnt == 0 ) {
+		return BOOTSTRAP_NO_CHILDREN;
+	}
+	
+	mach_port_array_t _child_ports = NULL;
+	mig_allocate((vm_address_t *)&_child_ports, cnt * sizeof(_child_ports[0]));
+	if( !job_assumes(j, _child_ports != NULL) ) {
+		kr = BOOTSTRAP_NO_MEMORY;
+		goto out_bad;
+	}
+
+	name_array_t _child_names = NULL;
+	mig_allocate((vm_address_t *)&_child_names, cnt * sizeof(_child_names[0]));
+	if( !job_assumes(j, _child_ports != NULL) ) {
+		kr = BOOTSTRAP_NO_MEMORY;
+		goto out_bad;
+	}
+	
+	unsigned int cnt2 = 0;
+	SLIST_FOREACH( jmi, &jmr->submgrs, sle ) {
+		if( jobmgr_assumes(jmi, launchd_mport_make_send(jmi->jm_port)) == KERN_SUCCESS ) {
+			_child_ports[cnt2] = jmi->jm_port;
+		} else {
+			_child_ports[cnt2] = MACH_PORT_NULL;
+		}
+		
+		strlcpy(_child_names[cnt2], jmi->name, sizeof(_child_names[0]));
+		cnt2++;
+	}
+	
+	LIST_FOREACH( ji, &jmr->jobs, sle ) {
+		if( ji->per_user ) {
+			if( job_assumes(ji, SLIST_FIRST(&ji->machservices)->per_user_hack == true) ) {
+				mach_port_t port = machservice_port(SLIST_FIRST(&ji->machservices));
+				
+				if( job_assumes(ji, launchd_mport_copy_send(port)) == KERN_SUCCESS ) {
+					_child_ports[cnt2] = port;
+				} else {
+					_child_ports[cnt2] = MACH_PORT_NULL;
+				}
+			} else {
+				_child_ports[cnt2] = MACH_PORT_NULL;
+			}
+			
+			strlcpy(_child_names[cnt2], ji->label, sizeof(_child_names[0]));
+			cnt2++;
+		}
+	}
+	
+	*child_names_cnt = cnt;
+	*child_ports_cnt = cnt;
+
+	*child_names = _child_names;
+	*child_ports = _child_ports;
+		
+	unsigned int i = 0;
+	for( i = 0; i < cnt; i++ ) {
+		job_log(j, LOG_DEBUG, "child_names[%u] = %s", i, (char *)_child_names[i]);
+	}
+
+	return BOOTSTRAP_SUCCESS;
+out_bad:
+	if( _child_ports ) {
+		mig_deallocate((vm_address_t)_child_ports, cnt * sizeof(_child_ports[0]));
+	}
+	
+	if( _child_names ) {
+		mig_deallocate((vm_address_t)_child_names, cnt * sizeof(_child_ports[0]));
+	}
+	
+	return kr;
+}
+
 void
 mspolicy_setup(launch_data_t obj, const char *key, void *context)
 {

Modified: branches/PR-6046664/launchd/src/launchd_runtime.c
===================================================================
--- branches/PR-6046664/launchd/src/launchd_runtime.c	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/launchd_runtime.c	2008-09-30 22:33:12 UTC (rev 23717)
@@ -816,6 +816,12 @@
 }
 
 INTERNAL_ABI kern_return_t
+launchd_mport_copy_send(mach_port_t name)
+{
+	return errno = mach_port_insert_right(mach_task_self(), name, name, MACH_MSG_TYPE_COPY_SEND);
+}
+
+INTERNAL_ABI kern_return_t
 launchd_mport_close_recv(mach_port_t name)
 {
 	return errno = mach_port_mod_refs(mach_task_self(), name, MACH_PORT_RIGHT_RECEIVE, -1);

Modified: branches/PR-6046664/launchd/src/launchd_runtime.h
===================================================================
--- branches/PR-6046664/launchd/src/launchd_runtime.h	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/launchd_runtime.h	2008-09-30 22:33:12 UTC (rev 23717)
@@ -106,7 +106,7 @@
 
 extern bool pid1_magic;
 extern bool low_level_debug;
-extern char g_username[128];
+extern char *g_username;
 
 INTERNAL_ABI mach_port_t runtime_get_kernel_port(void);
 
@@ -174,6 +174,7 @@
 INTERNAL_ABI kern_return_t launchd_mport_create_recv(mach_port_t *name);
 INTERNAL_ABI kern_return_t launchd_mport_deallocate(mach_port_t name);
 INTERNAL_ABI kern_return_t launchd_mport_make_send(mach_port_t name);
+INTERNAL_ABI kern_return_t launchd_mport_copy_send(mach_port_t name);
 INTERNAL_ABI kern_return_t launchd_mport_close_recv(mach_port_t name);
 
 #endif

Modified: branches/PR-6046664/launchd/src/launchproxy.c
===================================================================
--- branches/PR-6046664/launchd/src/launchproxy.c	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/launchproxy.c	2008-09-30 22:33:12 UTC (rev 23717)
@@ -191,7 +191,7 @@
 
 			setpgid(0, 0);
 
-#if HAVE_SECURITY
+#if 0
 			if ((tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SESSIONCREATE)) && launch_data_get_bool(tmp)) {
 				if (SessionCreate) {
 					OSStatus scr = SessionCreate(0, 0);

Modified: branches/PR-6046664/launchd/src/libbootstrap.c
===================================================================
--- branches/PR-6046664/launchd/src/libbootstrap.c	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/libbootstrap.c	2008-09-30 22:33:12 UTC (rev 23717)
@@ -18,6 +18,7 @@
  * @APPLE_APACHE_LICENSE_HEADER_END@
  */
 
+#include <stdlib.h>
 #include "config.h"
 #include "libbootstrap_public.h"
 #include "libbootstrap_private.h"
@@ -56,6 +57,7 @@
 kern_return_t
 bootstrap_subset(mach_port_t bp, mach_port_t requestor_port, mach_port_t *subset_port)
 {
+	_vproc_log(LOG_NOTICE, "%s(): Called by %s.", __func__, getprogname());
 	return vproc_mig_subset(bp, requestor_port, subset_port);
 }
 
@@ -88,6 +90,56 @@
 }
 
 kern_return_t
+bootstrap_lookup_children(mach_port_t bp, mach_port_array_t *children, name_array_t *names, mach_msg_type_number_t *n_children)
+{
+	mach_msg_type_number_t junk = 0;
+	return vproc_mig_lookup_children(bp, children, &junk, names, n_children);
+}
+
+kern_return_t
+bootstrap_lookup_per_user_context(mach_port_t bp, uid_t uid, char *session_type __attribute__((unused)), mach_port_t *puc)
+{
+	return vproc_mig_lookup_per_user_context(bp, uid, puc);
+}
+
+kern_return_t bootstrap_lookup_local_per_user_context(mach_port_t bp, mach_port_t *puc)
+{
+	return vproc_mig_lookup_local_per_user_context(bp, puc);
+}
+
+kern_return_t
+bootstrap_root(mach_port_t *rbsp)
+{
+	mach_port_t last_bsport = MACH_PORT_NULL;
+	mach_port_t _rbsp = bootstrap_port;
+	kern_return_t result = KERN_FAILURE;
+	
+	do {
+		last_bsport = _rbsp;
+		result = bootstrap_parent(last_bsport, &_rbsp);
+
+		if( result == BOOTSTRAP_NOT_PRIVILEGED ) {
+			syslog(LOG_ERR, "bootstrap_parent(): Permission denied.\n");
+			_rbsp = MACH_PORT_NULL;
+		} else if( result != BOOTSTRAP_SUCCESS ) {
+			syslog(LOG_ERR, "bootstrap_parent() %d\n", result);
+			_rbsp = MACH_PORT_NULL;
+		}
+		
+		/* Even though last_bport being equal to _rbsp is the stopping point, we'll
+		 * still get back another send right, and thus our reference count will be
+		 * incremented by one, and we'll be responsible for releasing the additional
+		 * reference.
+		 */
+		mach_port_mod_refs(mach_task_self(), last_bsport, MACH_PORT_RIGHT_SEND, -1);
+	} while( _rbsp != MACH_PORT_NULL && last_bsport != _rbsp );
+	
+	*rbsp = _rbsp;
+	
+	return result;
+}
+
+kern_return_t
 bootstrap_register(mach_port_t bp, name_t service_name, mach_port_t sp)
 {
 	return bootstrap_register2(bp, service_name, sp, 0);
@@ -237,7 +289,6 @@
 			mach_port_deallocate(mach_task_self(), *sp);
 			kr = BOOTSTRAP_NOT_PRIVILEGED;
 		}
-
 	}
 
 	return kr;
@@ -265,12 +316,9 @@
 }
 
 kern_return_t
-bootstrap_info(mach_port_t bp,
-		name_array_t *service_names, mach_msg_type_number_t *service_namesCnt,
-		bootstrap_status_array_t *service_active, mach_msg_type_number_t *service_activeCnt)
+bootstrap_info(mach_port_t bp, name_array_t *service_names, mach_msg_type_number_t *service_namesCnt, bootstrap_status_array_t *service_active,  mach_msg_type_number_t *service_activeCnt)
 {
-	return vproc_mig_info(bp, service_names, service_namesCnt,
-			service_active, service_activeCnt);
+	return vproc_mig_info(bp, service_names, service_namesCnt, service_active, service_activeCnt);
 }
 
 const char *

Modified: branches/PR-6046664/launchd/src/libbootstrap_private.h
===================================================================
--- branches/PR-6046664/launchd/src/libbootstrap_private.h	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/libbootstrap_private.h	2008-09-30 22:33:12 UTC (rev 23717)
@@ -42,6 +42,14 @@
 
 kern_return_t bootstrap_set_policy(mach_port_t bp, pid_t target_pid, uint64_t flags, const char *target_service);
 
+kern_return_t bootstrap_lookup_children(mach_port_t bp, mach_port_array_t *children, name_array_t *names, mach_msg_type_number_t *n_children);
+
+kern_return_t bootstrap_lookup_per_user_context(mach_port_t bp, uid_t uid, char *session_type __attribute__((unused)), mach_port_t *puc);
+
+kern_return_t bootstrap_lookup_local_per_user_context(mach_port_t bp, mach_port_t *puc);
+
+kern_return_t bootstrap_root(mach_port_t *rbsp);
+
 #pragma GCC visibility pop
 
 __END_DECLS

Modified: branches/PR-6046664/launchd/src/libbootstrap_public.h
===================================================================
--- branches/PR-6046664/launchd/src/libbootstrap_public.h	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/libbootstrap_public.h	2008-09-30 22:33:12 UTC (rev 23717)
@@ -102,12 +102,13 @@
 #define	BOOTSTRAP_MAX_LOOKUP_COUNT		20
 
 #define	BOOTSTRAP_SUCCESS			0
-#define	BOOTSTRAP_NOT_PRIVILEGED		1100
-#define	BOOTSTRAP_NAME_IN_USE			1101
-#define	BOOTSTRAP_UNKNOWN_SERVICE		1102
-#define	BOOTSTRAP_SERVICE_ACTIVE		1103
+#define	BOOTSTRAP_NOT_PRIVILEGED	1100
+#define	BOOTSTRAP_NAME_IN_USE		1101
+#define	BOOTSTRAP_UNKNOWN_SERVICE	1102
+#define	BOOTSTRAP_SERVICE_ACTIVE	1103
 #define	BOOTSTRAP_BAD_COUNT			1104
 #define	BOOTSTRAP_NO_MEMORY			1105
+#define BOOTSTRAP_NO_CHILDREN		1106
 
 #define BOOTSTRAP_STATUS_INACTIVE		0
 #define BOOTSTRAP_STATUS_ACTIVE			1

Modified: branches/PR-6046664/launchd/src/libvproc.c
===================================================================
--- branches/PR-6046664/launchd/src/libvproc.c	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/libvproc.c	2008-09-30 22:33:12 UTC (rev 23717)
@@ -260,8 +260,7 @@
 }
 
 kern_return_t
-_vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright, launch_data_t *outval,
-		mach_port_array_t *ports, mach_msg_type_number_t *portCnt)
+_vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright, launch_data_t *outval, mach_port_array_t *ports, mach_msg_type_number_t *portCnt)
 {
 	mach_msg_type_number_t outdata_cnt;
 	vm_offset_t outdata = 0;
@@ -325,6 +324,10 @@
 		return (vproc_err_t)_vprocmgr_move_subset_to_user;
 	}
 
+	_vproc_log(LOG_NOTICE, "%s(%u, %s): %s, uid = %u", __func__, target_user, session_type, getprogname(), getuid());
+
+	_vproc_log(LOG_NOTICE, "%s(%u, %s): %s", __func__, target_user, session_type, getprogname());
+
 	if (!is_bkgd && ldpid != 1) {
 		if (lduid == getuid()) {
 			return NULL;
@@ -336,25 +339,42 @@
 		return (vproc_err_t)_vprocmgr_move_subset_to_user;
 	}
 
-	if (is_bkgd || target_user) {
-		mach_port_t puc = 0, rootbs = get_root_bootstrap_port();
+#if 0
+	mach_port_t puc = 0, rootbs = get_root_bootstrap_port();
 
-		if (vproc_mig_lookup_per_user_context(rootbs, target_user, &puc) != 0) {
-			return (vproc_err_t)_vprocmgr_move_subset_to_user;
-		}
+	if (vproc_mig_lookup_per_user_context(rootbs, target_user, &puc) != 0) {
+		return (vproc_err_t)_vprocmgr_move_subset_to_user;
+	}
 
-		if (is_bkgd) {
-			task_set_bootstrap_port(mach_task_self(), puc);
-			mach_port_deallocate(mach_task_self(), bootstrap_port);
-			bootstrap_port = puc;
-		} else {
-			kr = vproc_mig_move_subset(puc, bootstrap_port, (char *)session_type);
-			mach_port_deallocate(mach_task_self(), puc);
-		}
+	if( ldpid == 1 ) {
+		_vproc_log(LOG_NOTICE, "%s(): %s: ldpid = %llu, lduid = %llu, moving subset to per-user bootstrap.", __func__, getprogname(), ldpid, lduid);
+		kr = vproc_mig_move_subset(puc, bootstrap_port, VPROCMGR_SESSION_BACKGROUND);
+		mach_port_deallocate(mach_task_self(), puc);
 	} else {
-		kr = _vprocmgr_init(session_type) ? 1 : 0;
+		_vproc_log(LOG_NOTICE, "%s(): %s: ldpid = %llu, lduid = %llu, swapping bootstrap_port and puc.", __func__, getprogname(), ldpid, lduid);
+		task_set_bootstrap_port(mach_task_self(), puc);
+		mach_port_deallocate(mach_task_self(), bootstrap_port);
+		bootstrap_port = puc;
 	}
+#else
+	mach_port_t puc = 0, rootbs = get_root_bootstrap_port();
 
+	_vproc_log(LOG_NOTICE, "%s(%u, %s): Looking up per-user context...", __func__, target_user, session_type);
+	if (vproc_mig_lookup_per_user_context(rootbs, target_user, &puc) != 0) {
+		return (vproc_err_t)_vprocmgr_move_subset_to_user;
+	}
+
+	if (is_bkgd) {
+		_vproc_log(LOG_NOTICE, "%s(%u, %s): Background session, swapping bootstrap_port with puc.", __func__, target_user, session_type);
+		task_set_bootstrap_port(mach_task_self(), puc);
+		mach_port_deallocate(mach_task_self(), bootstrap_port);
+		bootstrap_port = puc;
+	} else {
+		_vproc_log(LOG_NOTICE, "%s(%u, %s): Moving subset...", __func__, target_user, session_type);
+		kr = vproc_mig_move_subset(puc, bootstrap_port, (char *)session_type);
+		mach_port_deallocate(mach_task_self(), puc);
+	}
+#endif
 	cached_pid = -1;
 
 	if (kr) {

Modified: branches/PR-6046664/launchd/src/protocol_job.defs
===================================================================
--- branches/PR-6046664/launchd/src/protocol_job.defs	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/protocol_job.defs	2008-09-30 22:33:12 UTC (rev 23717)
@@ -35,148 +35,157 @@
 type mach_port_move_send_array_t = array[] of mach_port_move_send_t
 		ctype: mach_port_array_t;
 
+type mach_port_make_send_array_t = array[] of mach_port_make_send_t
+		ctype: mach_port_array_t;
 
 userprefix vproc_mig_;
 serverprefix job_mig_;
 
 routine create_server(
-		__bs_port	: job_t;
-		__server_cmd	: cmd_t;
-		__server_uid	: uid_t;
-		__on_demand	: boolean_t;
-	out	__server_port	: mach_port_make_send_t);
+				__bs_port				: job_t;
+				__server_cmd			: cmd_t;
+				__server_uid			: uid_t;
+				__on_demand				: boolean_t;
+out				__server_port			: mach_port_make_send_t);
 
 routine reboot2(
-		__bs_port	: job_t;
-		__flags		: uint64_t);
+				__bs_port				: job_t;
+				__flags					: uint64_t);
 
 routine check_in2(
-		__bs_port	: job_t;
-		__service_name	: name_t;
-	out	__service_port	: mach_port_move_receive_t;
-		__flags		: uint64_t);
+				__bs_port				: job_t;
+				__service_name			: name_t;
+out				__service_port			: mach_port_move_receive_t;
+				__flags					: uint64_t);
 
 routine register2(
-		__bs_port	: job_t;
-		__service_name	: name_t;
-		__service_port	: mach_port_t;
-		__flags		: uint64_t);
+				__bs_port				: job_t;
+				__service_name			: name_t;
+				__service_port			: mach_port_t;
+				__flags					: uint64_t);
 
 routine look_up2(
-		__bs_port	: job_t;
-	sreplyport	__rport	: mach_port_make_send_once_t;
-		__service_name	: name_t;
-	out	__service_port	: mach_port_t;
-	UserAuditToken __server_cred:	audit_token_t;
-		__target_pid	: pid_t;
-		__flags		: uint64_t);
+				__bs_port				: job_t;
+sreplyport		__rport					: mach_port_make_send_once_t;
+				__service_name			: name_t;
+out				__service_port			: mach_port_t;
+UserAuditToken 	__server_cred			: audit_token_t;
+				__target_pid			: pid_t;
+				__flags					: uint64_t);
 
 routine send_signal(
-		__bs_port	: job_t;
-	sreplyport	__rport	: mach_port_make_send_once_t;
-		__label		: name_t;
-		__signal	: integer_t);
+				__bs_port				: job_t;
+sreplyport		__rport					: mach_port_make_send_once_t;
+				__label					: name_t;
+				__signal				: integer_t);
 
 routine parent(
-		__bs_port	: job_t;
-	sreplyport	__rport	: mach_port_make_send_once_t;
-	out	__parent_port	: mach_port_make_send_t);
+				__bs_port				: job_t;
+sreplyport		__rport					: mach_port_make_send_once_t;
+out				__parent_port			: mach_port_make_send_t);
 
 routine post_fork_ping(
-		__bs_port	: job_t;
-		__task_port	: task_t);
+				__bs_port				: job_t;
+				__task_port				: task_t);
 
 routine info(
-		__bs_port	: job_t;
-	out	__service_names	: name_array_t, dealloc;
-	out __service_active	: bootstrap_status_array_t, dealloc);
+				__bs_port				: job_t;
+out				__service_names			: name_array_t, dealloc;
+out 			__service_active		: bootstrap_status_array_t, dealloc);
 
 routine subset(
-		__bs_port	: job_t;
-		__requestor_port: mach_port_t;
-	out	__subset_port	: mach_port_make_send_t);
+				__bs_port				: job_t;
+				__requestor_port		: mach_port_t;
+out				__subset_port			: mach_port_make_send_t);
 
 routine setup_shmem(
-		__bs_port	: job_t;
-	out	__shmem_port	: mach_port_move_send_t);
+				__bs_port				: job_t;
+out				__shmem_port			: mach_port_move_send_t);
 
 routine take_subset(
-		__bs_port	: job_t;
-	out	__bs_reqport	: mach_port_move_send_t;
-	out	__bs_rcvright	: mach_port_move_receive_t;
-	out	__outdata	: pointer_t, dealloc;
-	out	__service_ports	: mach_port_move_send_array_t, dealloc);
+				__bs_port				: job_t;
+out				__bs_reqport			: mach_port_move_send_t;
+out				__bs_rcvright			: mach_port_move_receive_t;
+out				__outdata				: pointer_t, dealloc;
+out				__service_ports			: mach_port_move_send_array_t, dealloc);
 
 routine getsocket(
-		__bs_port	: job_t;
-	out	__sockpath	: name_t);
+				__bs_port				: job_t;
+out				__sockpath				: name_t);
 
 routine spawn(
-		__bs_port	: job_t;
-		__indata	: pointer_t;
-	out	__pid		: pid_t;
-	out	__obsvr_port	: mach_port_make_send_t);
+				__bs_port				: job_t;
+				__indata				: pointer_t;
+out				__pid					: pid_t;
+out				__obsvr_port			: mach_port_make_send_t);
 
 routine wait(
-		__bs_port	: job_t;
-	sreplyport	__rport	: mach_port_make_send_once_t;
-	out	__waitval	: integer_t);
+				__bs_port				: job_t;
+sreplyport		__rport					: mach_port_make_send_once_t;
+out				__waitval				: integer_t);
 
 routine uncork_fork(
-		__bs_port	: job_t);
+				__bs_port				: job_t);
 
 routine swap_integer(
-		__bs_port	: job_t;
-		__inkey		: vproc_gsk_t;
-		__outkey	: vproc_gsk_t;
-		__inval		: int64_t;
-	out	__outval	: int64_t);
+				__bs_port				: job_t;
+				__inkey					: vproc_gsk_t;
+				__outkey				: vproc_gsk_t;
+				__inval					: int64_t;
+out				__outval				: int64_t);
 
 routine set_service_policy(
-		__bs_port	: job_t;
-		__target_pid	: pid_t;
-		__flags		: uint64_t;
-		__service	: name_t);
+				__bs_port				: job_t;
+				__target_pid			: pid_t;
+				__flags					: uint64_t;
+				__service				: name_t);
 
 routine log(
-		__bs_port	: job_t;
-		__pri		: integer_t;
-		__err		: integer_t;
-		__msg		: logmsg_t);
+				__bs_port				: job_t;
+				__pri					: integer_t;
+				__err					: integer_t;
+				__msg					: logmsg_t);
 
 routine lookup_per_user_context(
-		__bs_port	: job_t;
-		__wu		: uid_t;
-	out	__u_cont	: mach_port_t);
+				__bs_port				: job_t;
+sreplyport		__rport					: mach_port_make_send_once_t;
+				__wu					: uid_t;
+out				__u_cont				: mach_port_move_send_t);
 
 routine move_subset(
-		__bs_port	: job_t;
-		__target_port	: mach_port_t;
-		__sessiontype	: name_t);
+				__bs_port				: job_t;
+				__target_port			: mach_port_t;
+				__sessiontype			: name_t);
 
 routine swap_complex(
-		__bs_port	: job_t;
-		__inkey		: vproc_gsk_t;
-		__outkey	: vproc_gsk_t;
-		__inval		: pointer_t;
-	out	__outval	: pointer_t, dealloc);
+				__bs_port				: job_t;
+				__inkey					: vproc_gsk_t;
+				__outkey				: vproc_gsk_t;
+				__inval					: pointer_t;
+out				__outval				: pointer_t, dealloc);
 
 routine log_drain(
-		__bs_port	: job_t;
-	sreplyport	__rport	: mach_port_make_send_once_t;
-	out	__outval	: pointer_t, dealloc);
+				__bs_port				: job_t;
+sreplyport		__rport					: mach_port_make_send_once_t;
+out				__outval				: pointer_t, dealloc);
 
 routine log_forward(
-		__bs_port	: job_t;
-		__inval		: pointer_t);
+				__bs_port				: job_t;
+				__inval					: pointer_t);
 
 routine embedded_kickstart(
-		__bs_port	: job_t;
-		__label		: name_t;
-	out	__pid		: pid_t;
-	out	__name_port	: mach_port_t);
+				__bs_port				: job_t;
+				__label					: name_t;
+out				__pid					: pid_t;
+out				__name_port				: mach_port_t);
 
 routine embedded_wait(
-		__bs_port	: job_t;
-		__label		: name_t;
-	out	__waitval	: integer_t);
+				__bs_port				: job_t;
+				__label					: name_t;
+out				__waitval				: integer_t);
+
+routine lookup_children(
+				__bs_port				: job_t;
+out 			__child_ports			: mach_port_move_send_array_t, dealloc;
+out				__child_names			: name_array_t, dealloc);
+

Modified: branches/PR-6046664/launchd/src/protocol_job_forward.defs
===================================================================
--- branches/PR-6046664/launchd/src/protocol_job_forward.defs	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/protocol_job_forward.defs	2008-09-30 22:33:12 UTC (rev 23717)
@@ -39,15 +39,43 @@
 skip; /* register2 */
 
 simpleroutine look_up2_forward(
-		__bs_port	: job_t;
-	replyport	__rport	: mach_port_move_send_once_t;
-		__service_name	: name_t;
-		__target_pid	: pid_t;
-		__flags		: uint64_t);
+			__bs_port		: job_t;
+replyport	__rport			: mach_port_move_send_once_t;
+			__service_name	: name_t;
+			__target_pid	: pid_t;
+			__flags			: uint64_t);
 
 skip; /* send_signal */
 
 simpleroutine parent_forward(
-                __bs_port       : job_t;
-	replyport	__rport	: mach_port_move_send_once_t);
+			__bs_port		: job_t;
+replyport	__rport			: mach_port_move_send_once_t);
 
+skip; /* post_fork_ping */
+
+skip; /* info */
+
+skip; /* subset */
+
+skip; /* setup_shmem */
+
+skip; /* take_subset */
+
+skip; /* getsocket */
+
+skip; /* spawn */
+
+skip; /* wait */
+
+skip; /* uncork_fork */
+
+skip; /* swap_integer */
+
+skip; /* set_service_policy */
+
+skip; /* log */
+
+simpleroutine lookup_per_user_context_forward(
+			__bs_port		: job_t;
+replyport	__rport			: mach_port_move_send_once_t;
+			__wu			: uid_t);

Modified: branches/PR-6046664/launchd/src/protocol_job_reply.defs
===================================================================
--- branches/PR-6046664/launchd/src/protocol_job_reply.defs	2008-09-30 22:09:48 UTC (rev 23716)
+++ branches/PR-6046664/launchd/src/protocol_job_reply.defs	2008-09-30 22:33:12 UTC (rev 23717)
@@ -70,7 +70,7 @@
 
 skip; /* log */
 
-skip; /* lookup_per_user_context */
+skip; /* lookup_per_user_context_reply */
 
 skip; /* move_subset */
 
@@ -79,4 +79,4 @@
 simpleroutine job_mig_log_drain_reply(
 		__r_port	: mach_port_move_send_once_t;
 		__result	: kern_return_t, RetCode;
-		__outval        : pointer_t);
+		__outval	: pointer_t);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20080930/b74c0145/attachment-0001.html 


More information about the launchd-changes mailing list