check for disconnected parent objects before linking into them
authorKay Sievers <kay@vrfy.org>
Sat, 22 Mar 2014 18:03:02 +0000 (19:03 +0100)
committerKay Sievers <kay@vrfy.org>
Sat, 22 Mar 2014 18:57:22 +0000 (19:57 +0100)
bus.c
connection.c
domain.c
endpoint.c

diff --git a/bus.c b/bus.c
index 1b5b0471eefb7366ba8c29b5b8e3ec06adfa508e..8d8b2cf9d8e76b668873a863b30cc7afaef6ff5b 100644 (file)
--- a/bus.c
+++ b/bus.c
@@ -274,6 +274,11 @@ int kdbus_bus_new(struct kdbus_domain *domain,
 
        /* 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);
index 045f8c85417015cebecfbafacc5810dce70044d8..3233730dbfe638e398a48085e0682e716ab1ac54 100644 (file)
@@ -521,7 +521,7 @@ static int kdbus_conn_queue_alloc(struct kdbus_conn *conn,
 
        /* allocate the needed space in the pool of the receiver */
        mutex_lock(&conn->lock);
-       if (conn->disconnected) {
+       if (!kdbus_conn_active(conn)) {
                ret = -ECONNRESET;
                goto exit_unlock;
        }
@@ -726,7 +726,7 @@ static void kdbus_conn_work(struct work_struct *work)
        conn = container_of(work, struct kdbus_conn, work.work);
 
        mutex_lock(&conn->lock);
-       if (unlikely(conn->disconnected)) {
+       if (!kdbus_conn_active(conn)) {
                mutex_unlock(&conn->lock);
                return;
        }
@@ -1487,7 +1487,7 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
        LIST_HEAD(reply_list);
 
        mutex_lock(&conn->lock);
-       if (conn->disconnected) {
+       if (!kdbus_conn_active(conn)) {
                mutex_unlock(&conn->lock);
                return -EALREADY;
        }
@@ -1502,16 +1502,14 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
 
        cancel_delayed_work_sync(&conn->work);
 
-       /* remove from bus */
+       /* remove from bus and endpoint */
        mutex_lock(&conn->bus->lock);
+       mutex_lock(&conn->ep->lock);
        hash_del(&conn->hentry);
        list_del(&conn->monitor_entry);
-       mutex_unlock(&conn->bus->lock);
-
-       /* remove from endpoint */
-       mutex_lock(&conn->ep->lock);
        list_del(&conn->ep_entry);
        mutex_unlock(&conn->ep->lock);
+       mutex_unlock(&conn->bus->lock);
 
        /* if we die while other connections wait for our reply, notify them */
        mutex_lock(&conn->lock);
@@ -2113,14 +2111,18 @@ int kdbus_conn_new(struct kdbus_ep *ep,
                goto exit_unref_user;
        }
 
-       /* link into endpoint */
+       /* link into bus and endpoint */
+       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;
+       }
        list_add_tail(&conn->ep_entry, &ep->conn_list);
-       mutex_unlock(&ep->lock);
-
-       /* link into bus */
-       mutex_lock(&bus->lock);
        hash_add(bus->conn_hash, &conn->hentry, conn->id);
+       mutex_unlock(&ep->lock);
        mutex_unlock(&bus->lock);
 
        *c = conn;
index 2e05e9074f21036ba48b835a8f69993663e8e7ca..d79db6f1debb9d16b9e8559c2a85ebde1f43daf3 100644 (file)
--- a/domain.c
+++ b/domain.c
@@ -256,8 +256,14 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
        atomic64_set(&d->msg_seq_last, 0);
        idr_init(&d->user_idr);
 
-       if (parent)
+       if (parent) {
                mutex_lock(&parent->lock);
+               if (parent->disconnected) {
+                       mutex_unlock(&parent->lock);
+                       return -ESHUTDOWN;
+               }
+       }
+
        mutex_lock(&kdbus_subsys_lock);
 
        /* compose name and path of base directory in /dev */
@@ -437,6 +443,11 @@ struct kdbus_domain_user
 
        /* link into domain */
        mutex_lock(&domain->lock);
+       if (domain->disconnected) {
+               mutex_unlock(&domain->lock);
+               kfree(u);
+               return NULL;
+       }
 
        /*
         * Allocate the smallest possible index for this user; used
index a6d9dfbd617f39536bbbfd07835e3da73f7736cc..7642bcd2e9f4dad580abe805c8afa3027aba249a 100644 (file)
@@ -231,6 +231,11 @@ int kdbus_ep_new(struct kdbus_bus *bus, const char *name,
 
        /* link into bus  */
        mutex_lock(&bus->lock);
+       if (bus->disconnected) {
+               mutex_unlock(&bus->lock);
+               ret = -ESHUTDOWN;
+               goto exit_dev_unregister;
+       }
        e->id = ++bus->ep_seq_last;
        e->bus = kdbus_bus_ref(bus);
        list_add_tail(&e->bus_entry, &bus->ep_list);