Revision: 22944 http://trac.macosforge.org/projects/launchd/changeset/22944 Author: zarzycki@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 */
participants (1)
-
source_changes@macosforge.org