Bugs:
- replace memfd ioctls with shmem memfd_create() + fcntl() logic
- - disconnect connections with kdbus_ep_disconnect(), remove
- ep->disconnected checks
Features:
- test kdbus_match_bloom() multi-generation bloom masks, we need to
kdbus_ep_unref(ep);
}
-
- /* disconnect all connections to this bus */
- for (;;) {
- struct kdbus_conn *conn = NULL, *c;
- unsigned int i;
-
- mutex_lock(&bus->lock);
- hash_for_each(bus->conn_hash, i, c, hentry) {
- conn = c;
- break;
- }
- if (!conn) {
- mutex_unlock(&bus->lock);
- break;
- }
-
- kdbus_conn_ref(conn);
- mutex_unlock(&bus->lock);
-
- kdbus_conn_disconnect(conn, false);
- kdbus_conn_unref(conn);
- }
-
/* drop reference for our "bus" endpoint after we disconnected */
bus->ep = kdbus_ep_unref(bus->ep);
}
int ret = 0;
mutex_lock(&conn->lock);
- if (unlikely(conn->ep->disconnected)) {
- ret = -ECONNRESET;
- goto exit_unlock;
- }
-
if (conn->msg_count == 0) {
ret = -EAGAIN;
goto exit_unlock;
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);
+
/* if we die while other connections wait for our reply, notify them */
mutex_lock(&conn->lock);
list_for_each_entry_safe(queue, tmp, &conn->msg_list, entry) {
goto exit_unref_user;
}
+ /* link into endpoint */
+ mutex_lock(&ep->lock);
+ 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);
* individual user
* @msg_users_max: Size of the users array
* @hentry: Entry in ID <-> connection map
+ * @ep_entry: The enpoint this connection belongs to
* @monitor_entry: The connection is a monitor
* @names_list: List of well-known names
* @names_queue_list: Well-known names this connection waits for
unsigned int *msg_users;
unsigned int msg_users_max;
struct hlist_node hentry;
+ struct list_head ep_entry;
struct list_head monitor_entry;
struct list_head names_list;
struct list_head names_queue_list;
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include "connection.h"
#include "bus.h"
#include "endpoint.h"
#include "domain.h"
ep->disconnected = true;
mutex_unlock(&ep->lock);
+ /* disconnect all connections to this endpoint */
+ for (;;) {
+ struct kdbus_conn *conn;
+
+ mutex_lock(&ep->lock);
+ conn = list_first_entry_or_null(&ep->conn_list,
+ struct kdbus_conn,
+ ep_entry);
+ if (!conn) {
+ mutex_unlock(&ep->lock);
+ break;
+ }
+
+ kdbus_conn_ref(conn);
+ mutex_unlock(&ep->lock);
+
+ kdbus_conn_disconnect(conn, false);
+ kdbus_conn_unref(conn);
+ }
+
/* disconnect from bus */
mutex_lock(&ep->bus->lock);
list_del(&ep->bus_entry);
mutex_init(&e->lock);
kref_init(&e->kref);
+ INIT_LIST_HEAD(&e->conn_list);
e->uid = uid;
e->gid = gid;
e->mode = mode;
* @mode: File mode of this endpoint device node
* @uid: UID owning this endpoint
* @gid: GID owning this endpoint
+ * @conn_list: Connections of this endpoint
* @bus_entry: bus' endpoints
* @lock: Endpoint data lock
* @user: Custom enpoints account against an anonymous user
umode_t mode;
kuid_t uid;
kgid_t gid;
+ struct list_head conn_list;
struct list_head bus_entry;
struct mutex lock;
struct kdbus_domain_user *user;
struct poll_table_struct *wait)
{
struct kdbus_handle *handle = file->private_data;
- struct kdbus_conn *conn;
+ struct kdbus_conn *conn = handle->conn;
unsigned int mask = 0;
/* Only a connected endpoint can read/write data */
if (handle->type != KDBUS_HANDLE_EP_CONNECTED)
return POLLERR | POLLHUP;
- conn = handle->conn;
-
poll_wait(file, &conn->wait, wait);
mutex_lock(&conn->lock);
-
if (unlikely(conn->disconnected))
mask |= POLLERR | POLLHUP;
else if (!list_empty(&conn->msg_list))
mask |= POLLIN | POLLRDNORM;
-
mutex_unlock(&conn->lock);
return mask;