X-Git-Url: https://git.saurik.com/apple/configd.git/blobdiff_plain/f715d9467d5e87b8d8c63f8bb206034f6823ebcd..HEAD:/configd.tproj/session.c diff --git a/configd.tproj/session.c b/configd.tproj/session.c index 8226211..2e88cc3 100644 --- a/configd.tproj/session.c +++ b/configd.tproj/session.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, 2003-2005, 2007-2018 Apple Inc. All rights reserved. + * Copyright (c) 2000, 2001, 2003-2005, 2007-2020 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -39,6 +39,7 @@ #include #include +#include #include #if !TARGET_OS_SIMULATOR || (defined(IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED) && (IPHONE_SIMULATOR_HOST_MIN_VERSION_REQUIRED >= 1090)) @@ -46,172 +47,133 @@ #endif -/* information maintained for each active session */ -static serverSessionRef *sessions = NULL; -static int nSessions = 0; /* # of allocated sessions */ -static int lastSession = -1; /* # of last used session */ +/* information maintained for the main listener */ +static serverSessionRef server_session = NULL; -/* CFMachPortInvalidation runloop */ -static CFRunLoopRef sessionRunLoop = NULL; +/* + * information maintained for each active session + * Note: sync w/sessionQueue() + */ +static CFMutableDictionaryRef client_sessions = NULL; +static CFIndex client_sessions_advise = 250; // when snapshot handler should detail sessions -__private_extern__ -serverSessionRef -getSession(mach_port_t server) +static dispatch_queue_t +sessionQueue(void) { - int i; + static dispatch_once_t once; + static dispatch_queue_t q; - if (server == MACH_PORT_NULL) { - SC_log(LOG_NOTICE, "Excuse me, why is getSession() being called with an invalid port?"); - return NULL; - } + dispatch_once(&once, ^{ + // allocate mapping between [client] session mach port and session info + client_sessions = CFDictionaryCreateMutable(NULL, + 0, + NULL, // use the actual mach_port_t as the key + &kCFTypeDictionaryValueCallBacks); + + // and a queue to synchronize access to the mapping + q = dispatch_queue_create("SCDynamicStore/sessions", NULL); + }); - /* look for matching session (note: slot 0 is the "server" port) */ - for (i = 1; i <= lastSession; i++) { - serverSessionRef thisSession = sessions[i]; + return q; +} - if (thisSession == NULL) { - /* found an empty slot, skip it */ - continue; - } - if (thisSession->key == server) { - /* we've seen this server before */ - return thisSession; - } +#pragma mark - +#pragma mark __serverSession object - if ((thisSession->store != NULL) && - (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) { - /* we've seen this task port before */ - return thisSession; - } - } +static CFStringRef __serverSessionCopyDescription (CFTypeRef cf); +static void __serverSessionDeallocate (CFTypeRef cf); - /* no sessions available */ - return NULL; -} +static const CFRuntimeClass __serverSessionClass = { + 0, // version + "serverSession", // className + NULL, // init + NULL, // copy + __serverSessionDeallocate, // dealloc + NULL, // equal + NULL, // hash + NULL, // copyFormattingDesc + __serverSessionCopyDescription // copyDebugDesc +}; +static CFTypeID __serverSessionTypeID = _kCFRuntimeNotATypeID; -__private_extern__ -serverSessionRef -tempSession(mach_port_t server, CFStringRef name, audit_token_t auditToken) + +static CFStringRef +__serverSessionCopyDescription(CFTypeRef cf) { - static dispatch_once_t once; - SCDynamicStorePrivateRef storePrivate; /* temp session */ - static serverSession temp_session; + CFAllocatorRef allocator = CFGetAllocator(cf); + CFMutableStringRef result; + serverSessionRef session = (serverSessionRef)cf; - dispatch_once(&once, ^{ - temp_session = *sessions[0]; /* use "server" session */ - temp_session.activity = NULL; - (void) __SCDynamicStoreOpen(&temp_session.store, NULL); - }); + result = CFStringCreateMutable(allocator, 0); + CFStringAppendFormat(result, NULL, CFSTR(" {"), cf, allocator); - if (temp_session.key != server) { - // if not SCDynamicStore "server" port - return NULL; - } + // add client port + CFStringAppendFormat(result, NULL, CFSTR("port = 0x%x (%d)"), session->key, session->key); - /* save audit token, caller entitlements */ - temp_session.auditToken = auditToken; - temp_session.callerEUID = 1; /* not "root" */ - temp_session.callerRootAccess = UNKNOWN; - if ((temp_session.callerWriteEntitlement != NULL) && - (temp_session.callerWriteEntitlement != kCFNull)) { - CFRelease(temp_session.callerWriteEntitlement); + // add session info + if (session->name != NULL) { + CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), session->name); } - temp_session.callerWriteEntitlement = kCFNull; /* UNKNOWN */ - /* save name */ - storePrivate = (SCDynamicStorePrivateRef)temp_session.store; - if (storePrivate->name != NULL) CFRelease(storePrivate->name); - storePrivate->name = CFRetain(name); - - return &temp_session; + CFStringAppendFormat(result, NULL, CFSTR("}")); + return result; } -__private_extern__ -serverSessionRef -addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info)) +static void +__serverSessionDeallocate(CFTypeRef cf) { - CFMachPortContext context = { 0, NULL, NULL, NULL, NULL }; - kern_return_t kr; - mach_port_t mp = server; - int n = -1; - serverSessionRef newSession = NULL; - - /* save current (SCDynamicStore) runloop */ - if (sessionRunLoop == NULL) { - sessionRunLoop = CFRunLoopGetCurrent(); - } - - if (nSessions <= 0) { - /* if first session (the "server" port) */ - n = 0; /* use slot "0" */ - lastSession = 0; /* last used slot */ +#pragma unused(cf) + serverSessionRef session = (serverSessionRef)cf; - nSessions = 64; - sessions = malloc(nSessions * sizeof(serverSessionRef)); + if (session->changedKeys != NULL) CFRelease(session->changedKeys); + if (session->name != NULL) CFRelease(session->name); + if (session->sessionKeys != NULL) CFRelease(session->sessionKeys); - // allocate a new session for "the" server - newSession = calloc(1, sizeof(serverSession)); - } else { - int i; -#ifdef HAVE_MACHPORT_GUARDS - mach_port_options_t opts; -#endif // HAVE_MACHPORT_GUARDS - - /* check to see if we already have an open session (note: slot 0 is the "server" port) */ - for (i = 1; i <= lastSession; i++) { - serverSessionRef thisSession = sessions[i]; - - if (thisSession == NULL) { - /* found an empty slot */ - if (n < 0) { - /* keep track of the first [empty] slot */ - n = i; - } - - /* and keep looking for a matching session */ - continue; - } + return; +} - if (thisSession->key == server) { - /* we've seen this server before */ - return NULL; - } - if ((thisSession->store != NULL) && - (((SCDynamicStorePrivateRef)thisSession->store)->notifySignalTask == server)) { - /* we've seen this task port before */ - return NULL; - } - } +static serverSessionRef +__serverSessionCreate(CFAllocatorRef allocator, mach_port_t server) +{ + static dispatch_once_t once; + serverSessionRef session; + uint32_t size; - /* add a new session */ - if (n < 0) { - /* if no empty slots */ - n = ++lastSession; - if (lastSession >= nSessions) { - /* expand the session list */ - nSessions *= 2; - sessions = reallocf(sessions, (nSessions * sizeof(serverSessionRef))); - } - } + // initialize runtime + dispatch_once(&once, ^{ + __serverSessionTypeID = _CFRuntimeRegisterClass(&__serverSessionClass); + }); - // allocate a session for this client - newSession = calloc(1, sizeof(serverSession)); + // allocate session + size = sizeof(serverSession) - sizeof(CFRuntimeBase); + session = (serverSessionRef)_CFRuntimeCreateInstance(allocator, + __serverSessionTypeID, + size, + NULL); + if (session == NULL) { + return NULL; + } - // create mach port for SCDynamicStore client - mp = MACH_PORT_NULL; + // if needed, allocate a mach port for SCDynamicStore client + if (server == MACH_PORT_NULL) { + kern_return_t kr; + mach_port_t mp = MACH_PORT_NULL; +#ifdef HAVE_MACHPORT_GUARDS + mach_port_options_t opts; +#endif // HAVE_MACHPORT_GUARDS retry_allocate : #ifdef HAVE_MACHPORT_GUARDS - bzero(&opts, sizeof(opts)); + memset(&opts, 0, sizeof(opts)); opts.flags = MPO_CONTEXT_AS_GUARD; - kr = mach_port_construct(mach_task_self(), &opts, (mach_port_context_t)newSession, &mp); + kr = mach_port_construct(mach_task_self(), &opts, (mach_port_context_t)session, &mp); #else // HAVE_MACHPORT_GUARDS kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp); #endif // HAVE_MACHPORT_GUARDS @@ -230,27 +192,10 @@ addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info)) NULL, NULL); if (err != NULL) free(err); - - free(newSession); + CFRelease(session); return NULL; } - } - // create server port - context.info = newSession; - context.copyDescription = copyDescription; - - // - // Note: we create the CFMachPort *before* we insert a send - // right present to ensure that CF does not establish - // its dead name notification. - // - newSession->serverPort = _SC_CFMachPortCreateWithPort("SCDynamicStore/session", - mp, - configdCallback, - &context); - - if (n > 0) { // insert send right that will be moved to the client kr = mach_port_insert_right(mach_task_self(), mp, @@ -262,194 +207,436 @@ addSession(mach_port_t server, CFStringRef (*copyDescription)(const void *info)) * only happen if someone stomped on OUR port (so let's leave * the port alone). */ - SC_log(LOG_NOTICE, "mach_port_insert_right() failed: %s", mach_error_string(kr)); - - free(newSession); + SC_log(LOG_ERR, "mach_port_insert_right() failed: %s", mach_error_string(kr)); + CFRelease(session); return NULL; } + + server = mp; } - newSession->activity = os_activity_create("processing SCDynamicStore notification", - OS_ACTIVITY_CURRENT, - OS_ACTIVITY_FLAG_DEFAULT); - newSession->callerEUID = 1; /* not "root" */ - newSession->callerRootAccess = UNKNOWN; - newSession->callerWriteEntitlement = kCFNull; /* UNKNOWN */ - newSession->key = mp; -// newSession->serverRunLoopSource = NULL; -// newSession->store = NULL; + session->callerEUID = 1; /* not "root" */ + session->callerRootAccess = UNKNOWN; + session->callerWriteEntitlement = kCFNull; /* UNKNOWN */ + session->key = server; +// session->store = NULL; + + return session; +} - sessions[n] = newSession; - return newSession; +#pragma mark - +#pragma mark SCDynamicStore state handler + + +static void +addSessionReference(const void *key, const void *value, void *context) +{ +#pragma unused(key) + CFMutableDictionaryRef dict = (CFMutableDictionaryRef)context; + serverSessionRef session = (serverSessionRef)value; + + if (session->name != NULL) { + int cnt; + CFNumberRef num; + + if (!CFDictionaryGetValueIfPresent(dict, + session->name, + (const void **)&num) || + !CFNumberGetValue(num, kCFNumberIntType, &cnt)) { + // if first session + cnt = 0; + } + cnt++; + num = CFNumberCreate(NULL, kCFNumberIntType, &cnt); + CFDictionarySetValue(dict, session->name, num); + CFRelease(num); + } + + return; } -__private_extern__ -void -cleanupSession(mach_port_t server) +static void +add_state_handler() { - int i; + os_state_block_t state_block; + + state_block = ^os_state_data_t(os_state_hints_t hints) { +#pragma unused(hints) + CFDataRef data = NULL; + CFIndex n; + Boolean ok; + os_state_data_t state_data; + size_t state_data_size; + CFIndex state_len; + + n = CFDictionaryGetCount(client_sessions); + if (n < client_sessions_advise) { + CFStringRef str; + + str = CFStringCreateWithFormat(NULL, NULL, CFSTR("n = %ld"), n); + ok = _SCSerialize(str, &data, NULL, NULL); + CFRelease(str); + } else { + CFMutableDictionaryRef dict; + + dict = CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFDictionaryApplyFunction(client_sessions, addSessionReference, dict); + ok = _SCSerialize(dict, &data, NULL, NULL); + CFRelease(dict); + } - for (i = 1; i <= lastSession; i++) { - CFStringRef sessionKey; - serverSessionRef thisSession = sessions[i]; + state_len = (ok && (data != NULL)) ? CFDataGetLength(data) : 0; + state_data_size = OS_STATE_DATA_SIZE_NEEDED(state_len); + if (state_data_size > MAX_STATEDUMP_SIZE) { + SC_log(LOG_ERR, "SCDynamicStore/sessions : state data too large (%zd > %zd)", + state_data_size, + (size_t)MAX_STATEDUMP_SIZE); + if (data != NULL) CFRelease(data); + return NULL; + } - if (thisSession == NULL) { - /* found an empty slot, skip it */ - continue; + state_data = calloc(1, state_data_size); + if (state_data == NULL) { + SC_log(LOG_ERR, "SCDynamicStore/sessions: could not allocate state data"); + if (data != NULL) CFRelease(data); + return NULL; } - if (thisSession->key == server) { - /* - * session entry still exists. - */ + state_data->osd_type = OS_STATE_DATA_SERIALIZED_NSCF_OBJECT; + state_data->osd_data_size = (uint32_t)state_len; + strlcpy(state_data->osd_title, "SCDynamicStore/sessions", sizeof(state_data->osd_title)); + if (state_len > 0) { + memcpy(state_data->osd_data, CFDataGetBytePtr(data), state_len); + } + if (data != NULL) CFRelease(data); - SC_trace("cleanup : %5d", server); + return state_data; + }; - /* - * Close any open connections including cancelling any outstanding - * notification requests and releasing any locks. - */ - __MACH_PORT_DEBUG(TRUE, "*** cleanupSession", server); - (void) __SCDynamicStoreClose(&thisSession->store); - __MACH_PORT_DEBUG(TRUE, "*** cleanupSession (after __SCDynamicStoreClose)", server); + (void) os_state_add_handler(sessionQueue(), state_block); + return; +} - /* - * Our send right has already been removed. Remove our receive right. - */ -#ifdef HAVE_MACHPORT_GUARDS - (void) mach_port_destruct(mach_task_self(), server, 0, (mach_port_context_t)thisSession); -#else // HAVE_MACHPORT_GUARDS - (void) mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_RECEIVE, -1); -#endif // HAVE_MACHPORT_GUARDS - /* - * release any entitlement info - */ - if ((thisSession->callerWriteEntitlement != NULL) && - (thisSession->callerWriteEntitlement != kCFNull)) { - CFRelease(thisSession->callerWriteEntitlement); - } +#pragma mark - +#pragma mark SCDynamicStore session management - /* - * release our per-session activity - */ - if (thisSession->activity != NULL) { - os_release(thisSession->activity); - } - /* - * We don't need any remaining information in the - * sessionData dictionary, remove it. - */ - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), server); - CFDictionaryRemoveValue(sessionData, sessionKey); - CFRelease(sessionKey); +__private_extern__ +serverSessionRef +getSession(mach_port_t server) +{ + __block serverSessionRef session; - /* - * get rid of the per-session structure. - */ - free(thisSession); - sessions[i] = NULL; - - if (i == lastSession) { - /* we are removing the last session, update last used slot */ - while (--lastSession > 0) { - if (sessions[lastSession] != NULL) { - break; - } - } - } + assert(server != MACH_PORT_NULL); + dispatch_sync(sessionQueue(), ^{ + session = (serverSessionRef)CFDictionaryGetValue(client_sessions, + (const void *)(uintptr_t)server); + }); - return; - } + return session; +} + + +__private_extern__ +serverSessionRef +getSessionNum(CFNumberRef serverNum) +{ + union { + mach_port_t mp; + uint64_t val; + } server; + serverSessionRef session; + + (void) CFNumberGetValue(serverNum, kCFNumberSInt64Type, &server.val); + session = getSession(server.mp); + + return session; +} + + +__private_extern__ +serverSessionRef +getSessionStr(CFStringRef serverKey) +{ + mach_port_t server; + serverSessionRef session; + char str[16]; + + (void) _SC_cfstring_to_cstring(serverKey, str, sizeof(str), kCFStringEncodingASCII); + server = atoi(str); + session = getSession(server); + + return session; +} + + +#if __has_feature(ptrauth_intrinsics) +extern const struct { char c; } objc_absolute_packed_isa_class_mask; +#endif + +static void +memcpy_objc_object(void* dst, const void* restrict src, size_t size) +{ + // first, we copy the object + memcpy(dst, src, size); + + // then, if needed, fix the isa pointer + #if __has_feature(ptrauth_intrinsics) + uintptr_t flags; + uintptr_t isa_mask; + void ** opaqueObject; + uintptr_t raw_isa; + uintptr_t real_isa; + + opaqueObject = (void**)src; + isa_mask = (uintptr_t)&objc_absolute_packed_isa_class_mask; + flags = (uintptr_t)(*opaqueObject) & ~isa_mask; + real_isa = (uintptr_t)(*opaqueObject) & isa_mask; + + #if __has_feature(ptrauth_objc_isa) + raw_isa = (uintptr_t)ptrauth_auth_data((void *)real_isa, + ptrauth_key_process_independent_data, + ptrauth_blend_discriminator(opaqueObject, 0x6AE1)); + #else // __has_feature(ptrauth_objc_isa) + raw_isa = (uintptr_t)ptrauth_strip((void*)real_isa, ptrauth_key_process_independent_data); + #endif // __has_feature(ptrauth_objc_isa) + ((CFRuntimeBase*)dst)->_cfisa = raw_isa; + ((uint64_t*)dst)[0] |= flags; + #endif // __has_feature(ptrauth_intrinsics) +} + + +__private_extern__ +serverSessionRef +tempSession(mach_port_t server, CFStringRef name, audit_token_t auditToken) +{ + static dispatch_once_t once; + SCDynamicStorePrivateRef storePrivate; /* temp session */ + static serverSession temp_session; + + dispatch_once(&once, ^{ + memcpy_objc_object(&temp_session, /* use "server" session clone */ + server_session, + sizeof(temp_session)); + (void) __SCDynamicStoreOpen(&temp_session.store, NULL); + }); + + if (temp_session.key != server) { + // if not SCDynamicStore "server" port + return NULL; } - SC_log(LOG_NOTICE, "MACH_NOTIFY_NO_SENDERS w/no session, port = %d", server); - __MACH_PORT_DEBUG(TRUE, "*** cleanupSession w/no session", server); - return; + /* save audit token, caller entitlements */ + temp_session.auditToken = auditToken; + temp_session.callerEUID = 1; /* not "root" */ + temp_session.callerRootAccess = UNKNOWN; + if ((temp_session.callerWriteEntitlement != NULL) && + (temp_session.callerWriteEntitlement != kCFNull)) { + CFRelease(temp_session.callerWriteEntitlement); + } + temp_session.callerWriteEntitlement = kCFNull; /* UNKNOWN */ + + /* save name */ + storePrivate = (SCDynamicStorePrivateRef)temp_session.store; + if (storePrivate->name != NULL) CFRelease(storePrivate->name); + storePrivate->name = CFRetain(name); + + return &temp_session; } __private_extern__ void -listSessions(FILE *f) +addSession(serverSessionRef session, Boolean isMain) { - int i; + session->serverChannel = dispatch_mach_create_f("configd/SCDynamicStore", + server_queue(), + (void *)session, + server_mach_channel_handler); + if (!isMain) { + // if not main SCDynamicStore port, watch for exit + dispatch_mach_notify_no_senders(session->serverChannel, FALSE); + } +#if TARGET_OS_SIMULATOR + // simulators don't support MiG QoS propagation yet + dispatch_set_qos_class_fallback(session->serverChannel, QOS_CLASS_USER_INITIATED); +#else + dispatch_set_qos_class_fallback(session->serverChannel, QOS_CLASS_BACKGROUND); +#endif + dispatch_mach_connect(session->serverChannel, session->key, MACH_PORT_NULL, NULL); + return; +} - SCPrint(TRUE, f, CFSTR("Current sessions :\n")); - for (i = 0; i <= lastSession; i++) { - serverSessionRef thisSession = sessions[i]; - if (thisSession == NULL) { - continue; - } +__private_extern__ +serverSessionRef +addClient(mach_port_t server, audit_token_t audit_token) +{ - SCPrint(TRUE, f, CFSTR("\t%d : port = 0x%x"), i, thisSession->key); + __block serverSessionRef newSession = NULL; - if (thisSession->store != NULL) { - SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)thisSession->store; + dispatch_sync(sessionQueue(), ^{ + Boolean ok; - if (storePrivate->notifySignalTask != TASK_NULL) { - SCPrint(TRUE, f, CFSTR(", task = %d"), storePrivate->notifySignalTask); - } + // check to see if we already have an open session + ok = CFDictionaryContainsKey(client_sessions, + (const void *)(uintptr_t)server); + if (ok) { + // if we've already added a session for this port + return; } - if (sessionData != NULL) { - CFDictionaryRef info; - CFStringRef key; + // allocate a new session for "the" server + newSession = __serverSessionCreate(NULL, MACH_PORT_NULL); + if (newSession != NULL) { + // and add a port --> session mapping + CFDictionarySetValue(client_sessions, + (const void *)(uintptr_t)newSession->key, + newSession); - key = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), thisSession->key); - info = CFDictionaryGetValue(sessionData, key); - CFRelease(key); - if (info != NULL) { - CFStringRef name; + // save the audit_token in case we need to check the callers credentials + newSession->auditToken = audit_token; - name = CFDictionaryGetValue(info, kSCDName); - if (name != NULL) { - SCPrint(TRUE, f, CFSTR(", name = %@"), name); - } - } + CFRelease(newSession); // reference held by dictionary } + }); - if (thisSession->serverPort != NULL) { - SCPrint(TRUE, f, CFSTR("\n\t\t%@"), thisSession->serverPort); - } + if (newSession != NULL) { + addSession(newSession, FALSE); + } - if (thisSession->serverRunLoopSource != NULL) { - SCPrint(TRUE, f, CFSTR("\n\t\t%@"), thisSession->serverRunLoopSource); - } + return newSession; +} - SCPrint(TRUE, f, CFSTR("\n")); + +__private_extern__ +serverSessionRef +addServer(mach_port_t server) +{ + // allocate a session for "the" server + server_session = __serverSessionCreate(NULL, server); + addSession(server_session, TRUE); + + // add a state dump handler + add_state_handler(); + + return server_session; +} + + +__private_extern__ +void +cleanupSession(serverSessionRef session) +{ + mach_port_t server = session->key; + + SC_trace("cleanup : %5d", server); + + /* + * Close any open connections including cancelling any outstanding + * notification requests and releasing any locks. + */ + __MACH_PORT_DEBUG(TRUE, "*** cleanupSession", server); + (void) __SCDynamicStoreClose(&session->store); + __MACH_PORT_DEBUG(TRUE, "*** cleanupSession (after __SCDynamicStoreClose)", server); + + /* + * Our send right has already been removed. Remove our receive right. + */ +#ifdef HAVE_MACHPORT_GUARDS + (void) mach_port_destruct(mach_task_self(), server, 0, (mach_port_context_t)session); +#else // HAVE_MACHPORT_GUARDS + (void) mach_port_mod_refs(mach_task_self(), server, MACH_PORT_RIGHT_RECEIVE, -1); +#endif // HAVE_MACHPORT_GUARDS + + /* + * release any entitlement info + */ + if ((session->callerWriteEntitlement != NULL) && + (session->callerWriteEntitlement != kCFNull)) { + CFRelease(session->callerWriteEntitlement); + } + + /* + * get rid of the per-session structure. + */ + dispatch_sync(sessionQueue(), ^{ + CFDictionaryRemoveValue(client_sessions, + (const void *)(uintptr_t)server); + }); + + return; +} + + +__private_extern__ +void +closeSession(serverSessionRef session) +{ + /* + * cancel and release the mach channel + */ + if (session->serverChannel != NULL) { + dispatch_mach_cancel(session->serverChannel); + dispatch_release(session->serverChannel); + session->serverChannel = NULL; } - SCPrint(TRUE, f, CFSTR("\n")); return; } -#include -#include +typedef struct ReportSessionInfo { + FILE *f; + int n; +} ReportSessionInfo, *ReportSessionInfoRef; -static CFStringRef -sessionName(serverSessionRef session) +static void +printOne(const void *key, const void *value, void *context) { - CFDictionaryRef info; - CFStringRef name = NULL; - CFStringRef sessionKey; +#pragma unused(key) + ReportSessionInfoRef reportInfo = (ReportSessionInfoRef)context; + serverSessionRef session = (serverSessionRef)value; + + SCPrint(TRUE, reportInfo->f, CFSTR(" %d : port = 0x%x"), ++reportInfo->n, session->key); + SCPrint(TRUE, reportInfo->f, CFSTR(", name = %@"), session->name); + if (session->changedKeys != NULL) { + SCPrint(TRUE, reportInfo->f, CFSTR("\n changedKeys = %@"), session->changedKeys); + } + if (session->sessionKeys != NULL) { + SCPrint(TRUE, reportInfo->f, CFSTR("\n sessionKeys = %@"), session->sessionKeys); + } + SCPrint(TRUE, reportInfo->f, CFSTR("\n")); + return; +} - sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), session->key); - info = CFDictionaryGetValue(sessionData, sessionKey); - CFRelease(sessionKey); - if (info != NULL) { - name = CFDictionaryGetValue(info, kSCDName); - } +__private_extern__ +void +listSessions(FILE *f) +{ + dispatch_sync(sessionQueue(), ^{ + ReportSessionInfo reportInfo = { .f = f, .n = 0 }; - return (name != NULL) ? name : CFSTR("???"); + SCPrint(TRUE, f, CFSTR("Current sessions :\n")); + CFDictionaryApplyFunction(client_sessions, + printOne, + (void *)&reportInfo); + SCPrint(TRUE, f, CFSTR("\n")); + }); + return; } + +#include +#include + static CFTypeRef copyEntitlement(serverSessionRef session, CFStringRef entitlement) { @@ -473,7 +660,7 @@ copyEntitlement(serverSessionRef session, CFStringRef entitlement) SC_log(LOG_NOTICE, "SecTaskCopyValueForEntitlement(,\"%@\",) failed, error = %@ : %@", entitlement, error, - sessionName(session)); + session->name); } CFRelease(error); } @@ -481,7 +668,7 @@ copyEntitlement(serverSessionRef session, CFStringRef entitlement) CFRelease(task); } else { SC_log(LOG_NOTICE, "SecTaskCreateWithAuditToken() failed: %@", - sessionName(session)); + session->name); } return value; @@ -595,7 +782,7 @@ hasWriteAccess(serverSessionRef session, const char *op, CFStringRef key) sessionPid(session), key); - //return FALSE; // return FALSE when rdar://9811832 has beed fixed + return FALSE; } if (session->callerWriteEntitlement == kCFNull) {