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

source_changes at macosforge.org source_changes at macosforge.org
Sat Feb 28 13:15:57 PST 2009


Revision: 23849
          http://trac.macosforge.org/projects/launchd/changeset/23849
Author:   dsorresso at apple.com
Date:     2009-02-28 13:15:57 -0800 (Sat, 28 Feb 2009)
Log Message:
-----------
<rdar://problem/6476424> launchd adoption of audit session objects
<rdar://problem/6633748> _vprocmgr_switch_to_session() should return success if you're already in the target session

Modified Paths:
--------------
    trunk/launchd/src/launch_priv.h
    trunk/launchd/src/launchctl.c
    trunk/launchd/src/launchd.c
    trunk/launchd/src/launchd_core_logic.c
    trunk/launchd/src/launchd_core_logic.h
    trunk/launchd/src/launchd_mig_types.defs
    trunk/launchd/src/launchd_runtime.c
    trunk/launchd/src/launchd_runtime.h
    trunk/launchd/src/liblaunch.c
    trunk/launchd/src/libvproc.c
    trunk/launchd/src/protocol_vproc.defs
    trunk/launchd/src/vproc_internal.h
    trunk/launchd/src/vproc_priv.h

Modified: trunk/launchd/src/launch_priv.h
===================================================================
--- trunk/launchd/src/launch_priv.h	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launch_priv.h	2009-02-28 21:15:57 UTC (rev 23849)
@@ -25,6 +25,7 @@
 #include <launch.h>
 #include <unistd.h>
 #include <paths.h>
+#include <uuid/uuid.h>
 
 #pragma GCC visibility push(default)
 
@@ -58,6 +59,7 @@
 #define LAUNCH_JOBKEY_SANDBOXFLAGS						"SandboxFlags"
 #define LAUNCH_JOBKEY_SANDBOX_NAMED						"Named"
 #define LAUNCH_JOBKEY_JETSAMPRIORITY					"JetsamPriority"
+#define LAUNCH_JOBKEY_SECURITYSESSIONUUID				"SecuritySessionUUID"
 
 #define LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL		"EnterKernelDebuggerBeforeKill"
 #define LAUNCH_JOBKEY_PERJOBMACHSERVICES				"PerJobMachServices"

Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launchctl.c	2009-02-28 21:15:57 UTC (rev 23849)
@@ -255,6 +255,8 @@
 static bool do_apple_internal_magic;
 static bool system_context;
 static bool rootuser_context;
+static bool bootstrapping_system;
+static bool bootstrapping_peruser;
 static bool g_shutdown_debugging = false;
 
 int
@@ -860,6 +862,14 @@
 	if (job_disabled && lus->load) {
 		goto out_bad;
 	}
+	
+	if( bootstrapping_system || bootstrapping_peruser ) {
+		uuid_t uuid;
+		uuid_clear(uuid);
+		
+		launch_data_t uuid_d = launch_data_new_opaque(uuid, sizeof(uuid_t));
+		launch_data_dict_insert(thejob, uuid_d, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+	}
 
 	if (delay_to_second_pass(thejob)) {
 		launch_data_array_append(lus->pass2, thejob);
@@ -1899,7 +1909,6 @@
 
 	_vproc_set_global_on_demand(true);
 
-	
 #if !TARGET_OS_EMBEDDED
 	char *load_launchd_items[] = { "load", "-D", "all", "/etc/mach_init.d", NULL };
 	int load_launchd_items_cnt = 4;
@@ -2031,6 +2040,7 @@
 	}
 
 	if (strcasecmp(session_type, "System") == 0) {
+		bootstrapping_system = true;
 		system_specific_bootstrap(sflag);
 	} else {
 		char *load_launchd_items[] = { "load", "-S", session_type, "-D", "all", NULL, NULL, NULL, NULL, NULL, NULL };
@@ -2104,6 +2114,7 @@
 		}
 
 		if (strcasecmp(session_type, VPROCMGR_SESSION_BACKGROUND) == 0) {
+			bootstrapping_peruser = true;
 			read_launchd_conf();
 #if 0 /* XXX PR-6456403 */
 			assumes(SessionCreate(sessionKeepCurrentBootstrap, 0) == 0);

Modified: trunk/launchd/src/launchd.c
===================================================================
--- trunk/launchd/src/launchd.c	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launchd.c	2009-02-28 21:15:57 UTC (rev 23849)
@@ -45,6 +45,7 @@
 #include <sys/kern_event.h>
 #include <sys/reboot.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netinet/in_var.h>
@@ -116,6 +117,7 @@
 bool fake_shutdown_in_progress;
 bool network_up;
 char g_username[128] = "__Uninitialized__";
+char g_my_label[128] = "__Uninitialized__";
 FILE *g_console = NULL;
 
 int
@@ -187,6 +189,15 @@
 			strlcpy(g_username, pwent->pw_name, sizeof(g_username) - 1);
 		}
 		
+		snprintf(g_my_label, sizeof(g_my_label), "com.apple.launchd.peruser.%u", getuid());
+		
+		auditinfo_addr_t auinfo;
+		if( launchd_assumes(getaudit_addr(&auinfo, sizeof(auinfo)) != -1) ) {
+			g_audit_session = auinfo.ai_asid;
+			runtime_syslog(LOG_DEBUG, "Our audit session ID is %i", g_audit_session);
+		}
+		
+		g_audit_session_port = _audit_session_self();
 		runtime_syslog(LOG_DEBUG, "Per-user launchd for UID %u (%s) has begun.", getuid(), g_username);
 	}
 
@@ -404,9 +415,30 @@
 	launchd_assumes(setsid() != -1);
 	launchd_assumes(chdir("/") != -1);
 	launchd_assumes(setlogin("root") != -1);
+	
+	strcpy(g_my_label, "com.apple.launchd");
+
+#if !TARGET_OS_EMBEDDED	
+	auditinfo_addr_t auinfo = {
+		.ai_termid = { .at_type = AU_IPv4 },
+		.ai_asid = AU_ASSIGN_ASID,
+		.ai_flags = sessionIsRoot,
+	};
+	
+	if( !launchd_assumes(setaudit_addr(&auinfo, sizeof(auinfo)) != -1) ) {
+		runtime_syslog(LOG_WARNING | LOG_CONSOLE, "Could not set audit session! (errno = %d)", errno);
+		_exit(EXIT_FAILURE);
+	}
+
+	if( launchd_assumes(getaudit_addr(&auinfo, sizeof(auinfo)) != -1) ) {
+		g_audit_session = auinfo.ai_asid;
+		runtime_syslog(LOG_DEBUG, "Our audit session ID is %i", g_audit_session);
+	}
+
+	g_audit_session_port = _audit_session_self();
+#endif
 }
 
-
 int
 _fd(int fd)
 {

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launchd_core_logic.c	2009-02-28 21:15:57 UTC (rev 23849)
@@ -52,6 +52,7 @@
 #include <sys/pipe.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netinet/in_var.h>
@@ -340,6 +341,7 @@
 	STAILQ_HEAD(, job_s) pending_samples;
 	mach_port_t jm_port;
 	mach_port_t req_port;
+	mach_port_t init_audit_session;
 	jobmgr_t parentmgr;
 	int reboot_flags;
 	unsigned int global_on_demand_cnt;
@@ -362,7 +364,7 @@
 #define jobmgr_assumes(jm, e)	\
 	(unlikely(!(e)) ? jobmgr_log_bug(jm, __LINE__), 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 jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name, mach_port_t session_port);
 static job_t jobmgr_import2(jobmgr_t jm, launch_data_t pload);
 static jobmgr_t jobmgr_parent(jobmgr_t jm);
 static jobmgr_t jobmgr_do_hopefully_first_shutdown_phase(jobmgr_t jm);
@@ -397,7 +399,8 @@
 
 struct job_s {
 	kq_callback kqjob_callback;	/* MUST be first element of this structure for benefit of launchd's run loop. */
-	LIST_ENTRY(job_s) sle;								
+	LIST_ENTRY(job_s) sle;
+	LIST_ENTRY(job_s) needing_session_sle;
 	LIST_ENTRY(job_s) jetsam_sle;
 	LIST_ENTRY(job_s) pid_hash_sle;
 	LIST_ENTRY(job_s) label_hash_sle;
@@ -527,6 +530,8 @@
 			migratory					:1; /* The (anonymous) job called vprocmgr_switch_to_session(). */
 	mode_t mask;
 	pid_t tracing_pid;
+	mach_port_t audit_session;
+	uuid_t expected_audit_uuid;
 	const char label[0];
 };
 
@@ -562,9 +567,6 @@
 static bool job_setup_machport(job_t j);
 static void job_setup_fd(job_t j, int target_fd, const char *path, int flags);
 static void job_postfork_become_user(job_t j);
-#if !TARGET_OS_EMBEDDED
-static void job_enable_audit_for_user(job_t j, uid_t u, char *name);
-#endif
 static void job_postfork_test_user(job_t j);
 static void job_log_pids_with_weird_uids(job_t j);
 static void job_setup_exception_port(job_t j, task_t target_task);
@@ -633,6 +635,13 @@
 static size_t total_anon_children;
 static mach_port_t the_exception_server;
 static job_t workaround_5477111;
+static LIST_HEAD(, job_s) s_needing_sessions;
+mach_port_t g_audit_session_port = MACH_PORT_NULL;
+#if !TARGET_OS_EMBEDDED
+au_asid_t g_audit_session = AU_DEFAUDITSID;
+#else
+pid_t g_audit_session = 0;
+#endif
 static pid_t s_update_pid = 0;
 static int s_no_hang_fd = -1;
 
@@ -1143,6 +1152,12 @@
 		LIST_REMOVE(j, jetsam_sle);
 		j->mgr->jetsam_jobs_cnt--;
 	}
+	if( j->audit_session != MACH_PORT_NULL ) {
+		job_assumes(j, mach_port_deallocate(mach_task_self(), j->audit_session) == KERN_SUCCESS);
+	}
+	if( !uuid_is_null(j->expected_audit_uuid) ) {
+		LIST_REMOVE(j, needing_session_sle);
+	}
 	
 	kevent_mod((uintptr_t)j, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
 	kevent_mod((uintptr_t)j, EVFILT_PROC, EV_DELETE, 0, 0, NULL);
@@ -1468,6 +1483,7 @@
 	j->ondemand = true;
 	j->checkedin = true;
 	j->jetsam_priority = LAUNCHD_JETSAM_PRIORITY_UNSET;
+	uuid_clear(j->expected_audit_uuid);
 	
 	if (prog) {
 		j->prog = strdup(prog);
@@ -1507,6 +1523,7 @@
 
 	LIST_INSERT_HEAD(&jm->jobs, j, sle);
 	LIST_INSERT_HEAD(&label_hash[hash_label(j->label)], j, label_hash_sle);
+	uuid_clear(j->expected_audit_uuid);
 
 	job_log(j, LOG_DEBUG, "Conceived");
 
@@ -1903,6 +1920,14 @@
 			}
 		}
 #endif
+	case 's':
+	case 'S':
+		if( strcasecmp(key, LAUNCH_JOBKEY_SECURITYSESSIONUUID) == 0 ) {
+			size_t tmpsz = launch_data_get_opaque_size(value);
+			if( job_assumes(j, tmpsz == sizeof(uuid_t)) ) {
+				memcpy(j->expected_audit_uuid, launch_data_get_opaque(value), sizeof(uuid_t));
+			}
+		}
 		break;
 	default:
 		break;
@@ -2203,6 +2228,15 @@
 
 	if (likely(j = job_new(jm, label, prog, argv))) {
 		launch_data_dict_iterate(pload, job_import_keys, j);
+		if( !uuid_is_null(j->expected_audit_uuid) ) {
+			uuid_string_t uuid_str;
+			uuid_unparse(j->expected_audit_uuid, uuid_str);
+			job_log(j, LOG_DEBUG, "Imported job. Waiting for session for UUID %s.", uuid_str);
+			LIST_INSERT_HEAD(&s_needing_sessions, j, needing_session_sle);
+		} else {
+			job_log(j, LOG_DEBUG, "No security session specified.");
+			j->audit_session = MACH_PORT_NULL;
+		}
 	}
 
 	return j;
@@ -2894,6 +2928,11 @@
 job_t
 job_dispatch(job_t j, bool kickstart)
 {
+	/* Don't dispatch a job if it has no audit session set. */
+	if( !uuid_is_null(j->expected_audit_uuid) ) {
+		return NULL;
+	}
+	
 	/*
 	 * The whole job removal logic needs to be consolidated. The fact that
 	 * a job can be removed from just about anywhere makes it easy to have
@@ -2901,7 +2940,7 @@
 	 * used after the deallocation. In particular, during job iteration.
 	 *
 	 * This is a classic example. The act of dispatching a job may delete it.
-	 */
+	 */	
 	if (!job_active(j)) {
 		if (job_useless(j)) {
 			job_remove(j);
@@ -3903,10 +3942,6 @@
 		desired_gid = gre->gr_gid;
 	}
 
-#if !TARGET_OS_EMBEDDED
-	job_enable_audit_for_user(j, desired_uid, loginname);
-#endif
-
 	if (!job_assumes(j, setlogin(loginname) != -1)) {
 		_exit(EXIT_FAILURE);
 	}
@@ -3957,31 +3992,7 @@
 	setenv("LOGNAME", loginname, 0);
 }
 
-#if !TARGET_OS_EMBEDDED
 void
-job_enable_audit_for_user(job_t j, uid_t u, char *name)
-{
-	auditinfo_t auinfo = {
-		.ai_auid = u,
-		.ai_asid = j->p,
-	};
-	long au_cond;
-
-	if (!job_assumes(j, auditon(A_GETCOND, &au_cond, sizeof(long)) == 0)) {
-		_exit(EXIT_FAILURE);
-	}
-
-	if (au_cond != AUC_NOAUDIT) {
-		if (!job_assumes(j, au_user_mask(name, &auinfo.ai_mask) == 0)) {
-			_exit(EXIT_FAILURE);
-		} else if (!job_assumes(j, setaudit(&auinfo) == 0)) {
-			_exit(EXIT_FAILURE);
-		}
-	}
-}
-#endif
-
-void
 job_setup_attributes(job_t j)
 {
 	struct limititem *li;
@@ -4010,6 +4021,23 @@
 		}
 	}
 
+#if !TARGET_OS_EMBEDDED
+	if( unlikely(j->per_user) ) {
+		auditinfo_addr_t auinfo = {
+			.ai_termid = { .at_type = AU_IPv4 },
+			.ai_auid = j->mach_uid,
+			.ai_asid = AU_ASSIGN_ASID,
+		};
+		
+		if( !launchd_assumes(setaudit_addr(&auinfo, sizeof(auinfo)) != -1) ) {
+			runtime_syslog(LOG_WARNING | LOG_CONSOLE, "Could not set audit session! (errno = %d)", errno);
+			_exit(EXIT_FAILURE);
+		} else {
+			job_log(j, LOG_DEBUG, "Created new security session for per-user launchd.");
+		}
+	}
+#endif
+
 	if (unlikely(!j->inetcompat && j->session_create)) {
 		launchd_SessionCreate();
 	}
@@ -4242,7 +4270,7 @@
 	bool log_to_console = pri & LOG_CONSOLE;
 	int _pri = pri & ~LOG_CONSOLE;
 	
-	struct runtime_syslog_attr attr = { "com.apple.launchd", j->label, j->mgr->name, _pri, getuid(), getpid(), j->p };
+	struct runtime_syslog_attr attr = { g_my_label, j->label, j->mgr->name, _pri, getuid(), getpid(), j->p };
 	char *newmsg;
 	int oldmask = 0;
 	size_t newmsgsz;
@@ -4358,7 +4386,7 @@
 		bool log_to_console = pri & LOG_CONSOLE;
 		int _pri = pri & ~LOG_CONSOLE;
 		
-		struct runtime_syslog_attr attr = { "com.apple.launchd", "com.apple.launchd", jm->name, _pri, getuid(), getpid(), getpid() };
+		struct runtime_syslog_attr attr = { g_my_label, g_my_label, jm->name, _pri, getuid(), getpid(), getpid() };
 
 		runtime_vsyslog(&attr, log_to_console, newmsg, ap);
 	}
@@ -5492,7 +5520,7 @@
 	
 	/* If we've killed everyone, move on. */
 	if( unkilled_cnt == 0 ) {
-		jm->killed_hopefully_first_jobs = true;
+		jm->killed_normal_jobs = true;
 		jm = NULL;
 	}
 	
@@ -5554,7 +5582,7 @@
 	
 	/* If we've killed everyone, move on. */
 	if( unkilled_cnt == 0 ) {
-		jm->killed_hopefully_first_jobs = true;
+		jm->killed_hopefully_last_jobs = true;
 		jm = NULL;
 	}
 	
@@ -5760,7 +5788,7 @@
 }
 
 jobmgr_t 
-jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name)
+jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name, mach_port_t session_port)
 {
 	mach_msg_size_t mxmsgsz;
 	job_t bootstrapper = NULL;
@@ -5859,6 +5887,8 @@
 	jobmgr_log(jmr, LOG_DEBUG, "Created job manager%s%s", jm ? " with parent: " : ".", jm ? jm->name : "");
 
 	if (bootstrapper) {
+		bootstrapper->audit_session = session_port;
+		jobmgr_log(jmr, LOG_DEBUG, "Bootstrapping new job manager with audit session %u", session_port);
 		jobmgr_assumes(jmr, job_dispatch(bootstrapper, true) != NULL);
 	}
 
@@ -5909,7 +5939,7 @@
 		#endif
 		}
 	}
-	
+
 	jm->session_initialized = true;
 
 	return bootstrapper;
@@ -6783,8 +6813,8 @@
 
 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) 
+					 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 = NULL, output_obj = NULL;
@@ -7118,7 +7148,7 @@
 }
 
 kern_return_t
-job_mig_post_fork_ping(job_t j, task_t child_task)
+job_mig_post_fork_ping(job_t j, task_t child_task, mach_port_t *audit_session)
 {
 	struct machservice *ms;
 
@@ -7155,6 +7185,14 @@
 		}
 	}
 
+	mach_port_t _session = MACH_PORT_NULL;
+#if !TARGET_OS_EMBEDDED
+	if( !j->anonymous && !j->per_user ) {
+		job_log(j, LOG_DEBUG, "Returning session port %u", j->audit_session);
+		_session = j->audit_session;
+	}
+#endif	
+	*audit_session = _session;
 	job_assumes(j, launchd_mport_deallocate(child_task) == KERN_SUCCESS);
 
 	return 0;
@@ -7823,6 +7861,51 @@
 	return kr;
 }
 
+#if !TARGET_OS_EMBEDDED
+kern_return_t
+job_mig_set_security_session(job_t j, uuid_t uuid, mach_port_t session)
+{
+	uuid_string_t uuid_str;
+	uuid_unparse(uuid, uuid_str);
+	job_log(j, LOG_DEBUG, "Setting session %u for UUID %s...", session, uuid_str);
+	
+	job_t ji = NULL, jt = NULL;
+	LIST_FOREACH_SAFE( ji, &s_needing_sessions, sle, jt ) {
+		uuid_string_t uuid_str2;
+		uuid_unparse(ji->expected_audit_uuid, uuid_str2);
+
+		if( uuid_compare(uuid, ji->expected_audit_uuid) == 0 ) {
+			uuid_clear(ji->expected_audit_uuid);
+			if( session != MACH_PORT_NULL  ) {
+				job_log(ji, LOG_DEBUG, "Job should join session with port %u", session);
+				mach_port_mod_refs(mach_task_self(), session, MACH_PORT_RIGHT_SEND, 1);
+			} else {
+				job_log(ji, LOG_DEBUG, "No session to set for job. Using our session.");
+			}
+			
+			ji->audit_session = session;
+			LIST_REMOVE(ji, needing_session_sle);
+			job_dispatch(ji, false);
+		}
+	}
+	
+	/* Each job that the session port was set for holds a reference. At the end of
+	 * the loop, there will be one extra reference belonging to this MiG protocol.
+	 * We need to release it so that the session goes away when all the jobs
+	 * referencing it are unloaded.
+	 */
+	mach_port_deallocate(mach_task_self(), session);
+
+	return KERN_SUCCESS;
+}
+#else
+kern_return_t
+job_mig_set_security_session(job_t j __attribute__((unused)), uuid_t uuid __attribute__((unused)), mach_port_t session __attribute__((unused)))
+{
+	return KERN_SUCCESS;
+}
+#endif
+
 jobmgr_t 
 jobmgr_find_by_name(jobmgr_t jm, const char *where)
 {
@@ -7866,7 +7949,7 @@
 }
 
 kern_return_t
-job_mig_move_subset(job_t j, mach_port_t target_subset, name_t session_type, uint64_t flags)
+job_mig_move_subset(job_t j, mach_port_t target_subset, name_t session_type, mach_port_t audit_session, uint64_t flags)
 {
 	mach_msg_type_number_t l2l_i, l2l_port_cnt = 0;
 	mach_port_array_t l2l_ports = NULL;
@@ -7880,50 +7963,7 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	if (target_subset == MACH_PORT_NULL) {
-		job_t j2;
-
-		if (j->mgr->session_initialized) {
-			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;
-
-			/*
-			 * 5330262
-			 *
-			 * We're working around LoginWindow and the WindowServer.
-			 *
-			 * In practice, there is only one LoginWindow session. Unfortunately, for certain
-			 * scenarios, the WindowServer spawns loginwindow, and in those cases, it frequently
-			 * spawns a replacement loginwindow session before cleaning up the previous one.
-			 *
-			 * We're going to use the creation of a new LoginWindow context as a clue that the
-			 * previous LoginWindow context is on the way out and therefore we should just
-			 * kick-start the shutdown of it.
-			 */
-
-			SLIST_FOREACH(jmi, &root_jobmgr->submgrs, sle) {
-				if (unlikely(jmi->shutting_down)) {
-					continue;
-				} else if (strcasecmp(jmi->name, session_type) == 0) {
-					jobmgr_shutdown(jmi);
-					break;
-				}
-			}
-		}
-
-		jobmgr_log(j->mgr, LOG_DEBUG, "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)))) {
-			job_assumes(j, job_dispatch(j2, true));
-		}
-
-		kr = 0;
-		goto out;
-	} else if (job_mig_intran2(root_jobmgr, target_subset, ldc->pid)) {
+	if (job_mig_intran2(root_jobmgr, target_subset, ldc->pid)) {
 		job_log(j, LOG_ERR, "Moving a session to ourself is bogus.");
 
 		kr = BOOTSTRAP_NOT_PRIVILEGED;
@@ -7940,7 +7980,7 @@
 
 	launchd_assert(launch_data_array_get_count(out_obj_array) == l2l_port_cnt);
 
-	if (!job_assumes(j, (jmr = jobmgr_new(j->mgr, reqport, rcvright, false, session_type)) != NULL)) {
+	if (!job_assumes(j, (jmr = jobmgr_new(j->mgr, reqport, rcvright, false, session_type, audit_session)) != NULL)) {
 		kr = BOOTSTRAP_NO_MEMORY;
 		goto out;
 	}
@@ -8014,7 +8054,7 @@
 }
 
 kern_return_t
-job_mig_init_session(job_t j, name_t session_type)
+job_mig_init_session(job_t j, name_t session_type, mach_port_t audit_session)
 {
 	job_t j2;
 	
@@ -8053,6 +8093,7 @@
 	strcpy(j->mgr->name_init, session_type);
 	
 	if (job_assumes(j, (j2 = jobmgr_init_session(j->mgr, session_type, false)))) {
+		j2->audit_session = audit_session;
 		job_assumes(j, job_dispatch(j2, true));
 		kr = BOOTSTRAP_SUCCESS;
 	}
@@ -8061,9 +8102,9 @@
 }
 
 kern_return_t
-job_mig_switch_to_session(job_t j, mach_port_t requestor_port, name_t session_name, mach_port_t *new_bsport)
+job_mig_switch_to_session(job_t j, mach_port_t requestor_port, name_t session_name, mach_port_t audit_session, mach_port_t *new_bsport)
 {
-	job_log(j, LOG_NOTICE, "Job wants to move to %s session.", session_name);
+	job_log(j, LOG_DEBUG, "Job wants to move to %s session.", session_name);
 	
 	if( !job_assumes(j, pid1_magic == false) ) {
 		job_log(j, LOG_WARNING, "Switching sessions is not allowed in the system Mach bootstrap.");
@@ -8077,11 +8118,18 @@
 	
 	jobmgr_t target_jm = jobmgr_find_by_name(root_jobmgr, session_name);
 	if( target_jm == j->mgr ) {
-		job_log(j, LOG_WARNING, "Job tried to switch to its current session (%s).", session_name);
-		return BOOTSTRAP_NOT_PRIVILEGED;
+		job_log(j, LOG_DEBUG, "Job is already in its desired session (%s).", session_name);
+		*new_bsport = target_jm->jm_port;
+		return BOOTSTRAP_SUCCESS;
 	}
 	
-	target_jm = target_jm ? : jobmgr_new(j->mgr, requestor_port, MACH_PORT_NULL, false, session_name);
+	if( !target_jm ) {
+		target_jm = jobmgr_new(j->mgr, requestor_port, MACH_PORT_NULL, false, session_name, audit_session);
+		if( !target_jm ) {
+			mach_port_deallocate(mach_task_self(), audit_session);
+		}
+	}
+	
 	if( !job_assumes(j, target_jm != NULL) ) {
 		job_log(j, LOG_WARNING, "Could not find %s session!", session_name);
 		return BOOTSTRAP_NO_MEMORY;
@@ -8293,7 +8341,7 @@
 		return BOOTSTRAP_NO_MEMORY;
 	}
 
-	if (!job_assumes(j, (jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL, false, NULL)) != NULL)) {
+	if (!job_assumes(j, (jmr = jobmgr_new(j->mgr, requestorport, MACH_PORT_NULL, false, NULL, j->audit_session)) != NULL)) {
 		if (unlikely(requestorport == MACH_PORT_NULL)) {
 			return BOOTSTRAP_NOT_PRIVILEGED;
 		}
@@ -8426,7 +8474,7 @@
 }
 
 kern_return_t
-job_mig_spawn(job_t j, vm_offset_t indata, mach_msg_type_number_t indataCnt, pid_t *child_pid, mach_port_t *obsvr_port)
+job_mig_spawn(job_t j, vm_offset_t indata, mach_msg_type_number_t indataCnt, mach_port_t audit_session, pid_t *child_pid, mach_port_t *obsvr_port)
 {
 	launch_data_t input_obj = NULL;
 	size_t data_offset = 0;
@@ -8466,7 +8514,7 @@
 		jobmgr_log(j->mgr, LOG_NOTICE, "%s() can't find its session!", __func__);
 		return 1;
 	}
-	
+
 	jr = jobmgr_import2(target_jm ?: j->mgr, input_obj);
 	
 	if (!job_assumes(j, jr != NULL)) {
@@ -8486,6 +8534,8 @@
 	jr->abandon_pg = true;
 	jr->stall_before_exec = jr->wait4debugger;
 	jr->wait4debugger = false;
+	jr->audit_session = audit_session;
+	uuid_clear(jr->expected_audit_uuid);
 
 	jr = job_dispatch(jr, true);
 
@@ -8518,8 +8568,9 @@
 {
 	const char *root_session_type = pid1_magic ? VPROCMGR_SESSION_SYSTEM : VPROCMGR_SESSION_BACKGROUND;
 	SLIST_INIT(&s_curious_jobs);
+	LIST_INIT(&s_needing_sessions);
 	
-	launchd_assert((root_jobmgr = jobmgr_new(NULL, MACH_PORT_NULL, MACH_PORT_NULL, sflag, root_session_type)) != NULL);
+	launchd_assert((root_jobmgr = jobmgr_new(NULL, MACH_PORT_NULL, MACH_PORT_NULL, sflag, root_session_type, MACH_PORT_NULL)) != NULL);
 	
 	uint32_t fflags = NOTE_ATTRIB | NOTE_LINK | NOTE_REVOKE | NOTE_EXTEND | NOTE_WRITE;
 	s_no_hang_fd = open("/dev/autofs_nowait", O_EVTONLY | O_NONBLOCK);

Modified: trunk/launchd/src/launchd_core_logic.h
===================================================================
--- trunk/launchd/src/launchd_core_logic.h	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launchd_core_logic.h	2009-02-28 21:15:57 UTC (rev 23849)
@@ -29,6 +29,8 @@
 
 extern jobmgr_t root_jobmgr;
 extern mach_port_t inherited_bootstrap_port;
+extern mach_port_t g_audit_session_port;
+extern au_asid_t g_audit_session;
 extern bool g_flat_mach_namespace;
 
 void jobmgr_init(bool);

Modified: trunk/launchd/src/launchd_mig_types.defs
===================================================================
--- trunk/launchd/src/launchd_mig_types.defs	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launchd_mig_types.defs	2009-02-28 21:15:57 UTC (rev 23849)
@@ -36,6 +36,7 @@
 type bootstrap_property_array_t	= ^array [] of bootstrap_property_t;
 type bootstrap_status_t			= integer_t;
 type bootstrap_status_array_t	= ^array [] of bootstrap_status_t;
+type uuid_t						= array [16] of MACH_MSG_TYPE_BYTE;
 
 type job_t = mach_port_t
         intran		: job_t job_mig_intran(mach_port_t) 

Modified: trunk/launchd/src/launchd_runtime.c
===================================================================
--- trunk/launchd/src/launchd_runtime.c	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launchd_runtime.c	2009-02-28 21:15:57 UTC (rev 23849)
@@ -1239,9 +1239,13 @@
 	int _pri = pri & ~LOG_CONSOLE;
 	
 	struct runtime_syslog_attr attr = {
-		"com.apple.launchd", "com.apple.launchd",
+		g_my_label, 
+		g_my_label,
 		pid1_magic ? "System" : "Background",
-		_pri, getuid(), getpid(), getpid()
+		_pri, 
+		getuid(), 
+		getpid(), 
+		getpid()
 	};
 	va_list ap;
 
@@ -1271,9 +1275,8 @@
 
 	vsnprintf(newmsg, sizeof(newmsg), message, args);
 
-	if (unlikely(low_level_debug) || echo_to_console) {
-		fprintf(g_console, "%s %u\t%s %u\t%s\n", attr->from_name, attr->from_pid,
-				attr->about_name, attr->about_pid, newmsg);
+	if( g_console && (unlikely(low_level_debug) || echo_to_console) ) {
+		fprintf(g_console, "%s %u\t%s %u\t%s\n", attr->from_name, attr->from_pid, attr->about_name, attr->about_pid, newmsg);
 	}
 
 	logmsg_add(attr, saved_errno, newmsg);

Modified: trunk/launchd/src/launchd_runtime.h
===================================================================
--- trunk/launchd/src/launchd_runtime.h	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/launchd_runtime.h	2009-02-28 21:15:57 UTC (rev 23849)
@@ -101,6 +101,7 @@
 extern bool pid1_magic;
 extern bool low_level_debug;
 extern char g_username[128];
+extern char g_my_label[128];
 extern bool g_shutdown_debugging;
 extern bool g_use_gmalloc;
 extern bool g_log_per_user_shutdown;

Modified: trunk/launchd/src/liblaunch.c
===================================================================
--- trunk/launchd/src/liblaunch.c	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/liblaunch.c	2009-02-28 21:15:57 UTC (rev 23849)
@@ -40,6 +40,8 @@
 #include <errno.h>
 #include <pwd.h>
 #include <assert.h>
+#include <uuid/uuid.h>
+#include <sys/syscall.h>
 
 #ifdef __LP64__
 /* workaround: 5723161 */
@@ -951,6 +953,23 @@
 	return r;
 }
 
+extern kern_return_t vproc_mig_set_security_session(mach_port_t, uuid_t, mach_port_t);
+
+static inline bool
+uuid_data_is_null(launch_data_t d)
+{
+	bool result = false;
+	if( launch_data_get_type(d) == LAUNCH_DATA_OPAQUE && launch_data_get_opaque_size(d) == sizeof(uuid_t) ) {
+		uuid_t existing_uuid;
+		memcpy(existing_uuid, launch_data_get_opaque(d), sizeof(uuid_t));
+		
+		/* A NULL UUID tells us to keep the session inherited from the parent. */
+		result = (bool)uuid_is_null(existing_uuid);
+	}
+	
+	return result;
+}
+
 launch_data_t
 launch_msg_internal(launch_data_t d)
 {
@@ -964,6 +983,46 @@
 
 	pthread_once(&_lc_once, launch_client_init);
 
+#if !TARGET_OS_EMBEDDED
+	uuid_t uuid;
+	launch_data_t uuid_d = NULL;
+	size_t jobs_that_need_sessions = 0;
+	if( d && launch_data_get_type(d) == LAUNCH_DATA_DICTIONARY ) {
+		launch_data_t v = launch_data_dict_lookup(d, LAUNCH_KEY_SUBMITJOB);
+
+		if( v && launch_data_get_type(v) == LAUNCH_DATA_ARRAY ) {
+			size_t cnt = launch_data_array_get_count(v);
+			size_t i = 0;
+
+			uuid_generate(uuid);
+			for( i = 0; i < cnt; i++ ) {
+				launch_data_t ji = launch_data_array_get_index(v, i);
+				if( launch_data_get_type(ji) == LAUNCH_DATA_DICTIONARY ) {
+					launch_data_t existing_v = launch_data_dict_lookup(ji, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+					if( !existing_v ) {
+						/* I really wish these were reference-counted. Sigh... */
+						uuid_d = launch_data_new_opaque(uuid, sizeof(uuid));
+						launch_data_dict_insert(ji, uuid_d, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+						jobs_that_need_sessions++;
+					} else if( launch_data_get_type(existing_v) == LAUNCH_DATA_OPAQUE ) {
+						jobs_that_need_sessions += uuid_data_is_null(existing_v) ? 0 : 1;
+					}
+				}
+			}
+		} else if( v && launch_data_get_type(v) == LAUNCH_DATA_DICTIONARY ) {
+			launch_data_t existing_v = launch_data_dict_lookup(v, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+			if( !existing_v ) {
+				uuid_generate(uuid);
+				uuid_d = launch_data_new_opaque(uuid, sizeof(uuid));
+				launch_data_dict_insert(v, uuid_d, LAUNCH_JOBKEY_SECURITYSESSIONUUID);
+				jobs_that_need_sessions++;
+			} else {
+				jobs_that_need_sessions += uuid_data_is_null(existing_v) ? 0 : 1;
+			}
+		}
+	}
+#endif
+
 	if (!_lc) {
 		errno = ENOTCONN;
 		return NULL;
@@ -999,8 +1058,28 @@
 			}
 		}
 	}
+out:
+#if !TARGET_OS_EMBEDDED
+	if( !uuid_is_null(uuid) && resp && jobs_that_need_sessions > 0 ) {
+		mach_port_t session = MACH_PORT_NULL;
+		if( (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO && launch_data_get_errno(resp) == 0) || launch_data_get_type(resp) == LAUNCH_DATA_ARRAY ) {
+			session = _audit_session_self();
+		}
 
-out:
+		kern_return_t kr = KERN_FAILURE;
+		
+		/* If we can't get our own session, set the sessions for our recently-submitted jobs
+		 * to MACH_PORT_NULL.
+		 */
+		kr = vproc_mig_set_security_session(bootstrap_port, uuid, session);
+		
+		if( kr != KERN_SUCCESS || session == MACH_PORT_NULL ) {
+			launch_data_set_errno(resp, EACCES);
+			_vproc_log_error(LOG_WARNING, "Could not set security session for recently submitted jobs!");
+		}
+	}
+#endif
+
 	pthread_mutex_unlock(&_lc->mtx);
 
 	return resp;

Modified: trunk/launchd/src/libvproc.c
===================================================================
--- trunk/launchd/src/libvproc.c	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/libvproc.c	2009-02-28 21:15:57 UTC (rev 23849)
@@ -35,6 +35,7 @@
 #include <signal.h>
 #include <assert.h>
 #include <libkern/OSAtomic.h>
+#include <sys/syscall.h>
 
 #if HAVE_QUARANTINE
 #include <quarantine.h>
@@ -407,13 +408,45 @@
 vproc_err_t
 _vproc_post_fork_ping(void)
 {
-	return vproc_mig_post_fork_ping(bootstrap_port, mach_task_self()) == 0 ? NULL : _vproc_post_fork_ping;
+#if !TARGET_OS_EMBEDDED
+	au_asid_t s = AU_DEFAUDITSID;
+	do {
+		mach_port_t session = MACH_PORT_NULL;
+		kern_return_t kr = vproc_mig_post_fork_ping(bootstrap_port, mach_task_self(), &session);
+		if( kr != KERN_SUCCESS ) {
+			/* If this happens, our bootstrap port probably got hosed. */
+			_vproc_log(LOG_ERR, "Post-fork ping failed!");
+			break;
+		}
+		
+		/* If we get back MACH_PORT_NULL, that means we just stick with the session
+		 * we inherited across fork(2).
+		 */
+		if( session == MACH_PORT_NULL ) {
+			s = ~AU_DEFAUDITSID;
+			break;
+		}
+		
+		s = _audit_session_join(session);
+		if( s == 0 ) {
+			_vproc_log_error(LOG_ERR, "Could not join security session!");
+			s = AU_DEFAUDITSID;
+		} else {
+			_vproc_log(LOG_DEBUG, "Joined session %d.", s);
+		}
+	} while( 0 );
+	
+	return s != AU_DEFAUDITSID ? NULL : _vproc_post_fork_ping;
+#else
+	mach_port_t session = MACH_PORT_NULL;
+	return vproc_mig_post_fork_ping(bootstrap_port, mach_task_self(), &session) ? _vproc_post_fork_ping : NULL;
+#endif
 }
 
 vproc_err_t
 _vprocmgr_init(const char *session_type)
 {
-	if (vproc_mig_init_session(bootstrap_port, (char *)session_type) == 0) {
+	if (vproc_mig_init_session(bootstrap_port, (char *)session_type, _audit_session_self()) == 0) {
 		return NULL;
 	}
 
@@ -457,7 +490,7 @@
 		mach_port_deallocate(mach_task_self(), bootstrap_port);
 		bootstrap_port = puc;
 	} else {
-		kr = vproc_mig_move_subset(puc, bootstrap_port, (char *)session_type, flags);
+		kr = vproc_mig_move_subset(puc, bootstrap_port, (char *)session_type, _audit_session_self(), flags);
 		mach_port_deallocate(mach_task_self(), puc);
 	}
 	
@@ -475,11 +508,10 @@
 {
 	mach_port_t new_bsport = MACH_PORT_NULL;
 	kern_return_t kr = KERN_FAILURE;
-	
+
 	mach_port_t tnp = MACH_PORT_NULL;
 	task_name_for_pid(mach_task_self(), getpid(), &tnp);
-	
-	if( (kr = vproc_mig_switch_to_session(bootstrap_port, tnp, (char *)target_session, &new_bsport)) != KERN_SUCCESS ) {
+	if( (kr = vproc_mig_switch_to_session(bootstrap_port, tnp, (char *)target_session, _audit_session_self(), &new_bsport)) != KERN_SUCCESS ) {
 		_vproc_log(LOG_NOTICE, "_vprocmgr_switch_to_session(): kr = 0x%x", kr);
 		return (vproc_err_t)_vprocmgr_switch_to_session;
 	}
@@ -628,13 +660,13 @@
 
 	indata = (vm_offset_t)buf;
 
-	kr = vproc_mig_spawn(bootstrap_port, indata, indata_cnt, &p, &obsvr_port);
+	kr = vproc_mig_spawn(bootstrap_port, indata, indata_cnt, _audit_session_self(), &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, indata, indata_cnt, &p, &obsvr_port);
+			kr = vproc_mig_spawn(puc, indata, indata_cnt, _audit_session_self(), &p, &obsvr_port);
 			mach_port_deallocate(mach_task_self(), puc);
 		}
 	}

Modified: trunk/launchd/src/protocol_vproc.defs
===================================================================
--- trunk/launchd/src/protocol_vproc.defs	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/protocol_vproc.defs	2009-02-28 21:15:57 UTC (rev 23849)
@@ -83,7 +83,8 @@
 
 routine post_fork_ping(
 				__bs_port			: job_t;
-				__task_port			: task_t);
+				__task_port			: task_t;
+out				__audit_session		: mach_port_t);
 
 routine info(
 				__bs_port			: job_t;
@@ -114,6 +115,7 @@
 routine spawn(
 				__bs_port			: job_t;
 				__indata			: pointer_t;
+				__audit_session		: mach_port_t;
 out				__pid				: pid_t;
 out				__obsvr_port		: mach_port_make_send_t);
 
@@ -147,6 +149,7 @@
 				__bs_port			: job_t;
 				__target_port		: mach_port_t;
 				__sessiontype		: name_t;
+				__audit_session		: mach_port_t;
 				__sessionflags		: uint64_t);
 
 routine swap_complex(
@@ -188,6 +191,7 @@
 				__bs_port			: job_t;
 				__req_port			: mach_port_t;
 				__session_name		: name_t;
+				__audit_session		: mach_port_t;
 out				__new_bs_port		: mach_port_make_send_t);
 
 routine transaction_count_for_pid(
@@ -208,8 +212,14 @@
 
 routine init_session(
 				__bs_port			: job_t;
-				__session_name		: name_t);
+				__session_name		: name_t;
+				__audit_session		: mach_port_t);
 
+routine set_security_session(
+				__bs_port			: job_t;
+				__uuid				: uuid_t;
+				__session			: mach_port_t);
+
 routine wait2(
 				__bs_port			: job_t;
 				__target_port		: job_t;

Modified: trunk/launchd/src/vproc_internal.h
===================================================================
--- trunk/launchd/src/vproc_internal.h	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/vproc_internal.h	2009-02-28 21:15:57 UTC (rev 23849)
@@ -24,6 +24,8 @@
 #include <sys/queue.h>
 #include <sys/time.h>
 #include <stdarg.h>
+#include <sys/syscall.h>
+#include <bsm/audit.h>
 #include "launch.h"
 #include "bootstrap.h"
 #include "vproc.h"
@@ -54,6 +56,14 @@
 vproc_err_t _vprocmgr_init(const char *session_type);
 vproc_err_t _vproc_post_fork_ping(void);
 
+#if !TARGET_OS_EMBEDDED
+	#define _audit_session_self(v) (mach_port_t)syscall(SYS_audit_session_self)
+	#define _audit_session_join(s) (au_asid_t)syscall(SYS_audit_session_join, session)
+#else
+	#define _audit_session_self(v) MACH_PORT_NULL
+	#define _audit_session_join(s) 0
+#endif
+
 #define SPAWN_HAS_PATH			0x0001
 #define SPAWN_HAS_WDIR			0x0002
 #define SPAWN_HAS_UMASK			0x0004
@@ -65,7 +75,6 @@
 
 kern_return_t _vprocmgr_getsocket(name_t);
 
-
 struct logmsg_s {
 	union {
 		STAILQ_ENTRY(logmsg_s) sqe;

Modified: trunk/launchd/src/vproc_priv.h
===================================================================
--- trunk/launchd/src/vproc_priv.h	2009-02-28 06:34:34 UTC (rev 23848)
+++ trunk/launchd/src/vproc_priv.h	2009-02-28 21:15:57 UTC (rev 23849)
@@ -28,6 +28,7 @@
 #include <stdbool.h>
 #include <launch.h>
 #include <vproc.h>
+#include <uuid/uuid.h>
 
 #ifndef VPROC_HAS_TRANSACTIONS
 	#define VPROC_HAS_TRANSACTIONS
@@ -61,6 +62,7 @@
 	VPROC_GSK_TRANSACTIONS_ENABLED,
 	VPROC_GSK_WEIRD_BOOTSTRAP,
 	VPROC_GSK_WAITFORDEBUGGER,
+	VPROC_GSK_SECURITYSESSION,
 	VPROC_GSK_SHUTDOWN_DEBUGGING,
 	VPROC_GSK_PERUSER_SUSPEND,
 	VPROC_GSK_PERUSER_RESUME,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/launchd-changes/attachments/20090228/7b19c848/attachment-0001.html>


More information about the launchd-changes mailing list