X-Git-Url: https://git.saurik.com/apple/securityd.git/blobdiff_plain/569135f537d6bd5118fa29c2fb4b6d4d436e066e..4cd1cad0dea00daa03e1b54fdf2797a02373ad5b:/src/server.cpp diff --git a/src/server.cpp b/src/server.cpp index 4b6f8d8..0177679 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -65,15 +65,12 @@ Server::Server(Authority &authority, CodeSignatures &signatures, const char *boo mCSPModule(gGuidAppleCSP, mCssm), mCSP(mCSPModule), mAuthority(authority), mCodeSignatures(signatures), - mAudit(geteuid(), getpid()), mVerbosity(0), mWaitForClients(true), mShuttingDown(false) { // make me eternal (in the object mesh) ref(); - mAudit.registerSession(); - // engage the subsidiary port handler for sleep notifications add(sleepWatcher); } @@ -99,6 +96,7 @@ Connection &Server::connection(mach_port_t port, audit_token_t &auditToken) Server &server = active(); StLock _(server); Connection *conn = server.mConnections.get(port, CSSM_ERRCODE_INVALID_CONTEXT_HANDLE); + conn->process().checkSession(auditToken); active().mCurrentConnection() = conn; conn->beginWork(auditToken); return *conn; @@ -221,27 +219,27 @@ boolean_t Server::handle(mach_msg_header_t *in, mach_msg_header_t *out) // Everything at and below that level is constructed. This is straight-forward except // in the case of session re-initialization (see below). // -void Server::setupConnection(ConnectLevel type, Port servicePort, Port replyPort, Port taskPort, - const audit_token_t &auditToken, const ClientSetupInfo *info, const char *identity) +void Server::setupConnection(ConnectLevel type, Port replyPort, Port taskPort, + const audit_token_t &auditToken, const ClientSetupInfo *info) { + AuditToken audit(auditToken); + // first, make or find the process based on task port StLock _(*this); RefPointer &proc = mProcesses[taskPort]; - if (type == connectNewSession && proc) { - // The client has talked to us before and now wants to create a new session. - proc->changeSession(servicePort); - } + if (proc && proc->session().sessionId() != audit.sessionId()) + proc->changeSession(audit.sessionId()); if (proc && type == connectNewProcess) { // the client has amnesia - reset it - assert(info && identity); - proc->reset(servicePort, taskPort, info, identity, AuditToken(auditToken)); - proc->changeSession(servicePort); + assert(info); + proc->reset(taskPort, info, audit); + proc->changeSession(audit.sessionId()); } if (!proc) { if (type == connectNewThread) // client error (or attack) CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - assert(info && identity); - proc = new Process(servicePort, taskPort, info, identity, AuditToken(auditToken)); + assert(info); + proc = new Process(taskPort, info, audit); notifyIfDead(taskPort); mPids[proc->pid()] = proc; } @@ -277,15 +275,21 @@ void Server::endConnection(Port replyPort) // void Server::notifyDeadName(Port port) { - StLock _(*this); + // We need the lock to get a proper iterator on mConnections or mProcesses, + // but must release it before we call abort or kill, as these might take + // unbounded time, including calls out to token daemons etc. + + StLock serverLock(*this); secdebug("SSports", "port %d is dead", port.port()); // is it a connection? PortMap::iterator conIt = mConnections.find(port); if (conIt != mConnections.end()) { SECURITYD_PORTS_DEAD_CONNECTION(port); - conIt->second->abort(); + RefPointer con = conIt->second; mConnections.erase(conIt); + serverLock.unlock(); + con->abort(); return; } @@ -293,10 +297,14 @@ void Server::notifyDeadName(Port port) PortMap::iterator procIt = mProcesses.find(port); if (procIt != mProcesses.end()) { SECURITYD_PORTS_DEAD_PROCESS(port); - Process *proc = procIt->second; - proc->kill(); + RefPointer proc = procIt->second; mPids.erase(proc->pid()); mProcesses.erase(procIt); + serverLock.unlock(); + // The kill may take some time; make sure there is a spare thread around + // to prevent deadlocks + StLock _(*this); + proc->kill(); return; } @@ -313,8 +321,6 @@ void Server::notifyDeadName(Port port) void Server::notifyNoSenders(Port port, mach_port_mscount_t) { SECURITYD_PORTS_DEAD_SESSION(port); - secdebug("SSports", "port %d no senders", port.port()); - Session::destroy(port); } @@ -371,6 +377,24 @@ kern_return_t self_server_handleSignal(mach_port_t sport, } +kern_return_t self_server_handleSession(mach_port_t sport, + mach_port_t taskPort, uint32_t event, uint64_t ident) +{ + try { + if (taskPort != mach_task_self()) { + Syslog::error("handleSession: received from someone other than myself"); + return KERN_SUCCESS; + } + if (event == AUE_SESSION_CLOSE) + Session::destroy(ident); + } catch(...) { + secdebug("SS", "exception handling a signal (ignored)"); + } + mach_port_deallocate(mach_task_self(), taskPort); + return KERN_SUCCESS; +} + + // // Notifier for system sleep events //