[krbdev.mit.edu #6322] Leak in CCacheServer

Zhanna Tsitkova via RT rt-comment at krbdev.mit.edu
Mon Jan 12 09:49:26 EST 2009


diff -ru Kerberos.orig/KerberosFramework/Kerberos5/Sources/util/mac/k5_mig_server.c Kerberos/KerberosFramework/Kerberos5/Sources/util/mac/k5_mig_server.c
--- Kerberos.orig/KerberosFramework/Kerberos5/Sources/util/mac/k5_mig_server.c	2008-12-18 21:34:46.000000000 -0800
+++ Kerberos/KerberosFramework/Kerberos5/Sources/util/mac/k5_mig_server.c	2008-12-19 00:31:02.000000000 -0800
@@ -37,6 +37,11 @@
 #include <launch.h>
 #include <string.h>
 
+/* Map of receive rights to libdispatch sources. */
+static CFMutableDictionaryRef mig_clients = NULL;
+__unused static int _assert_mach_port_can_be_used_as_cfdictionary_key_
+	[sizeof(mach_port_t) <= sizeof(void *) ? 0 : -1];
+
 /* ------------------------------------------------------------------------ */
 
 static boolean_t k5_ipc_request_demux (mach_msg_header_t *request, 
@@ -55,12 +60,11 @@
         err = k5_ipc_server_remove_client (request->msgh_local_port);
         
         if (!err) {
-            err = mach_port_mod_refs (mach_task_self (), 
-                                      request->msgh_local_port, 
-                                      MACH_PORT_RIGHT_RECEIVE, -1);
-        }
-        
-        if (!err) {
+            void *key = (void *)((uintptr_t)request->msgh_local_port);
+            dispatch_source_t source = (dispatch_source_t)CFDictionaryGetValue
+                                        (mig_clients, key);
+            CFDictionaryRemoveValue (mig_clients, key);
+            dispatch_release (source);
             handled = 1;  /* was a port we are tracking */
         }
     }
@@ -76,6 +80,8 @@
     kern_return_t err = KERN_SUCCESS;
     mach_port_t connection_port = MACH_PORT_NULL;
     mach_port_t old_notification_target = MACH_PORT_NULL;
+    dispatch_source_attr_t attr = NULL;
+    dispatch_source_t source = NULL;
     
     if (!err) {
         err = mach_port_allocate (mach_task_self (), 
@@ -97,18 +103,44 @@
     }
     
     if (!err) {
+	attr = dispatch_source_attr_create ();
+	if (attr == NULL) {
+	    err = KERN_FAILURE;
+	}
+    }
+
+    if (!err) {
+	dispatch_source_finalizer_t finalizer;
+	finalizer = ^(dispatch_source_t s){
+	    mach_port_mod_refs (mach_task_self (), connection_port, 
+	                        MACH_PORT_RIGHT_RECEIVE, -1);
+	};
+	if (dispatch_source_attr_set_finalizer (attr, finalizer)) {
+	    err = KERN_FAILURE;
+	}
+    }
+
+    if (!err) {
 	dispatch_queue_t queue;
-	queue = dispatch_get_main_queue();
-	dispatch_source_mig_create(connection_port, K5_IPC_MAX_MSG_SIZE, 
-				   NULL, queue, k5_ipc_request_demux);
+	queue = dispatch_get_main_queue ();
+	source = dispatch_source_mig_create (connection_port,
+	                                     K5_IPC_MAX_MSG_SIZE, attr, queue,
+	                                     k5_ipc_request_demux);
+	if (source == NULL) {
+	    err = KERN_FAILURE;
+	}
     }
 
     if (!err) {
+        CFDictionaryAddValue (mig_clients,
+                              (void *)((uintptr_t)connection_port), source);
         *out_connection_port = connection_port;
         connection_port = MACH_PORT_NULL;
     }
     
     if (MACH_PORT_VALID (connection_port)) { mach_port_deallocate (mach_task_self (), connection_port); }
+
+    if (attr != NULL) { dispatch_release (attr); }
     
     return err;    
 }
@@ -223,11 +255,14 @@
   
     if (launch_data_get_type(obj) == LAUNCH_DATA_MACHPORT) {
         mach_port_t port = launch_data_get_machport(obj);
-	dispatch_source_mig_create(port,
-				   K5_IPC_MAX_MSG_SIZE,
-				   NULL,
-				   dispatch_get_main_queue(),
-				   k5_ipc_request_demux);
+	source = dispatch_source_mig_create(port,
+					    K5_IPC_MAX_MSG_SIZE,
+					    NULL,
+					    dispatch_get_main_queue(),
+					    k5_ipc_request_demux);
+	if (source == NULL) {
+	    syslog(LOG_NOTICE, "Failed to register Mach source.");
+	}
     } else {
         syslog(LOG_NOTICE, "%s: not a mach port", key);
     }
@@ -254,6 +289,13 @@
 	syslog(LOG_NOTICE, "launch_msg() response: %s", strerror(errno));
 	return 1;
     }
+
+    mig_clients = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
+
+    if (mig_clients == NULL) {
+	syslog(LOG_NOTICE, "Failed to create client dictionary.");
+	return 1;
+    }
     
     tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_MACHSERVICES);
     




More information about the krb5-bugs mailing list