[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