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

source_changes at macosforge.org source_changes at macosforge.org
Mon Mar 9 17:16:40 PDT 2009


Revision: 23853
          http://trac.macosforge.org/projects/launchd/changeset/23853
Author:   dsorresso at apple.com
Date:     2009-03-09 17:16:39 -0700 (Mon, 09 Mar 2009)
Log Message:
-----------
<rdar://problem/6501491>
<rdar://problem/6527009>
<rdar://problem/6268510>
<rdar://problem/6565238> MNT: Attempting to unmount volumes one by one fails without an error

Modified Paths:
--------------
    trunk/launchd/src/launch_priv.h
    trunk/launchd/src/launchctl.c
    trunk/launchd/src/launchd_core_logic.c
    trunk/launchd/src/libbootstrap.c

Modified: trunk/launchd/src/launch_priv.h
===================================================================
--- trunk/launchd/src/launch_priv.h	2009-03-03 05:21:24 UTC (rev 23852)
+++ trunk/launchd/src/launch_priv.h	2009-03-10 00:16:39 UTC (rev 23853)
@@ -61,6 +61,8 @@
 #define LAUNCH_JOBKEY_JETSAMPRIORITY					"JetsamPriority"
 #define LAUNCH_JOBKEY_SECURITYSESSIONUUID				"SecuritySessionUUID"
 
+#define LAUNCH_JOBKEY_EMBEDDEDSHUTDOWNAUTHORITY			"EmbeddedShutdownAuthority"
+
 #define LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL		"EnterKernelDebuggerBeforeKill"
 #define LAUNCH_JOBKEY_PERJOBMACHSERVICES				"PerJobMachServices"
 #define LAUNCH_JOBKEY_SERVICEIPC						"ServiceIPC"

Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c	2009-03-03 05:21:24 UTC (rev 23852)
+++ trunk/launchd/src/launchctl.c	2009-03-10 00:16:39 UTC (rev 23853)
@@ -270,8 +270,8 @@
 #if 0
 static bool g_job_cache_db_has_changed = false;
 static launch_data_t g_job_cache_db = NULL;
-#endif
 static char g_job_cache_db_path[PATH_MAX];
+#endif
 
 int
 main(int argc, char *const argv[])
@@ -325,7 +325,7 @@
 		int64_t manager_uid = -1, manager_pid = -1;
 		if( vproc_swap_integer(NULL, VPROC_GSK_MGR_UID, NULL, &manager_uid) == NULL ) {
 			if( vproc_swap_integer(NULL, VPROC_GSK_MGR_PID, NULL, &manager_pid) == NULL ) {
-				if( manager_uid || manager_uid == 1 ) {
+				if( manager_uid || manager_pid == 1 ) {
 					fprintf(stderr, "Running in the root user's per-user context is not supported outside of the root user's bootstrap.\n");
 					exit(EXIT_FAILURE);
 				}
@@ -350,32 +350,6 @@
 		}
 	}
 
-	char *db = NULL;
-	vproc_err_t verr = vproc_swap_string(NULL, VPROC_GSK_JOB_OVERRIDES_DB, NULL, &db);
-	if( verr ) {
-		fprintf(stderr, "Could not get location of job overrides database.\n");
-		g_job_overrides_db_path[0] = 0;
-	} else {
-		strncpy(g_job_overrides_db_path, db, strlen(db));
-		free(db);
-		
-		g_job_overrides_db = (CFMutableDictionaryRef)CreateMyPropertyListFromFile(g_job_overrides_db_path);
-		if( !g_job_overrides_db ) {
-			g_job_overrides_db = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-		}
-	}
-	
-	verr = vproc_swap_string(NULL, VPROC_GSK_JOB_CACHE_DB, NULL, &db);
-	if( verr ) {
-		fprintf(stderr, "Could not get location of job cache database.\n");
-		g_job_cache_db_path[0] = 0;
-	} else {
-		strncpy(g_job_cache_db_path, db, strlen(db));
-		free(db);
-		
-		/* Create our launch_data_t from the file... */
-	}
-	
 	if (NULL == readline) {
 		fprintf(stderr, "missing library: readline\n");
 		exit(EXIT_FAILURE);
@@ -2120,7 +2094,7 @@
 		char *load_launchd_items[] = { "load", "-S", session_type, "-D", "all", NULL, NULL, NULL, NULL, NULL, NULL };
 		int the_argc = 5;
 
-		char *load_launchd_items_user[] = { "load", "-S", session_type, "-D", "user", NULL };
+		char *load_launchd_items_user[] = { "load", "-S", VPROCMGR_SESSION_BACKGROUND, "-D", "user", NULL };
 		int the_argc_user = 0;
 		
 		if (is_safeboot()) {
@@ -2137,35 +2111,17 @@
 			if (strcasecmp(session_type, VPROCMGR_SESSION_LOGINWINDOW) == 0) {
 				load_launchd_items[the_argc] = "/etc/mach_init_per_login_session.d";
 				the_argc += 1;
-			} else {
-			#if 0
-				/* If we're a per-user launchd initializing our Background session,
-				 * don't forget about the user's launchd jobs that may be specified as
-				 * LimitLoadToSessionType = Background. <rdar://problem/5279345> We also
-				 * must keep in mind that we need to load the user jobs last, since the
-				 * jobs in the local sessions may be responsible for mounting the home
-				 * directory.
-				 */
-				if( getppid() != 1 ) {
-					the_argc_user = 5;
-				}
-			#else
-				/* This deadlocks against mount_url when logging in with a network home
-				 * directory. For now, we'll just load user Background agents when
-				 * bootstrapping the Aqua or StandardIO sessions. This way, we can 
-				 * safely assume that the home directory is present. Yes it's a hack,
-				 * but it satisfies the user expectation in 99% of cases.
-				 */
-				if( 0 ) {
-					the_argc_user = 5;
-				}
-			#endif
 			}
 		} else if (strcasecmp(session_type, VPROCMGR_SESSION_AQUA) == 0) {
 			load_launchd_items[5] = "/etc/mach_init_per_user.d";
 			the_argc += 1;
-			/* If we're bootstrapping the Aqua session, bootstrap the user's Background
-			 * agents.
+			/* For now, we'll just load user Background agents when
+			 * bootstrapping the Aqua session. This way, we can 
+			 * safely assume that the home directory is present. If
+			 * we try reading the user's Background agents when we're
+			 * actually bootstrapping the Background session, we run the
+			 * risk of deadlocking against mount_url. But this fix should
+			 * satisfy <rdar://problem/5279345>.
 			 */
 			the_argc_user = 5;
 			
@@ -2180,11 +2136,6 @@
 			 * problem.
 			 */
 			read_environment_dot_plist();
-		} else if (strcasecmp(session_type, VPROCMGR_SESSION_AQUA) == 0) {
-			/* If we're bootstrapping the StandardIO session, bootstrap the user's Background
-			 * agents.
-			 */
-			the_argc_user = 5;
 		}
 
 		if (strcasecmp(session_type, VPROCMGR_SESSION_BACKGROUND) == 0) {
@@ -2198,13 +2149,10 @@
 		int retval = load_and_unload_cmd(the_argc, load_launchd_items);
 		if( retval == 0 && the_argc_user != 0 ) {
 			optind = 1;
-			pid_t p = getpid();
-			if( sysctlbyname("vfs.generic.noremotehang", NULL, NULL, &p, sizeof(p)) == 0 ) {
-				int64_t junk = 0;
-				vproc_err_t err = vproc_swap_integer(NULL, VPROC_GSK_WEIRD_BOOTSTRAP, &junk, NULL);
-				if( !err ) {
-					retval = load_and_unload_cmd(the_argc_user, load_launchd_items_user);
-				}
+			int64_t junk = 0;
+			vproc_err_t err = vproc_swap_integer(NULL, VPROC_GSK_WEIRD_BOOTSTRAP, &junk, NULL);
+			if( !err ) {
+				retval = load_and_unload_cmd(the_argc_user, load_launchd_items_user);
 			}
 		}
 		
@@ -2278,6 +2226,28 @@
 		return 1;
 	}
 
+	int dbfd = -1;
+	char *db = NULL;
+	vproc_err_t verr = vproc_swap_string(NULL, VPROC_GSK_JOB_OVERRIDES_DB, NULL, &db);
+	if( verr ) {
+		fprintf(stderr, "Could not get location of job overrides database.\n");
+		g_job_overrides_db_path[0] = 0;
+	} else {
+		strncpy(g_job_overrides_db_path, db, strlen(db));
+		free(db);
+		
+		/* If we can't create or lock the overrides database, we'll fall back to writing to the
+		 * plist file directly.
+		 */
+		assumes((dbfd = open(db, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1);
+		if( dbfd != -1 ) {
+			g_job_overrides_db = (CFMutableDictionaryRef)CreateMyPropertyListFromFile(g_job_overrides_db_path);
+			if( !g_job_overrides_db ) {
+				g_job_overrides_db = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+			}
+		}
+	}
+
 	/* I wish I didn't need to do three passes, but I need to load mDNSResponder and use it too.
 	 * And loading legacy mach init jobs is extra fun.
 	 *
@@ -2345,7 +2315,9 @@
 	if( g_job_overrides_db_has_changed ) {
 		WriteMyPropertyListToFile(g_job_overrides_db, g_job_overrides_db_path);
 	}
-
+	
+	flock(dbfd, LOCK_UN);
+	close(dbfd);
 	return 0;
 }
 
@@ -3029,7 +3001,7 @@
 	CFTypeRef value = NULL;	
 	do {
 		io_registry_entry_t entry = IORegistryEntryFromPath(kIOMasterPortDefault, "IODeviceTree:/options");
-		if( assumes(entry != IO_OBJECT_NULL) ) {
+		if( !assumes(entry != IO_OBJECT_NULL) ) {
 			break;
 		}
 		

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2009-03-03 05:21:24 UTC (rev 23852)
+++ trunk/launchd/src/launchd_core_logic.c	2009-03-10 00:16:39 UTC (rev 23853)
@@ -527,6 +527,7 @@
 			is_bootstrapper				:1, /* The job is a bootstrapper. */
 			has_console					:1, /* The job owns the console. */
 			clean_exit_timer_expired	:1, /* The job was clean, received SIGKILL and failed to exit after LAUNCHD_CLEAN_KILL_TIMER seconds. */
+			embedded_shutdown_auth		:1, /* The job is allowed to call reboot2() on embedded. */
 			migratory					:1; /* The (anonymous) job called vprocmgr_switch_to_session(). */
 	mode_t mask;
 	pid_t tracing_pid;
@@ -642,6 +643,7 @@
 #else
 pid_t g_audit_session = 0;
 #endif
+static bool s_embedded_shutdown_right_claimed = false;
 static pid_t s_update_pid = 0;
 static int s_no_hang_fd = -1;
 
@@ -1686,6 +1688,9 @@
 		} else if (strcasecmp(key, LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL) == 0) {
 			j->debug_before_kill = value;
 			found_key = true;
+		} else if( !s_embedded_shutdown_right_claimed && strcasecmp(key, LAUNCH_JOBKEY_EMBEDDEDSHUTDOWNAUTHORITY) == 0 ) {
+			j->embedded_shutdown_auth = true;
+			s_embedded_shutdown_right_claimed = true;
 		}
 		break;
 	case 'w':
@@ -3512,6 +3517,8 @@
 	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, kevent_mod((uintptr_t)j, EVFILT_TIMER, EV_ADD|EV_ONESHOT, NOTE_SECONDS, 1, j) != -1);
+		
 		job_assumes(j, runtime_close(execspair[0]) == 0);
 		job_assumes(j, runtime_close(execspair[1]) == 0);
 		if (sipc) {
@@ -7242,7 +7249,11 @@
 		return BOOTSTRAP_NOT_PRIVILEGED;
 	}
 
-	if (unlikely(ldc->euid)) {
+#if !TARGET_OS_EMBEDDED
+	if( unlikely(ldc->euid) ) {
+#else
+	if( unlikely(ldc->euid) && !j->embedded_shutdown_auth ) {
+#endif
 		return BOOTSTRAP_NOT_PRIVILEGED;
 	}
 

Modified: trunk/launchd/src/libbootstrap.c
===================================================================
--- trunk/launchd/src/libbootstrap.c	2009-03-03 05:21:24 UTC (rev 23852)
+++ trunk/launchd/src/libbootstrap.c	2009-03-10 00:16:39 UTC (rev 23853)
@@ -179,21 +179,21 @@
 	static mach_port_t prev_bp;
 	static mach_port_t prev_sp;
 	static name_t prev_name;
-	static bool privileged_server_okay;
 	audit_token_t au_tok;
 	bool per_pid_lookup = flags & BOOTSTRAP_PER_PID_SERVICE;
+	bool privileged_server_lookup = flags & BOOTSTRAP_PRIVILEGED_SERVER;
 	kern_return_t kr = 0;
 	mach_port_t puc;
-
+	
 	pthread_mutex_lock(&bslu2_lock);
-
-	if (per_pid_lookup) {
+	
+	if (per_pid_lookup || privileged_server_lookup) {
 		goto skip_cache;
 	}
-
+	
 	if (prev_sp) {
        	if ((bp == prev_bp) && (strncmp(prev_name, service_name, sizeof(name_t)) == 0)
-				&& (mach_port_mod_refs(mach_task_self(), prev_sp, MACH_PORT_RIGHT_SEND, 1) == 0)) {
+			&& (mach_port_mod_refs(mach_task_self(), prev_sp, MACH_PORT_RIGHT_SEND, 1) == 0)) {
 			*sp = prev_sp;
 			goto out;
 		} else {
@@ -201,49 +201,45 @@
 			prev_sp = 0;
 		}
 	}
-
+	
 skip_cache:
-	privileged_server_okay = false;
 	if ((kr = vproc_mig_look_up2(bp, (char *)service_name, sp, &au_tok, target_pid, flags)) != VPROC_ERR_TRY_PER_USER) {
 		goto out;
 	}
-
+	
 	if ((kr = vproc_mig_lookup_per_user_context(bp, 0, &puc)) != 0) {
 		goto out;
 	}
-
+	
 	kr = vproc_mig_look_up2(puc, (char *)service_name, sp, &au_tok, target_pid, flags);
 	mach_port_deallocate(mach_task_self(), puc);
-
+	
 out:
-	if (!per_pid_lookup && kr == 0 && prev_sp == 0 && mach_port_mod_refs(mach_task_self(), *sp, MACH_PORT_RIGHT_SEND, 1) == 0) {
+	if (!(per_pid_lookup || privileged_server_lookup) && kr == 0 && prev_sp == 0 && mach_port_mod_refs(mach_task_self(), *sp, MACH_PORT_RIGHT_SEND, 1) == 0) {
 		/* We're going to hold on to a send right as a MRU cache */
 		prev_bp = bp;
 		prev_sp = *sp;
 		strlcpy(prev_name, service_name, sizeof(name_t));
 	}
-
-	if ((kr == 0) && (flags & BOOTSTRAP_PRIVILEGED_SERVER) && !privileged_server_okay) {
+	
+	if ((kr == 0) && privileged_server_lookup) {
 		uid_t server_euid;
-
+		
 		/*
 		 * The audit token magic is dependent on the per-user launchd
 		 * forwarding MIG requests to the root launchd when it cannot
 		 * find the answer locally.
 		 */
-
+		
 		/* This API should be in Libsystem, but is not */
 		//audit_token_to_au32(au_tok, NULL, &server_euid, NULL, NULL, NULL, NULL, NULL, NULL);
 		
 		server_euid = au_tok.val[1];
-
+		
 		if (server_euid) {
 			mach_port_deallocate(mach_task_self(), *sp);
 			kr = BOOTSTRAP_NOT_PRIVILEGED;
-		} else {
-			privileged_server_okay = true;
 		}
-
 	}
 	/* If performance becomes a problem, we should restructure this. */
 	pthread_mutex_unlock(&bslu2_lock);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/launchd-changes/attachments/20090309/81873ee4/attachment-0001.html>


More information about the launchd-changes mailing list