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

source_changes at macosforge.org source_changes at macosforge.org
Tue Nov 14 14:49:00 PST 2006


Revision: 22944
          http://trac.macosforge.org/projects/launchd/changeset/22944
Author:   zarzycki at apple.com
Date:     2006-11-14 14:48:59 -0800 (Tue, 14 Nov 2006)

Log Message:
-----------
<rdar://problem/4836935> rejigger GUI application into the GUI session, regardless of which session they really are spawned in

Modified Paths:
--------------
    trunk/launchd/src/launchctl.c
    trunk/launchd/src/launchd.c
    trunk/launchd/src/launchd.h
    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
    trunk/launchd/src/protocol_job_reply.defs

Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/launchctl.c	2006-11-14 22:48:59 UTC (rev 22944)
@@ -63,6 +63,7 @@
 #include <sysexits.h>
 
 #include "libbootstrap_public.h"
+#include "libvproc_public.h"
 #include "libvproc_internal.h"
 #include "liblaunch_public.h"
 #include "liblaunch_private.h"
@@ -534,6 +535,13 @@
 			goto out_bad;
 	}
 
+	if (lus->session_type && !(tmpa = launch_data_dict_lookup(thejob, LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE))) {
+		fprintf(stderr, "%s: Missing key \"%s\", defaulting value to \"Aqua\"\n", getprogname(),
+				LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE);
+		tmpa = launch_data_new_string("Aqua");
+		launch_data_dict_insert(thejob, tmpa, LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE);
+	}
+
 	if ((tmpa = launch_data_dict_lookup(thejob, LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE))) {
 		const char *allowed_session;
 		bool skipjob = true;

Modified: trunk/launchd/src/launchd.c
===================================================================
--- trunk/launchd/src/launchd.c	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/launchd.c	2006-11-14 22:48:59 UTC (rev 22944)
@@ -65,6 +65,7 @@
 #include <setjmp.h>
 
 #include "libbootstrap_public.h"
+#include "libvproc_public.h"
 #include "libvproc_internal.h"
 #include "liblaunch_public.h"
 #include "liblaunch_private.h"
@@ -122,9 +123,6 @@
 	};
 	struct sigaction fsa;
 	bool sflag = false, dflag = false, Dflag = false;
-	mach_msg_type_number_t l2l_name_cnt = 0, l2l_port_cnt = 0;
-	name_array_t l2l_names = NULL;
-	mach_port_array_t l2l_ports = NULL;
 	char ldconf[PATH_MAX] = PID1LAUNCHD_CONF;
 	const char *h = getenv("HOME");
 	const char *session_type = NULL;
@@ -133,7 +131,6 @@
 	struct stat sb;
 	size_t i, checkin_fdcnt = 0;
 	int *checkin_fds = NULL;
-	mach_port_t req_mport = MACH_PORT_NULL;
 	mach_port_t checkin_mport = MACH_PORT_NULL;
 	int ch, ker, logopts;
 
@@ -247,30 +244,8 @@
 	/* sigh... ignoring SIGCHLD has side effects: we can't call wait*() */
 	launchd_assert(kevent_mod(SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, &kqsignal_callback) != -1);
 
-	if (session_type && strcmp(session_type, "Aqua") == 0) {
-		mach_port_t newparent;
+	mach_init_init(checkin_mport);
 
-		launchd_assert(bootstrap_parent(bootstrap_port, &newparent) == BOOTSTRAP_SUCCESS);
-
-		launchd_assert(_launchd_to_launchd(bootstrap_port, &req_mport, &checkin_mport,
-					&l2l_names, &l2l_name_cnt, &l2l_ports, &l2l_port_cnt) == BOOTSTRAP_SUCCESS);
-
-		launchd_assert(l2l_name_cnt == l2l_port_cnt);
-
-		task_set_bootstrap_port(mach_task_self(), newparent);
-		launchd_assumes(mach_port_deallocate(mach_task_self(), bootstrap_port) == KERN_SUCCESS);
-		bootstrap_port = newparent;
-	}
-
-	mach_init_init(req_mport, checkin_mport, l2l_names, l2l_ports, l2l_name_cnt);
-
-	if (l2l_names) {
-		mig_deallocate((vm_address_t)l2l_names, l2l_name_cnt * sizeof(l2l_names[0]));
-	}
-	if (l2l_ports) {
-		mig_deallocate((vm_address_t)l2l_ports, l2l_port_cnt * sizeof(l2l_ports[0]));
-	}
-
 	if (h) {
 		snprintf(ldconf, sizeof(ldconf), "%s/%s", h, LAUNCHD_CONF);
 	}

Modified: trunk/launchd/src/launchd.h
===================================================================
--- trunk/launchd/src/launchd.h	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/launchd.h	2006-11-14 22:48:59 UTC (rev 22944)
@@ -59,7 +59,7 @@
 void catatonia(void);
 
 void mach_start_shutdown(void);
-void mach_init_init(mach_port_t, mach_port_t, name_array_t, mach_port_array_t, mach_msg_type_number_t);
+void mach_init_init(mach_port_t);
 
 int _fd(int fd);
 

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/launchd_core_logic.c	2006-11-14 22:48:59 UTC (rev 22944)
@@ -74,6 +74,7 @@
 #include "liblaunch_public.h"
 #include "liblaunch_private.h"
 #include "libbootstrap_public.h"
+#include "libvproc_public.h"
 #include "libvproc_internal.h"
 
 #include "launchd.h"
@@ -288,6 +289,7 @@
 static bool job_setup_machport(job_t j);
 static void job_postfork_become_user(job_t j);
 static void job_force_sampletool(job_t j);
+static void job_reparent_to_aqua_hack(job_t j);
 static void job_callback(void *obj, struct kevent *kev);
 static launch_data_t job_export2(job_t j, bool subjobs);
 static job_t job_new_spawn(job_t j, const char *label, const char *path, const char *workingdir, const char *const *argv, const char *const *env, mode_t *u_mask, bool w4d, bool fppc);
@@ -815,7 +817,7 @@
 {
 	job_t jr;
 
-	if ((jr = jobmgr_find(j->mgr, label)) != NULL) {
+	if ((jr = jobmgr_find(root_jobmgr, label)) != NULL) {
 		errno = EEXIST;
 		return NULL;
 	}
@@ -826,6 +828,8 @@
 		return NULL;
 	}
 
+	job_reparent_to_aqua_hack(jr);
+
 	if (getpid() == 1) {
 		struct ldcred ldc;
 
@@ -1097,6 +1101,9 @@
 		} else if (strcasecmp(key, LAUNCH_JOBKEY_LIMITLOADFROMHOSTS) == 0) {
 			return;
 		} else if (strcasecmp(key, LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE) == 0) {
+			if (strcmp(value, "Aqua") == 0) {
+				job_reparent_to_aqua_hack(j);
+			}
 			return;
 		}
 		break;
@@ -3705,8 +3712,8 @@
 
 	runtime_get_caller_creds(&ldc);
 
-	if (ldc.uid != 0) {
-		which_user = ldc.uid;
+	if (ldc.euid || ldc.uid) {
+		which_user = ldc.euid ? ldc.euid : ldc.uid;
 	}
 
 	if (which_user == 0) {
@@ -3940,6 +3947,10 @@
 		}
 	}
 
+	if (cnt == 0) {
+		goto out;
+	}
+
 	mig_allocate((vm_address_t *)&service_names, cnt * sizeof(service_names[0]));
 	if (!launchd_assumes(service_names != NULL)) {
 		goto out_bad;
@@ -3960,6 +3971,7 @@
 
 	launchd_assumes(cnt == cnt2);
 
+out:
 	*servicenamesp = service_names;
 	*serviceactivesp = service_actives;
 	*servicenames_cnt = *serviceactives_cnt = cnt;
@@ -3977,8 +3989,76 @@
 	return BOOTSTRAP_NO_MEMORY;
 }
 
+
+void
+job_reparent_to_aqua_hack(job_t j)
+{
+	jobmgr_t jmi = NULL;
+
+	SLIST_FOREACH(jmi, &root_jobmgr->submgrs, sle) {
+		if (strcmp(jmi->name, "Aqua") == 0) {
+			break;
+		}
+	}
+
+	if (job_assumes(j, jmi != NULL)) {
+		SLIST_REMOVE(&j->mgr->jobs, j, job_s, sle);
+		SLIST_INSERT_HEAD(&jmi->jobs, j, sle);
+		j->mgr = jmi;
+	}
+}
+
 kern_return_t
-job_mig_transfer_subset(job_t j, mach_port_t *reqport, mach_port_t *rcvright,
+job_mig_move_subset_to_user(job_t j, mach_port_t target_subset)
+{
+	mach_msg_type_number_t l2l_i, l2l_name_cnt = 0, l2l_port_cnt = 0;
+	name_array_t l2l_names = NULL;
+	mach_port_array_t l2l_ports = NULL;
+	mach_port_t reqport, rcvright;
+	kern_return_t kr;
+	jobmgr_t jmr;
+
+	kr = _vproc_grab_subset(target_subset, &reqport,
+			&rcvright, &l2l_names, &l2l_name_cnt, &l2l_ports, &l2l_port_cnt);
+
+	if (job_assumes(j, kr == 0)) {
+		job_assumes(j, launchd_mport_deallocate(target_subset) == KERN_SUCCESS);
+	} else {
+		goto out;
+	}
+
+	launchd_assert(l2l_name_cnt == l2l_port_cnt);
+
+	if ((jmr = jobmgr_new(j->mgr, reqport, rcvright)) == 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;
+
+		if ((ms = machservice_new(jmr->anonj, l2l_names[l2l_i], &l2l_ports[l2l_i]))) {
+			machservice_watch(ms);
+		}
+	}
+
+	kr = 0;
+
+out:
+	if (l2l_names) {
+		mig_deallocate((vm_address_t)l2l_names, l2l_name_cnt * sizeof(l2l_names[0]));
+	}
+	if (l2l_ports) {
+		mig_deallocate((vm_address_t)l2l_ports, l2l_port_cnt * sizeof(l2l_ports[0]));
+	}
+
+	return kr;
+}
+
+kern_return_t
+job_mig_take_subset(job_t j, mach_port_t *reqport, mach_port_t *rcvright,
 		name_array_t *servicenamesp, unsigned int *servicenames_cnt,
 		mach_port_array_t *portsp, unsigned int *ports_cnt)
 {
@@ -4165,18 +4245,18 @@
 	const char *path = NULL;
 	const char *workingdir = NULL;
 	size_t argv_i = 0, env_i = 0;
+	struct ldcred ldc;
 
+	runtime_get_caller_creds(&ldc);
+
 	if (!launchd_assumes(j != NULL)) {
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-#if 0
-	if (ldc.asid != inherited_asid) {
-		job_log(j, LOG_ERR, "Security: PID %d (ASID %d) was denied a request to spawn a process in this session (ASID %d)",
-				ldc.pid, ldc.asid, inherited_asid);
-		return BOOTSTRAP_NOT_PRIVILEGED;
+	if (getpid() == 1 && ldc.euid && ldc.uid) {
+		job_log(j, LOG_DEBUG, "Punting spawn to per-user-context");
+		return VPROC_ERR_TRY_PER_USER;
 	}
-#endif
 
 	argv = alloca((argc + 1) * sizeof(char *));
 	memset(argv, 0, (argc + 1) * sizeof(char *));
@@ -4270,17 +4350,15 @@
 }
 
 void
-mach_init_init(mach_port_t req_port, mach_port_t checkin_port,
-		name_array_t l2l_names, mach_port_array_t l2l_ports, mach_msg_type_number_t l2l_cnt)
+mach_init_init(mach_port_t checkin_port)
 {
-	mach_msg_type_number_t l2l_i;
 	auditinfo_t inherited_audit;
 	job_t ji, anon_job = NULL;
 
 	getaudit(&inherited_audit);
 	inherited_asid = inherited_audit.ai_asid;
 
-	launchd_assert((root_jobmgr = jobmgr_new(NULL, req_port ? req_port : mach_task_self(), checkin_port)) != NULL);
+	launchd_assert((root_jobmgr = jobmgr_new(NULL, mach_task_self(), checkin_port)) != NULL);
 
 	SLIST_FOREACH(ji, &root_jobmgr->jobs, sle) {
 		if (ji->anonymous) {
@@ -4302,16 +4380,4 @@
 
 	/* cut off the Libc cache, we don't want to deadlock against ourself */
 	bootstrap_port = MACH_PORT_NULL;
-
-	if (l2l_names == NULL) {
-		return;
-	}
-
-	for (l2l_i = 0; l2l_i < l2l_cnt; l2l_i++) {
-		struct machservice *ms;
-
-		if ((ms = machservice_new(anon_job, l2l_names[l2l_i], &l2l_ports[l2l_i]))) {
-			machservice_watch(ms);
-		}
-	}
 }

Modified: trunk/launchd/src/liblaunch.c
===================================================================
--- trunk/launchd/src/liblaunch.c	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/liblaunch.c	2006-11-14 22:48:59 UTC (rev 22944)
@@ -39,6 +39,7 @@
 #include <pwd.h>
 
 #include "libbootstrap_public.h"
+#include "libvproc_public.h"
 #include "libvproc_internal.h"
 
 /* __OSBogusByteSwap__() must not really exist in the symbol namespace
@@ -1188,31 +1189,25 @@
 pid_t
 create_and_switch_to_per_session_launchd(const char *login, int flags, ...)
 {
-	static char *const ldargv[] = { "/sbin/launchd", "-S", "Aqua", NULL };
 	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;
-	name_t sp;
-	pid_t p, ldp;
+	pid_t p;
 	uid_t u;
 	gid_t g;
 
+	if (_vproc_move_subset_to_user()) {
+		return -1;
+	}
+
 	if ((pwe = getpwnam(login)) == NULL)
 		return -1;
 
 	u = pwe->pw_uid;
 	g = pwe->pw_gid;
 
-	if ((ldp = fexecv_as_user(login, u, g, ldargv)) == -1) {
-		return -1;
-	}
-
-	while (_vprocmgr_getsocket(sp) != BOOTSTRAP_SUCCESS) {
-		usleep(20000);
-	}
-
 	if (flags & LOAD_ONLY_SAFEMODE_LAUNCHAGENTS) {
 		largv[5] = "system";
 	}
@@ -1245,5 +1240,5 @@
 		}
 	}
 
-	return ldp;
+	return 1;
 }

Modified: trunk/launchd/src/libvproc.c
===================================================================
--- trunk/launchd/src/libvproc.c	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/libvproc.c	2006-11-14 22:48:59 UTC (rev 22944)
@@ -36,13 +36,28 @@
 #include "protocol_vproc.h"
 
 kern_return_t
-_launchd_to_launchd(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright,
+_vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright,
 		name_array_t *service_names, mach_msg_type_number_t *service_namesCnt,
 		mach_port_array_t *ports, mach_msg_type_number_t *portCnt)
 {
-	return vproc_mig_transfer_subset(bp, reqport, rcvright, service_names, service_namesCnt, ports, portCnt);
+	return vproc_mig_take_subset(bp, reqport, rcvright, service_names, service_namesCnt, ports, portCnt);
 }
 
+vproc_err_t
+_vproc_move_subset_to_user(void)
+{
+	kern_return_t kr = 1;
+	mach_port_t puc;
+
+	if (vproc_mig_lookup_per_user_context(bootstrap_port, 0, &puc) == 0) {
+		kr = vproc_mig_move_subset_to_user(puc, bootstrap_port);
+		mach_port_deallocate(mach_task_self(), puc);
+	}
+
+	return kr == 0 ? NULL : (vproc_err_t)_vproc_move_subset_to_user;
+}
+
+
 pid_t
 _spawn_via_launchd(const char *label, const char *const *argv, const struct spawn_via_launchd_attr *spawn_attrs, int struct_version)
 {
@@ -112,6 +127,15 @@
 
 	kr = vproc_mig_spawn(bootstrap_port, buf, buf_len, argc, envc, flags, u_mask, &p, &obsvr_port);
 
+	if (kr == VPROC_ERR_TRY_PER_USER) {
+		mach_port_t puc;
+
+		if (vproc_mig_lookup_per_user_context(bootstrap_port, 0, &puc) == 0) {
+			kr = vproc_mig_spawn(puc, buf, buf_len, argc, envc, flags, u_mask, &p, &obsvr_port);
+			mach_port_deallocate(mach_task_self(), puc);
+		}
+	}
+
 	free(buf);
 
 	if (kr == BOOTSTRAP_SUCCESS) {

Modified: trunk/launchd/src/libvproc_internal.h
===================================================================
--- trunk/launchd/src/libvproc_internal.h	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/libvproc_internal.h	2006-11-14 22:48:59 UTC (rev 22944)
@@ -48,12 +48,14 @@
 #define SPAWN_WANTS_FORCE_PPC		0x0010
 
 kern_return_t
-_launchd_to_launchd(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright,
+_vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright,
 		name_array_t *service_names, mach_msg_type_number_t *service_namesCnt,
 		mach_port_array_t *ports, mach_msg_type_number_t *portCnt);
 
 kern_return_t _vprocmgr_getsocket(name_t);
 
+vproc_err_t _vproc_move_subset_to_user(void);
+
 void _vproc_logv(int pri, int err, const char *msg, va_list ap);
 
 kern_return_t

Modified: trunk/launchd/src/protocol_job.defs
===================================================================
--- trunk/launchd/src/protocol_job.defs	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/protocol_job.defs	2006-11-14 22:48:59 UTC (rev 22944)
@@ -81,7 +81,7 @@
 		__service_name	: name_t;
 	out	__service_port	: mach_port_t);
 
-routine transfer_subset(
+routine take_subset(
 		__bs_port	: job_t;
 	out	__bs_reqport	: mach_port_t;
 	out	__bs_rcvright	: mach_port_move_receive_t;
@@ -130,3 +130,7 @@
 		__bs_port	: job_t;
 		__wu		: uid_t;
 	out	__u_cont	: mach_port_t);
+
+routine move_subset_to_user(
+		__bs_port	: job_t;
+		__target_port	: mach_port_t);

Modified: trunk/launchd/src/protocol_job_reply.defs
===================================================================
--- trunk/launchd/src/protocol_job_reply.defs	2006-11-13 20:53:23 UTC (rev 22943)
+++ trunk/launchd/src/protocol_job_reply.defs	2006-11-14 22:48:59 UTC (rev 22944)
@@ -24,6 +24,7 @@
 #include <mach/mach_types.defs>
 #include "launchd_mig_types.defs"
 import "libbootstrap_public.h";
+import "libvproc_public.h";
 import "libvproc_internal.h";
 
 skip; /* create_server */

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


More information about the launchd-changes mailing list