X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..0d4552ce43ff8bf2e8666a9c5c44c3590eb117a8:/OSX/libsecurity_utilities/lib/machserver.cpp?ds=sidebyside diff --git a/OSX/libsecurity_utilities/lib/machserver.cpp b/OSX/libsecurity_utilities/lib/machserver.cpp index 82434ef2..4fca0b64 100644 --- a/OSX/libsecurity_utilities/lib/machserver.cpp +++ b/OSX/libsecurity_utilities/lib/machserver.cpp @@ -30,7 +30,7 @@ #include #include #include -#include "mach_notify.h" +#include "mach_notifyServer.h" #include #include @@ -40,6 +40,8 @@ # include #endif +#define SEC_MACH_AUDIT_TOKEN_PID (5) + namespace Security { namespace MachPlusPlus { @@ -89,13 +91,13 @@ MachServer::~MachServer() // void MachServer::add(Port receiver) { - SECURITY_MACHSERVER_PORT_ADD(receiver); + secinfo("machserver", "port add: %d", receiver.port()); mPortSet += receiver; } void MachServer::remove(Port receiver) { - SECURITY_MACHSERVER_PORT_REMOVE(receiver); + secinfo("machserver", "port remove: %d", receiver.port()); mPortSet -= receiver; } @@ -143,9 +145,9 @@ void MachServer::run(mach_msg_size_t maxSize, mach_msg_options_t options) highestWorkerCount = 1; // run server loop in initial (immortal) thread - SECURITY_MACHSERVER_START_THREAD(false); + secinfo("machserver", "start thread"); runServerThread(false); - SECURITY_MACHSERVER_END_THREAD(false); + secinfo("machserver", "end thread"); // primary server thread exited somehow (not currently possible) assert(false); @@ -192,7 +194,7 @@ void MachServer::runServerThread(bool doTimeout) Time::Absolute rightNow = Time::now(); if (rightNow >= nextCheckTime) { // reaping period complete; process UInt32 idlers = leastIdleWorkers; - SECURITY_MACHSERVER_REAP(workerCount, idlers); + secinfo("machserver", "reaping workers: %d %d", (uint32_t) workerCount, (uint32_t) idlers); nextCheckTime = rightNow + workerTimeout; leastIdleWorkers = INT_MAX; if (idlers > 1) // multiple idle threads throughout measuring interval... @@ -213,9 +215,7 @@ void MachServer::runServerThread(bool doTimeout) timeout = workerTimeout; } } - if (SECURITY_MACHSERVER_RECEIVE_ENABLED()) - SECURITY_MACHSERVER_RECEIVE(indefinite ? 0 : timeout.seconds()); - + // receive next IPC request (or wait for timeout) mach_msg_return_t mr = indefinite ? mach_msg_overwrite(bufRequest, @@ -235,20 +235,28 @@ void MachServer::runServerThread(bool doTimeout) // process received request message below break; default: - SECURITY_MACHSERVER_RECEIVE_ERROR(mr); + secinfo("machserver", "received error: %d", mr); continue; } + // reset the buffer each time, handlers don't consistently set out params + bufReply.clearBuffer(); + // process received message if (bufRequest.msgId() >= MACH_NOTIFY_FIRST && bufRequest.msgId() <= MACH_NOTIFY_LAST) { // mach kernel notification message // we assume this is quick, so no thread arbitration here + mach_msg_audit_trailer_t *tlr = bufRequest.auditTrailer(); + if (tlr == NULL || tlr->msgh_audit.val[SEC_MACH_AUDIT_TOKEN_PID] != 0) { + secnotice("machserver", "ignoring invalid notify message"); + continue; + } cdsa_notify_server(bufRequest, bufReply); } else { // normal request message StLock _(*this); - SECURITY_MACHSERVER_BEGIN(bufRequest.localPort(), bufRequest.msgId()); + secinfo("machserver", "begin request: %d, %d", bufRequest.localPort().port(), bufRequest.msgId()); // try subsidiary handlers first bool handled = false; @@ -263,7 +271,7 @@ void MachServer::runServerThread(bool doTimeout) handle(bufRequest, bufReply); } - SECURITY_MACHSERVER_END(); + secinfo("machserver", "end request"); } // process reply generated by handler @@ -292,21 +300,25 @@ void MachServer::runServerThread(bool doTimeout) * To avoid falling off the kernel's fast RPC path unnecessarily, * we only supply MACH_SEND_TIMEOUT when absolutely necessary. */ - mr = mach_msg_overwrite(bufReply, + mr = mach_msg_overwrite(bufReply, (MACH_MSGH_BITS_REMOTE(bufReply.bits()) == MACH_MSG_TYPE_MOVE_SEND_ONCE) ? MACH_SEND_MSG | mMsgOptions : MACH_SEND_MSG | MACH_SEND_TIMEOUT | mMsgOptions, bufReply.length(), 0, MACH_PORT_NULL, 0, MACH_PORT_NULL, NULL, 0); - switch (mr) { - case MACH_MSG_SUCCESS: - break; - default: - SECURITY_MACHSERVER_SEND_ERROR(mr, bufReply.remotePort()); - bufReply.destroy(); - break; - } + switch (mr) { + case MACH_MSG_SUCCESS: + break; + case MACH_SEND_INVALID_DEST: + case MACH_SEND_TIMED_OUT: + secinfo("machserver", "send error: %d %d", mr, bufReply.remotePort().port()); + bufReply.destroy(); + break; + default: + secinfo("machserver", "send error: %d %d", mr, bufReply.remotePort().port()); + break; + } // clean up after the transaction @@ -371,7 +383,7 @@ void MachServer::releaseWhenDone(Allocator &alloc, void *memory) if (memory) { set &releaseSet = perThread().deferredAllocations; assert(releaseSet.find(Allocation(memory, alloc)) == releaseSet.end()); - SECURITY_MACHSERVER_ALLOC_REGISTER(memory, &alloc); + secinfo("machserver", "allocing register %p with alloc %p", memory, &alloc); releaseSet.insert(Allocation(memory, alloc)); } } @@ -388,8 +400,8 @@ void MachServer::releaseDeferredAllocations() { set &releaseSet = perThread().deferredAllocations; for (set::iterator it = releaseSet.begin(); it != releaseSet.end(); it++) { - SECURITY_MACHSERVER_ALLOC_RELEASE(it->addr, it->allocator); - + secinfo("machserver", "releasing alloc at %p with %p", it->addr, it->allocator); + // before we release the deferred allocation, zap it so that secrets aren't left in memory size_t memSize = malloc_size(it->addr); bzero(it->addr, memSize); @@ -464,12 +476,12 @@ void MachServer::LoadThread::action() // register the worker thread and go server.addThread(this); try { - SECURITY_MACHSERVER_START_THREAD(true); + secinfo("machserver", "start thread"); server.runServerThread(true); - SECURITY_MACHSERVER_END_THREAD(false); + secinfo("machserver", "end thread"); } catch (...) { // fell out of server loop by error. Let the thread go quietly - SECURITY_MACHSERVER_END_THREAD(true); + secinfo("machserver", "end thread (due to error)"); } server.removeThread(this); } @@ -515,7 +527,7 @@ bool MachServer::processTimer() return false; // nothing (more) to be done now } // drop lock; work has been retrieved try { - SECURITY_MACHSERVER_TIMER_START(top, top->longTerm(), Time::now().internalForm()); + secinfo("machserver", "timer start: %p, %d, %f", top, top->longTerm(), Time::now().internalForm()); StLock _t(*top); if (top->longTerm()) { @@ -524,9 +536,9 @@ bool MachServer::processTimer() } else { top->action(); } - SECURITY_MACHSERVER_TIMER_END(false); + secinfo("machserver", "timer end (false)"); } catch (...) { - SECURITY_MACHSERVER_TIMER_END(true); + secinfo("machserver", "timer end (true)"); } return true; } @@ -548,52 +560,60 @@ void MachServer::clearTimer(Timer *timer) // // Notification hooks and shims. Defaults do nothing. // -void cdsa_mach_notify_dead_name(mach_port_t, mach_port_name_t port) +kern_return_t cdsa_mach_notify_dead_name(mach_port_t, mach_port_name_t port) { try { MachServer::active().notifyDeadName(port); } catch (...) { } + // the act of receiving a dead name notification allocates a dead-name + // right that must be deallocated + mach_port_deallocate(mach_task_self(), port); + return KERN_SUCCESS; } void MachServer::notifyDeadName(Port) { } -void cdsa_mach_notify_port_deleted(mach_port_t, mach_port_name_t port) +kern_return_t cdsa_mach_notify_port_deleted(mach_port_t, mach_port_name_t port) { try { MachServer::active().notifyPortDeleted(port); } catch (...) { } + return KERN_SUCCESS; } void MachServer::notifyPortDeleted(Port) { } -void cdsa_mach_notify_port_destroyed(mach_port_t, mach_port_name_t port) +kern_return_t cdsa_mach_notify_port_destroyed(mach_port_t, mach_port_name_t port) { try { MachServer::active().notifyPortDestroyed(port); } catch (...) { } + return KERN_SUCCESS; } void MachServer::notifyPortDestroyed(Port) { } -void cdsa_mach_notify_send_once(mach_port_t port) +kern_return_t cdsa_mach_notify_send_once(mach_port_t port) { try { MachServer::active().notifySendOnce(port); } catch (...) { } + return KERN_SUCCESS; } void MachServer::notifySendOnce(Port) { } -void cdsa_mach_notify_no_senders(mach_port_t port, mach_port_mscount_t count) +kern_return_t cdsa_mach_notify_no_senders(mach_port_t port, mach_port_mscount_t count) { try { MachServer::active().notifyNoSenders(port, count); } catch (...) { } + return KERN_SUCCESS; } void MachServer::notifyNoSenders(Port, mach_port_mscount_t) { }