prevent special-purpose connections from owning names or exchanging messages
authorKay Sievers <kay@vrfy.org>
Mon, 4 Aug 2014 14:05:39 +0000 (16:05 +0200)
committerKay Sievers <kay@vrfy.org>
Mon, 4 Aug 2014 14:05:39 +0000 (16:05 +0200)
connection.c
connection.h
handle.c
names.c

index d8c3bc087bda2fa02476ed9f62842a49a44cfd72..71bb66af5339421b14d74fb017b42af0f5463e32 100644 (file)
@@ -1304,8 +1304,7 @@ int kdbus_conn_kmsg_send(struct kdbus_ep *ep,
                 * Special-purpose connections are not allowed to be addressed
                 * via their unique IDs.
                 */
-               if (conn_dst->flags & (KDBUS_HELLO_ACTIVATOR |
-                                      KDBUS_HELLO_MONITOR)) {
+               if (conn_dst->type != KDBUS_CONN_CONNECTED) {
                        ret = -ENXIO;
                        goto exit_unref;
                }
@@ -1464,7 +1463,7 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
                return -EBUSY;
        }
 
-       conn->disconnected = true;
+       conn->type = KDBUS_CONN_DISCONNECTED;
        mutex_unlock(&conn->lock);
 
        cancel_delayed_work_sync(&conn->work);
@@ -1542,7 +1541,7 @@ int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
  */
 bool kdbus_conn_active(const struct kdbus_conn *conn)
 {
-       return !conn->disconnected;
+       return conn->type != KDBUS_CONN_DISCONNECTED;
 }
 
 static void __kdbus_conn_free(struct kref *kref)
@@ -1991,6 +1990,15 @@ int kdbus_conn_new(struct kdbus_ep *ep,
                }
        }
 
+       if (is_activator)
+               conn->type = KDBUS_CONN_ACTIVATOR;
+       else if (is_policy_holder)
+               conn->type = KDBUS_CONN_POLICY_HOLDER;
+       else if (is_monitor)
+               conn->type = KDBUS_CONN_MONITOR;
+       else
+               conn->type = KDBUS_CONN_CONNECTED;
+
        kref_init(&conn->kref);
        mutex_init(&conn->lock);
        INIT_LIST_HEAD(&conn->msg_list);
index 46f7b6ea0be982e0c3795b6b21cb0dcf3c3c9cad..7b61b1a0ed96507f6e25a703bb5e6f2ed0274c7b 100644 (file)
 #include "metadata.h"
 #include "pool.h"
 
+/**
+ * enum kdbus_conn_type - type and state of connection
+ * @KDBUS_CONN_DISCONNECTED:   Invalidated connection
+ * @KDBUS_CONN_CONNECTED:      Ordinary connection that exchanges messages
+ * @KDBUS_CONN_ACTIVATOR:      Activator connection for a well-known name
+ * @KDBUS_CONN_POLICY_HOLDER:  Policy holding connection
+ * @KDBUS_CONN_MONITOR:                Bus monitor connection
+ */
+enum kdbus_conn_type {
+       KDBUS_CONN_DISCONNECTED,
+       KDBUS_CONN_CONNECTED,
+       KDBUS_CONN_ACTIVATOR,
+       KDBUS_CONN_POLICY_HOLDER,
+       KDBUS_CONN_MONITOR,
+};
+
 /**
  * struct kdbus_conn - connection to a bus
  * @kref:              Reference count
@@ -64,7 +80,7 @@ struct kdbus_conn {
        u64 id;
        u64 flags;
        u64 attach_flags;
-       bool disconnected;
+       unsigned int type;
        const char *name;
        struct kdbus_bus *bus;
        struct kdbus_ep *ep;
index 8d821d4f21997fa7b46d9ec4c42721448635ed42..4b8376cf499f5d10c9ddf8edb60b963db87001af 100644 (file)
--- a/handle.c
+++ b/handle.c
@@ -536,12 +536,22 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
 
        switch (cmd) {
        case KDBUS_CMD_BYEBYE:
+               if (conn->type != KDBUS_CONN_CONNECTED) {
+                       ret = -EPERM;
+                       break;
+               }
+
                ret = kdbus_conn_disconnect(conn, true);
                break;
 
        case KDBUS_CMD_NAME_ACQUIRE:
                /* acquire a well-known name */
 
+               if (conn->type != KDBUS_CONN_CONNECTED) {
+                       ret = -EPERM;
+                       break;
+               }
+
                ret = kdbus_memdup_user(buf, &p, &size,
                                        sizeof(struct kdbus_cmd_name),
                                        sizeof(struct kdbus_cmd_name) +
@@ -562,6 +572,11 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
        case KDBUS_CMD_NAME_RELEASE:
                /* release a well-known name */
 
+               if (conn->type != KDBUS_CONN_CONNECTED) {
+                       ret = -EPERM;
+                       break;
+               }
+
                ret = kdbus_memdup_user(buf, &p, NULL,
                                        sizeof(struct kdbus_cmd_name),
                                        sizeof(struct kdbus_cmd_name) +
@@ -621,6 +636,12 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
 
        case KDBUS_CMD_CONN_UPDATE:
                /* update the properties of a connection */
+
+               if (conn->type != KDBUS_CONN_CONNECTED) {
+                       ret = -EPERM;
+                       break;
+               }
+
                ret = kdbus_memdup_user(buf, &p, NULL,
                                        sizeof(struct kdbus_cmd_update),
                                        sizeof(struct kdbus_cmd_update) +
@@ -633,6 +654,13 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
 
        case KDBUS_CMD_MATCH_ADD:
                /* subscribe to/filter for broadcast messages */
+
+               if (conn->type != KDBUS_CONN_CONNECTED &&
+                   conn->type != KDBUS_CONN_MONITOR) {
+                       ret = -EPERM;
+                       break;
+               }
+
                ret = kdbus_memdup_user(buf, &p, NULL,
                                        sizeof(struct kdbus_cmd_match),
                                        sizeof(struct kdbus_cmd_match) +
@@ -645,6 +673,13 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
 
        case KDBUS_CMD_MATCH_REMOVE:
                /* unsubscribe from broadcast messages */
+
+               if (conn->type != KDBUS_CONN_CONNECTED &&
+                   conn->type != KDBUS_CONN_MONITOR) {
+                       ret = -EPERM;
+                       break;
+               }
+
                ret = kdbus_memdup_user(buf, &p, NULL,
                                        sizeof(struct kdbus_cmd_match),
                                        sizeof(struct kdbus_cmd_match));
@@ -658,7 +693,7 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
                /* submit a message which will be queued in the receiver */
                struct kdbus_kmsg *kmsg = NULL;
 
-               if (handle->conn->flags & KDBUS_HELLO_ACTIVATOR) {
+               if (conn->type != KDBUS_CONN_CONNECTED) {
                        ret = -EPERM;
                        break;
                }
@@ -690,6 +725,12 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
        case KDBUS_CMD_MSG_RECV: {
                struct kdbus_cmd_recv cmd;
 
+               if (conn->type != KDBUS_CONN_CONNECTED &&
+                   conn->type != KDBUS_CONN_MONITOR) {
+                       ret = -EPERM;
+                       break;
+               }
+
                if (!KDBUS_IS_ALIGNED8((uintptr_t)buf))
                        return -EFAULT;
 
@@ -712,6 +753,11 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
        case KDBUS_CMD_MSG_CANCEL: {
                u64 cookie;
 
+               if (conn->type != KDBUS_CONN_CONNECTED) {
+                       ret = -EPERM;
+                       break;
+               }
+
                if (!KDBUS_IS_ALIGNED8((uintptr_t)buf))
                        return -EFAULT;
 
@@ -727,6 +773,12 @@ static long kdbus_handle_ioctl_ep_connected(struct file *file, unsigned int cmd,
                u64 off;
                struct kdbus_pool_slice *slice;
 
+               if (conn->type != KDBUS_CONN_CONNECTED &&
+                   conn->type != KDBUS_CONN_MONITOR) {
+                       ret = -EPERM;
+                       break;
+               }
+
                if (!KDBUS_IS_ALIGNED8((uintptr_t)buf))
                        return -EFAULT;
 
diff --git a/names.c b/names.c
index f5ba37d4eb2b5791bdc5a5617119229f9bf96fad..aeedd6f79638c105fcfabf92f43e1db45ee602fb 100644 (file)
--- a/names.c
+++ b/names.c
@@ -632,10 +632,6 @@ int kdbus_cmd_name_acquire(struct kdbus_name_registry *reg,
        u64 allowed;
        int ret = 0;
 
-       /* monitor connection may not own names */
-       if (conn->flags & KDBUS_HELLO_MONITOR)
-               return -EPERM;
-
        if (conn->name_count > KDBUS_CONN_MAX_NAMES)
                return -E2BIG;