The coroipcc_dispatch_put coroipcc routine would fail to retrieve a
handle and then wouldn't properly put the reference counts of a handle
that was pending removal. This resulted in an invalid reference count
on the coroipcc data structure which would never drop to zero and leave
the process mmapped into the shared memory leaking shared memory when
finalize was called inside a dispatch routine.
Patch attached to fix.
Regards
-steve
Index: include/corosync/hdb.h
===================================================================
--- include/corosync/hdb.h (revision 2393)
+++ include/corosync/hdb.h (working copy)
@@ -260,6 +260,49 @@
return (0);
}
+static inline int hdb_handle_get_always (
+ struct hdb_handle_database *handle_database,
+ hdb_handle_t handle_in,
+ void **instance)
+{
+ unsigned int check = ((unsigned int)(((unsigned long long)handle_in) >> 32));
+ unsigned int handle = handle_in & 0xffffffff;
+
+ if (handle_database->first_run == 1) {
+ handle_database->first_run = 0;
+ hdb_database_lock_init (&handle_database->lock);
+ }
+ hdb_database_lock (&handle_database->lock);
+
+ *instance = NULL;
+ if (handle >= handle_database->handle_count) {
+ hdb_database_unlock (&handle_database->lock);
+ errno = EBADF;
+ return (-1);
+ }
+
+ if (handle_database->handles[handle].state == HDB_HANDLE_STATE_EMPTY) {
+ hdb_database_unlock (&handle_database->lock);
+ errno = EBADF;
+ return (-1);
+ }
+
+ if (check != 0xffffffff &&
+ check != handle_database->handles[handle].check) {
+
+ hdb_database_unlock (&handle_database->lock);
+ errno = EBADF;
+ return (-1);
+ }
+
+ *instance = handle_database->handles[handle].instance;
+
+ handle_database->handles[handle].ref_count += 1;
+
+ hdb_database_unlock (&handle_database->lock);
+ return (0);
+}
+
static inline int hdb_handle_put (
struct hdb_handle_database *handle_database,
hdb_handle_t handle_in)
Index: lib/coroipcc.c
===================================================================
--- lib/coroipcc.c (revision 2393)
+++ lib/coroipcc.c (working copy)
@@ -890,7 +890,7 @@
char *addr;
unsigned int read_idx;
- res = hdb_error_to_cs (hdb_handle_get (&ipc_hdb, handle, (void **)&ipc_instance));
+ res = hdb_error_to_cs (hdb_handle_get_always (&ipc_hdb, handle, (void **)&ipc_instance));
if (res != CS_OK) {
return (res);
}
@@ -907,14 +907,16 @@
retry_semop:
res = semop (ipc_instance->semid, &sop, 1);
if (res == -1 && errno == EINTR) {
- return (CS_ERR_TRY_AGAIN);
+ res = CS_ERR_TRY_AGAIN;
+ goto error_exit;
} else
if (res == -1 && errno == EACCES) {
priv_change_send (ipc_instance);
goto retry_semop;
} else
if (res == -1) {
- return (CS_ERR_LIBRARY);
+ res = CS_ERR_LIBRARY;
+ goto error_exit;
}
#endif
@@ -927,10 +929,13 @@
/*
* Put from dispatch get and also from this call's get
*/
+ res = CS_OK;
+
+error_exit:
hdb_handle_put (&ipc_hdb, handle);
hdb_handle_put (&ipc_hdb, handle);
- return (CS_OK);
+ return (res);
}
cs_error_t
_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais