]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_utilities/lib/machserver.cpp
Security-59306.140.5.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / machserver.cpp
index 82434ef2b4cd8e51ed187be454d7b054ce118998..4fca0b64d9d4ed5563ddc03729646459fe0d7e35 100644 (file)
@@ -30,7 +30,7 @@
 #include <mach/kern_return.h>
 #include <mach/message.h>
 #include <mach/mig_errors.h>
-#include "mach_notify.h"
+#include "mach_notifyServer.h"
 #include <security_utilities/debugging.h>
 #include <malloc/malloc.h>
 
@@ -40,6 +40,8 @@
 # include <sys/time.h>
 #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<MachServer, &MachServer::busy, &MachServer::idle> _(*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<Allocation> &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<Allocation> &releaseSet = perThread().deferredAllocations;
        for (set<Allocation>::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<MachServer::Timer,
                        &MachServer::Timer::select, &MachServer::Timer::unselect> _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) { }