[launchd-changes] [23130] trunk/launchd/src

source_changes at macosforge.org source_changes at macosforge.org
Sun Mar 4 15:38:22 PST 2007


Revision: 23130
          http://trac.macosforge.org/projects/launchd/changeset/23130
Author:   zarzycki at apple.com
Date:     2007-03-04 15:38:21 -0800 (Sun, 04 Mar 2007)

Log Message:
-----------
<rdar://problem/4465956> launchd should be able to bootstrap itself

Modified Paths:
--------------
    trunk/launchd/src/launchctl.c
    trunk/launchd/src/launchd_core_logic.c
    trunk/launchd/src/liblaunch.c
    trunk/launchd/src/libvproc.c
    trunk/launchd/src/libvproc_internal.h
    trunk/launchd/src/protocol_job.defs

Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c	2007-03-04 17:34:05 UTC (rev 23129)
+++ trunk/launchd/src/launchctl.c	2007-03-04 23:38:21 UTC (rev 23130)
@@ -250,8 +250,9 @@
 				}
 			}
 
-			if (i > 0)
+			if (i > 0) {
 				demux_cmd(i, argv2);
+			}
 
 			free(l);
 		}
@@ -1243,7 +1244,7 @@
 }
 
 static void
-very_pid2_specific_bootstrap(bool sflag)
+system_specific_bootstrap(bool sflag)
 {
 	int hnmib[] = { CTL_KERN, KERN_HOSTNAME };
 	struct group *tfp_gr;
@@ -1340,7 +1341,7 @@
 
 	_vproc_set_global_on_demand(true);
 
-	char *load_launchd_items[] = { "load", "-D", "all", "/etc/mach_init.d", NULL, NULL };
+	char *load_launchd_items[] = { "load", "-D", "all", "/etc/mach_init.d", NULL };
 
 	if (is_safeboot()) {
 		load_launchd_items[2] = "system";
@@ -1387,18 +1388,61 @@
 }
 
 int
-bootstrap_cmd(int argc, char *const argv[] __attribute__((unused)))
+bootstrap_cmd(int argc, char *const argv[])
 {
-	if (getuid() == 0) {
-		very_pid2_specific_bootstrap(argc == 2);
+	char *session_type = NULL;
+	bool sflag = false;
+	int ch;
+
+	while ((ch = getopt(argc, argv, "sS:")) != -1) {
+		switch (ch) {
+		case 's':
+			sflag = true;
+			break;
+		case 'S':
+			session_type = optarg;
+			break;
+		case '?':
+		default:
+			break;
+		}
+	}
+
+	optind = 1;
+	optreset = 1;
+
+	if (!session_type) {
+		fprintf(stderr, "usage: %s bootstrap [-s] -S <session-type>\n", getprogname());
+		return 1;
+	}
+
+	if (strcasecmp(session_type, "System") == 0) {
+		system_specific_bootstrap(sflag);
 	} else {
-		char *load_launchd_items[] = { "load", "-D", "all", "-S", "Background", NULL };
+		char *load_launchd_items[] = { "load", "-S", session_type, "-D", "all", NULL, NULL, NULL, NULL };
+		int the_argc = 5;
 
 		if (is_safeboot()) {
-			load_launchd_items[2] = "system";
+			load_launchd_items[4] = "system";
 		}
 
-		assumes(load_and_unload_cmd(5, load_launchd_items) == 0);
+		if (strcasecmp(session_type, "Background") == 0 || strcasecmp(session_type, "LoginWindow") == 0) {
+			load_launchd_items[4] = "system";
+			if (!is_safeboot()) {
+				load_launchd_items[5] = "-D";
+				load_launchd_items[6] = "local";
+				the_argc += 2;
+			}
+			if (strcasecmp(session_type, "LoginWindow") == 0) {
+				load_launchd_items[the_argc] = "/etc/mach_init_per_login_session.d";
+				the_argc += 1;
+			}
+		} else if (strcasecmp(session_type, "Aqua") == 0) {
+			load_launchd_items[5] = "/etc/mach_init_per_user.d";
+			the_argc += 1;
+		}
+
+		assumes(load_and_unload_cmd(the_argc, load_launchd_items) == 0);
 	}
 
 	return 0;
@@ -1416,8 +1460,9 @@
 
 	memset(&lus, 0, sizeof(lus));
 
-	if (!strcmp(argv[0], "load"))
+	if (strcmp(argv[0], "load") == 0) {
 		lus.load = true;
+	}
 
 	while ((ch = getopt(argc, argv, "wFS:D:")) != -1) {
 		switch (ch) {
@@ -1431,20 +1476,20 @@
 			lus.session_type = optarg;
 			break;
 		case 'D':
-			  if (strcasecmp(optarg, "all") == 0) {
-				  es |= NSAllDomainsMask;
-			  } else if (strcasecmp(optarg, "user") == 0) {
-				  es |= NSUserDomainMask;
-			  } else if (strcasecmp(optarg, "local") == 0) {
-				  es |= NSLocalDomainMask;
-			  } else if (strcasecmp(optarg, "network") == 0) {
-				  es |= NSNetworkDomainMask;
-			  } else if (strcasecmp(optarg, "system") == 0) {
-				  es |= NSSystemDomainMask;
-			  } else {
+			if (strcasecmp(optarg, "all") == 0) {
+				es |= NSAllDomainsMask;
+			} else if (strcasecmp(optarg, "user") == 0) {
+				es |= NSUserDomainMask;
+			} else if (strcasecmp(optarg, "local") == 0) {
+				es |= NSLocalDomainMask;
+			} else if (strcasecmp(optarg, "network") == 0) {
+				es |= NSNetworkDomainMask;
+			} else if (strcasecmp(optarg, "system") == 0) {
+				es |= NSSystemDomainMask;
+			} else {
 				badopts = true;
-			  }
-			  break;
+			}
+			break;
 		case '?':
 		default:
 			badopts = true;
@@ -1454,11 +1499,13 @@
 	argc -= optind;
 	argv += optind;
 
-	if (lus.session_type == NULL)
+	if (lus.session_type == NULL) {
 		es &= ~NSUserDomainMask;
+	}
 
-	if (argc == 0 && es == 0)
+	if (argc == 0 && es == 0) {
 		badopts = true;
+	}
 
 	if (badopts) {
 		fprintf(stderr, "usage: %s load [-wF] [-D <user|local|network|system|all>] paths...\n", getprogname());
@@ -1497,8 +1544,9 @@
 		}
 	}
 
-	for (i = 0; i < (size_t)argc; i++)
+	for (i = 0; i < (size_t)argc; i++) {
 		readpath(argv[i], &lus);
+	}
 
 	if (launch_data_array_get_count(lus.pass0) == 0 &&
 			launch_data_array_get_count(lus.pass1) == 0 &&

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2007-03-04 17:34:05 UTC (rev 23129)
+++ trunk/launchd/src/launchd_core_logic.c	2007-03-04 23:38:21 UTC (rev 23130)
@@ -211,7 +211,7 @@
 #define jobmgr_assumes(jm, e)      \
 	                (__builtin_expect(!(e), 0) ? jobmgr_log_bug(jm, __rcs_file_version__, __FILE__, __LINE__, #e), false : true)
 
-static jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag);
+static jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name);
 static jobmgr_t jobmgr_parent(jobmgr_t jm);
 static jobmgr_t jobmgr_do_garbage_collection(jobmgr_t jm);
 static bool jobmgr_is_idle(jobmgr_t jm);
@@ -272,7 +272,7 @@
 	mode_t mask;
 	unsigned int globargv:1, wait4debugger:1, unload_at_exit:1, stall_before_exec:1, only_once:1,
 		     currently_ignored:1, forced_peers_to_demand_mode:1, setnice:1, hopefully_exits_last:1, removal_pending:1,
-		     wait4pipe_eof:1, sent_sigkill:1, debug_before_kill:1, weird_per_user_bootstrap:1;
+		     wait4pipe_eof:1, sent_sigkill:1, debug_before_kill:1, weird_bootstrap:1;
 	char label[0];
 };
 
@@ -1649,7 +1649,7 @@
 
 	job_log(j, LOG_DEBUG, "Reaping");
 
-	if (j->weird_per_user_bootstrap) {
+	if (j->weird_bootstrap) {
 		mach_msg_size_t mxmsgsz = sizeof(union __RequestUnion__job_mig_protocol_vproc_subsystem);
 
 		if (job_mig_protocol_vproc_subsystem.maxsize > mxmsgsz) {
@@ -1657,7 +1657,7 @@
 		}
 
 		job_assumes(j, runtime_add_mport(j->mgr->jm_port, protocol_vproc_server, mxmsgsz) == KERN_SUCCESS);
-		j->weird_per_user_bootstrap = false;
+		j->weird_bootstrap = false;
 	}
 
 	if (j->log_redirect_fd && (!j->wait4pipe_eof || j->mgr->shutting_down)) {
@@ -1996,7 +1996,7 @@
 
 	time(&j->start_time);
 
-	switch (c = runtime_fork(j->weird_per_user_bootstrap ? j->j_port : j->mgr->jm_port)) {
+	switch (c = runtime_fork(j->weird_bootstrap ? j->j_port : j->mgr->jm_port)) {
 	case -1:
 		job_log_error(j, LOG_ERR, "fork() failed, will try again in one second");
 		job_assumes(j, close(execspair[0]) == 0);
@@ -3397,15 +3397,15 @@
 }
 
 jobmgr_t 
-jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag)
+jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name)
 {
-	const char *bootstrap_tool[] = { "/bin/launchctl", "bootstrap", NULL, NULL };
+	const char *bootstrap_tool[] = { "/bin/launchctl", "bootstrap", "-S", name, NULL, NULL };
 	mach_msg_size_t mxmsgsz;
 	job_t bootstrapper = NULL;
 	jobmgr_t jmr;
 
 	if (sflag) {
-		bootstrap_tool[2] = "-s";
+		bootstrap_tool[4] = "-s";
 	}
 
 	launchd_assert(offsetof(struct jobmgr_s, kqjobmgr_callback) == 0);
@@ -3415,7 +3415,7 @@
 		return NULL;
 	}
 
-	jmr = calloc(1, sizeof(struct jobmgr_s) + 30);
+	jmr = calloc(1, sizeof(struct jobmgr_s) + (name ? (strlen(name) + 1) : 128));
 	
 	if (jmr == NULL) {
 		return NULL;
@@ -3423,7 +3423,7 @@
 
 	TAILQ_INIT(&jmr->jobs);
 	jmr->kqjobmgr_callback = jobmgr_callback;
-	strcpy(jmr->name, "In-utero");
+	strcpy(jmr->name, name ? name : "Under construction");
 
 	jmr->req_port = requestorport;
 
@@ -3468,7 +3468,9 @@
 		goto out_bad;
 	}
 
-	sprintf(jmr->name, "%u", MACH_PORT_INDEX(jmr->jm_port));
+	if (!name) {
+		sprintf(jmr->name, "%u", MACH_PORT_INDEX(jmr->jm_port));
+	}
 
 	/* Sigh... at the moment, MIG has maxsize == sizeof(reply union) */
 	mxmsgsz = sizeof(union __RequestUnion__job_mig_protocol_vproc_subsystem);
@@ -3478,17 +3480,20 @@
 
 	jobmgr_assumes(jmr, (jmr->anonj = jobmgr_get_anonymous(jmr)) != NULL);
 
-	bootstrapper = job_new(jmr, "com.apple.launchctld", NULL, bootstrap_tool);
-
 	if (!jm) {
 		jobmgr_assumes(jmr, kevent_mod(SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, jmr) != -1);
 	}
 
-	if (!jm && getuid() != 0) {
-		/* per-user bootstrap context is messy */
-		bootstrapper->weird_per_user_bootstrap = true;
-		jobmgr_assumes(jmr, job_setup_machport(bootstrapper));
-	} else {
+	if (name) {
+		/* no name implies: bootstrap_subset() where creating a "bootstrapper" makes no sense */
+		bootstrapper = job_new(jmr, "com.apple.launchctld", NULL, bootstrap_tool);
+		if (jm || getuid()) {
+			bootstrapper->weird_bootstrap = true;
+			jobmgr_assumes(jmr, job_setup_machport(bootstrapper));
+		}
+	}
+
+	if (!bootstrapper || !bootstrapper->weird_bootstrap) {
 		if (!jobmgr_assumes(jmr, runtime_add_mport(jmr->jm_port, protocol_vproc_server, mxmsgsz) == KERN_SUCCESS)) {
 			goto out_bad;
 		}
@@ -3496,7 +3501,7 @@
 
 	jobmgr_log(jmr, LOG_DEBUG, "Created job manager%s%s", jm ? " with parent: " : ".", jm ? jm->name : "");
 
-	if (!jm && jobmgr_assumes(jmr, bootstrapper != NULL)) {
+	if (bootstrapper) {
 		jobmgr_assumes(jmr, job_dispatch(bootstrapper, true) != NULL);
 	}
 
@@ -4586,7 +4591,7 @@
 }
 
 kern_return_t
-job_mig_move_subset_to_user(job_t j, mach_port_t target_subset)
+job_mig_move_subset(job_t j, mach_port_t target_subset, name_t session_type)
 {
 	mach_msg_type_number_t l2l_i, l2l_name_cnt = 0, l2l_port_cnt = 0;
 	name_array_t l2l_names = NULL;
@@ -4596,9 +4601,17 @@
 	jobmgr_t jmr;
 
 	if (getuid() == 0) {
+		const char *bootstrap_tool[] = { "/bin/launchctl", "bootstrap", "-S", session_type, NULL };
+		job_t bootstrapper;
+
 		j = job_mig_intran2(root_jobmgr, target_subset);
+		strcpy(j->mgr->name, session_type);
 		job_assumes(j, launchd_mport_deallocate(target_subset) == KERN_SUCCESS);
-		strcpy(j->mgr->name, "Aqua");
+
+		bootstrapper = job_new(j->mgr, "com.apple.launchctld", NULL, bootstrap_tool);
+		if (job_assumes(j, bootstrapper != NULL)) {
+			job_dispatch(bootstrapper, true);
+		}
 		return 0;
 	}
 
@@ -4613,13 +4626,11 @@
 
 	launchd_assert(l2l_name_cnt == l2l_port_cnt);
 
-	if ((jmr = jobmgr_new(j->mgr, reqport, rcvright, false)) == NULL) {
+	if ((jmr = jobmgr_new(j->mgr, reqport, rcvright, false, session_type)) == NULL) {
 		kr = BOOTSTRAP_NO_MEMORY;
 		goto out;
 	}
 
-	strcpy(jmr->name, "Aqua");
-
 	for (l2l_i = 0; l2l_i < l2l_name_cnt; l2l_i++) {
 		struct machservice *ms;
 
@@ -4742,7 +4753,7 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	if ((jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL, false)) == NULL) {
+	if ((jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL, false, NULL)) == NULL) {
 		if (requestorport == MACH_PORT_NULL) {
 			return BOOTSTRAP_NOT_PRIVILEGED;
 		}
@@ -4917,5 +4928,5 @@
 void
 jobmgr_init(bool sflag)
 {
-	launchd_assert((root_jobmgr = jobmgr_new(NULL, MACH_PORT_NULL, MACH_PORT_NULL, sflag)) != NULL);
+	launchd_assert((root_jobmgr = jobmgr_new(NULL, MACH_PORT_NULL, MACH_PORT_NULL, sflag, getpid() == 1 ? "System" : "Background")) != NULL);
 }

Modified: trunk/launchd/src/liblaunch.c
===================================================================
--- trunk/launchd/src/liblaunch.c	2007-03-04 17:34:05 UTC (rev 23129)
+++ trunk/launchd/src/liblaunch.c	2007-03-04 23:38:21 UTC (rev 23130)
@@ -1160,101 +1160,28 @@
 	return r;
 }
 
-static pid_t
-fexecv_as_user(const char *login, uid_t u, gid_t g, char *const argv[])
-{
-	int i, dtsz;
-	pid_t p;
-
-	if ((p = fork()) != 0)
-		return p;
-
-	chdir("/");
-
-	seteuid(0);
-	setegid(0);
-	setgid(g);
-	initgroups(login, g);
-	setuid(u);
-
-	dtsz = getdtablesize();
-
-	for (i = STDERR_FILENO + 1; i < dtsz; i++)
-		close(i);
-
-	execv(argv[0], argv);
-	_exit(EXIT_FAILURE);
-}
-
 void
-load_launchd_jobs_at_loginwindow_prompt(int flags, ...)
+load_launchd_jobs_at_loginwindow_prompt(int flags __attribute__((unused)), ...)
 {
-	char *largv[] = { "/bin/launchctl", "load", "-S", "LoginWindow",
-		"-D", "system", "-D", "local", "/etc/mach_init_per_login_session.d", NULL };
-	int wstatus;
-	pid_t p;
-
-	if (flags & LOAD_ONLY_SAFEMODE_LAUNCHAGENTS) {
-		largv[5] = "system";
-	}
-
-	if (__vproc_tag_loginwindow_context()) {
-		return;
-	}
-
-	if ((p = fexecv_as_user("root", 0, 0, largv)) == -1) {
-		return;
-	}
-
-	if (waitpid(p, &wstatus, 0) != p) {
-		return;
-	}
+	_vproc_move_subset_to_user("LoginWindow");
 }
 
 pid_t
-create_and_switch_to_per_session_launchd(const char *login, int flags, ...)
+create_and_switch_to_per_session_launchd(const char *login __attribute__((unused)), int flags __attribute__((unused)), ...)
 {
-	char *largv[] = { "/bin/launchctl", "load", "-S", "Aqua", "-D", "all", "/etc/mach_init_per_user.d", NULL };
 	mach_port_t bezel_ui_server;
-	struct passwd *pwe;
 	struct stat sb;
-	int wstatus;
-	pid_t p;
-	uid_t u;
-	gid_t g;
 
-	if (_vproc_move_subset_to_user()) {
+	if (_vproc_move_subset_to_user("Aqua")) {
 		return -1;
 	}
 
-	if ((pwe = getpwnam(login)) == NULL)
-		return -1;
-
-	u = pwe->pw_uid;
-	g = pwe->pw_gid;
-
-	if (flags & LOAD_ONLY_SAFEMODE_LAUNCHAGENTS) {
-		largv[5] = "system";
-	}
-
-	if ((p = fexecv_as_user(login, u, g, largv)) == -1) {
-		return -1;
-	}
-
-	if (waitpid(p, &wstatus, 0) != p) {
-		return -1;
-	}
-
-	if (!(WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0)) {
-		return -1;
-	}
-
 #define BEZEL_UI_PATH "/System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/Resources/BezelUI/BezelUIServer"
 #define BEZEL_UI_PLIST "/System/Library/LaunchAgents/com.apple.BezelUIServer.plist"
 #define BEZEL_UI_SERVICE "BezelUI"
 
 	if (!(stat(BEZEL_UI_PLIST, &sb) == 0 && S_ISREG(sb.st_mode))) {
-		if (bootstrap_create_server(bootstrap_port, BEZEL_UI_PATH, u, true, &bezel_ui_server) == BOOTSTRAP_SUCCESS) {
+		if (bootstrap_create_server(bootstrap_port, BEZEL_UI_PATH, 0, true, &bezel_ui_server) == BOOTSTRAP_SUCCESS) {
 			mach_port_t srv;
 
 			if (bootstrap_create_service(bezel_ui_server, BEZEL_UI_SERVICE, &srv) == BOOTSTRAP_SUCCESS) {

Modified: trunk/launchd/src/libvproc.c
===================================================================
--- trunk/launchd/src/libvproc.c	2007-03-04 17:34:05 UTC (rev 23129)
+++ trunk/launchd/src/libvproc.c	2007-03-04 23:38:21 UTC (rev 23130)
@@ -47,7 +47,7 @@
 }
 
 vproc_err_t
-_vproc_move_subset_to_user(void)
+_vproc_move_subset_to_user(char *session_type)
 {
 	kern_return_t kr = 1;
 	mach_port_t puc = 0, which_port = bootstrap_port;
@@ -56,7 +56,7 @@
 		which_port = puc;
 	}
 
-	kr = vproc_mig_move_subset_to_user(which_port, bootstrap_port);
+	kr = vproc_mig_move_subset(which_port, bootstrap_port, session_type);
 
 	if (puc) {
 		mach_port_deallocate(mach_task_self(), puc);

Modified: trunk/launchd/src/libvproc_internal.h
===================================================================
--- trunk/launchd/src/libvproc_internal.h	2007-03-04 17:34:05 UTC (rev 23129)
+++ trunk/launchd/src/libvproc_internal.h	2007-03-04 23:38:21 UTC (rev 23130)
@@ -57,7 +57,7 @@
 
 kern_return_t _vprocmgr_getsocket(name_t);
 
-vproc_err_t _vproc_move_subset_to_user(void);
+vproc_err_t _vproc_move_subset_to_user(char *session_type);
 
 void _vproc_logv(int pri, int err, const char *msg, va_list ap);
 

Modified: trunk/launchd/src/protocol_job.defs
===================================================================
--- trunk/launchd/src/protocol_job.defs	2007-03-04 17:34:05 UTC (rev 23129)
+++ trunk/launchd/src/protocol_job.defs	2007-03-04 23:38:21 UTC (rev 23130)
@@ -142,6 +142,7 @@
 		__wu		: uid_t;
 	out	__u_cont	: mach_port_t);
 
-routine move_subset_to_user(
+routine move_subset(
 		__bs_port	: job_t;
-		__target_port	: mach_port_t);
+		__target_port	: mach_port_t;
+		__sessiontype	: name_t);

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20070304/b9186eeb/attachment.html


More information about the launchd-changes mailing list