[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