bus, connection: do not leak user accounting when parents are disconnected
authorKay Sievers <kay@vrfy.org>
Mon, 24 Mar 2014 13:02:03 +0000 (14:02 +0100)
committerKay Sievers <kay@vrfy.org>
Mon, 24 Mar 2014 13:02:03 +0000 (14:02 +0100)
bus.c
connection.c

diff --git a/bus.c b/bus.c
index e82b45f54d6d2ac9dc82daae1ef4e6c82ae95ba4..bce1a8b5bb32ddc60cee5e0b471471eb46014961 100644 (file)
--- a/bus.c
+++ b/bus.c
@@ -270,20 +270,20 @@ int kdbus_bus_new(struct kdbus_domain *domain,
                goto exit_ep_unref;
        }
 
+       /* link into domain */
+       mutex_lock(&domain->lock);
+       if (domain->disconnected) {
+               ret = -ESHUTDOWN;
+               goto exit_unlock;
+       }
+
        if (!capable(CAP_IPC_OWNER) &&
            atomic_inc_return(&b->user->buses) > KDBUS_USER_MAX_BUSES) {
                atomic_dec(&b->user->buses);
                ret = -EMFILE;
-               goto exit_user_unref;
+               goto exit_unlock;
        }
 
-       /* link into domain */
-       mutex_lock(&domain->lock);
-       if (domain->disconnected) {
-               mutex_unlock(&domain->lock);
-               ret = -ESHUTDOWN;
-               goto exit_user_unref;
-       }
        b->id = ++domain->bus_seq_last;
        list_add_tail(&b->domain_entry, &domain->bus_list);
        mutex_unlock(&domain->lock);
@@ -291,6 +291,8 @@ int kdbus_bus_new(struct kdbus_domain *domain,
        *bus = b;
        return 0;
 
+exit_unlock:
+       mutex_unlock(&domain->lock);
 exit_user_unref:
        kdbus_domain_user_unref(b->user);
 exit_ep_unref:
index f97847c6770f215f5d77e68f5ec254143753bf77..3687a437325f487d69a84f24a1f2ccbdad256c7b 100644 (file)
@@ -2123,22 +2123,20 @@ int kdbus_conn_new(struct kdbus_ep *ep,
                goto exit_free_meta;
        }
 
-       if (!capable(CAP_IPC_OWNER) &&
-           atomic_inc_return(&conn->user->connections) > KDBUS_USER_MAX_CONN) {
-               atomic_dec(&conn->user->connections);
-               ret = -EMFILE;
-               goto exit_unref_user;
-       }
-
        /* lock order: domain -> bus -> ep -> names -> conn */
        mutex_lock(&bus->lock);
        mutex_lock(&ep->lock);
 
        if (bus->disconnected || ep->disconnected) {
-               mutex_unlock(&ep->lock);
-               mutex_unlock(&bus->lock);
                ret = -ESHUTDOWN;
-               goto exit_unref_user;
+               goto exit_unlock;
+       }
+
+       if (!capable(CAP_IPC_OWNER) &&
+           atomic_inc_return(&conn->user->connections) > KDBUS_USER_MAX_CONN) {
+               atomic_dec(&conn->user->connections);
+               ret = -EMFILE;
+               goto exit_unlock;
        }
 
        /* link into bus and endpoint */
@@ -2151,6 +2149,9 @@ int kdbus_conn_new(struct kdbus_ep *ep,
        *c = conn;
        return 0;
 
+exit_unlock:
+       mutex_unlock(&ep->lock);
+       mutex_unlock(&bus->lock);
 exit_unref_user:
        kdbus_domain_user_unref(conn->user);
 exit_free_meta: