From: Kay Sievers Date: Mon, 4 Aug 2014 14:05:39 +0000 (+0200) Subject: prevent special-purpose connections from owning names or exchanging messages X-Git-Tag: upstream/0.20140911.160207utc~65 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7015a1e6746e0c238a723f132623819c2215bce1;p=platform%2Fcore%2Fsystem%2Fkdbus-bus.git prevent special-purpose connections from owning names or exchanging messages --- diff --git a/connection.c b/connection.c index d8c3bc0..71bb66a 100644 --- a/connection.c +++ b/connection.c @@ -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); diff --git a/connection.h b/connection.h index 46f7b6e..7b61b1a 100644 --- a/connection.h +++ b/connection.h @@ -18,6 +18,22 @@ #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; diff --git a/handle.c b/handle.c index 8d821d4..4b8376c 100644 --- 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 f5ba37d..aeedd6f 100644 --- 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;