From: "Mike Pagano" <mpagano@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/linux-patches:4.1 commit in: /
Date: Wed, 12 Aug 2015 14:17:42 +0000 (UTC) [thread overview]
Message-ID: <1439389049.bf5ec0ef3757347790f7c0269c3a657e2d1fdd2b.mpagano@gentoo> (raw)
commit: bf5ec0ef3757347790f7c0269c3a657e2d1fdd2b
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Aug 12 14:17:29 2015 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Aug 12 14:17:29 2015 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=bf5ec0ef
kdbus patch update 8-12-2015
0000_README | 2 +-
...s-7-22-2015.patch => 5015_kdbus-8-12-2015.patch | 1265 ++++++++++++--------
2 files changed, 757 insertions(+), 510 deletions(-)
diff --git a/0000_README b/0000_README
index 148063b..fd7a57d 100644
--- a/0000_README
+++ b/0000_README
@@ -115,6 +115,6 @@ Patch: 5010_enable-additional-cpu-optimizations-for-gcc-4.9.patch
From: https://github.com/graysky2/kernel_gcc_patch/
Desc: Kernel patch enables gcc >= v4.9 optimizations for additional CPUs.
-Patch: 5015_kdbus-7-22-15.patch
+Patch: 5015_kdbus-8-12-2015.patch
From: https://lkml.org
Desc: Kernel-level IPC implementation
diff --git a/5015_kdbus-7-22-2015.patch b/5015_kdbus-8-12-2015.patch
similarity index 97%
rename from 5015_kdbus-7-22-2015.patch
rename to 5015_kdbus-8-12-2015.patch
index b110b5c..4e018f2 100644
--- a/5015_kdbus-7-22-2015.patch
+++ b/5015_kdbus-8-12-2015.patch
@@ -7482,10 +7482,10 @@ index 1a0006a..4842a98 100644
header-y += kernelcapi.h
diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h
new file mode 100644
-index 0000000..ecffc6b
+index 0000000..4fc44cb
--- /dev/null
+++ b/include/uapi/linux/kdbus.h
-@@ -0,0 +1,980 @@
+@@ -0,0 +1,984 @@
+/*
+ * kdbus is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
@@ -8342,6 +8342,8 @@ index 0000000..ecffc6b
+ * @KDBUS_NAME_QUEUE: Name should be queued if busy
+ * @KDBUS_NAME_IN_QUEUE: Name is queued
+ * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection
++ * @KDBUS_NAME_PRIMARY: Primary owner of the name
++ * @KDBUS_NAME_ACQUIRED: Name was acquired/queued _now_
+ */
+enum kdbus_name_flags {
+ KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0,
@@ -8349,6 +8351,8 @@ index 0000000..ecffc6b
+ KDBUS_NAME_QUEUE = 1ULL << 2,
+ KDBUS_NAME_IN_QUEUE = 1ULL << 3,
+ KDBUS_NAME_ACTIVATOR = 1ULL << 4,
++ KDBUS_NAME_PRIMARY = 1ULL << 5,
++ KDBUS_NAME_ACQUIRED = 1ULL << 6,
+};
+
+/**
@@ -9072,10 +9076,10 @@ index 0000000..a67f825
+}
diff --git a/ipc/kdbus/bus.h b/ipc/kdbus/bus.h
new file mode 100644
-index 0000000..238986e
+index 0000000..8c2acae
--- /dev/null
+++ b/ipc/kdbus/bus.h
-@@ -0,0 +1,99 @@
+@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -9122,6 +9126,7 @@ index 0000000..238986e
+ * @domain: Domain of this bus
+ * @creator: Creator of the bus
+ * @creator_meta: Meta information about the bus creator
++ * @last_message_id: Last used message id
+ * @policy_db: Policy database for this bus
+ * @name_registry: Name registry of this bus
+ * @conn_rwlock: Read/Write lock for all lists of child connections
@@ -9145,6 +9150,7 @@ index 0000000..238986e
+ struct kdbus_meta_proc *creator_meta;
+
+ /* protected by own locks */
++ atomic64_t last_message_id;
+ struct kdbus_policy_db policy_db;
+ struct kdbus_name_registry *name_registry;
+
@@ -9177,10 +9183,10 @@ index 0000000..238986e
+#endif
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
new file mode 100644
-index 0000000..d94b417e
+index 0000000..ef63d65
--- /dev/null
+++ b/ipc/kdbus/connection.c
-@@ -0,0 +1,2207 @@
+@@ -0,0 +1,2227 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -9235,7 +9241,8 @@ index 0000000..d94b417e
+#define KDBUS_CONN_ACTIVE_BIAS (INT_MIN + 2)
+#define KDBUS_CONN_ACTIVE_NEW (INT_MIN + 1)
+
-+static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep, bool privileged,
++static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
++ struct file *file,
+ struct kdbus_cmd_hello *hello,
+ const char *name,
+ const struct kdbus_creds *creds,
@@ -9255,6 +9262,8 @@ index 0000000..d94b417e
+ bool is_policy_holder;
+ bool is_activator;
+ bool is_monitor;
++ bool privileged;
++ bool owner;
+ struct kvec kvec;
+ int ret;
+
@@ -9264,6 +9273,9 @@ index 0000000..d94b417e
+ struct kdbus_bloom_parameter bloom;
+ } bloom_item;
+
++ privileged = kdbus_ep_is_privileged(ep, file);
++ owner = kdbus_ep_is_owner(ep, file);
++
+ is_monitor = hello->flags & KDBUS_HELLO_MONITOR;
+ is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR;
+ is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER;
@@ -9280,9 +9292,9 @@ index 0000000..d94b417e
+ return ERR_PTR(-EINVAL);
+ if (is_monitor && ep->user)
+ return ERR_PTR(-EOPNOTSUPP);
-+ if (!privileged && (is_activator || is_policy_holder || is_monitor))
++ if (!owner && (is_activator || is_policy_holder || is_monitor))
+ return ERR_PTR(-EPERM);
-+ if ((creds || pids || seclabel) && !privileged)
++ if (!owner && (creds || pids || seclabel))
+ return ERR_PTR(-EPERM);
+
+ ret = kdbus_sanitize_attach_flags(hello->attach_flags_send,
@@ -9306,18 +9318,17 @@ index 0000000..d94b417e
+#endif
+ mutex_init(&conn->lock);
+ INIT_LIST_HEAD(&conn->names_list);
-+ INIT_LIST_HEAD(&conn->names_queue_list);
+ INIT_LIST_HEAD(&conn->reply_list);
-+ atomic_set(&conn->name_count, 0);
+ atomic_set(&conn->request_count, 0);
+ atomic_set(&conn->lost_count, 0);
+ INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work);
-+ conn->cred = get_current_cred();
++ conn->cred = get_cred(file->f_cred);
+ conn->pid = get_pid(task_pid(current));
+ get_fs_root(current->fs, &conn->root_path);
+ init_waitqueue_head(&conn->wait);
+ kdbus_queue_init(&conn->queue);
+ conn->privileged = privileged;
++ conn->owner = owner;
+ conn->ep = kdbus_ep_ref(ep);
+ conn->id = atomic64_inc_return(&bus->domain->last_id);
+ conn->flags = hello->flags;
@@ -9397,11 +9408,21 @@ index 0000000..d94b417e
+ * Note that limits are always accounted against the real UID, not
+ * the effective UID (cred->user always points to the accounting of
+ * cred->uid, not cred->euid).
++ * In case the caller is privileged, we allow changing the accounting
++ * to the faked user.
+ */
+ if (ep->user) {
+ conn->user = kdbus_user_ref(ep->user);
+ } else {
-+ conn->user = kdbus_user_lookup(ep->bus->domain, current_uid());
++ kuid_t uid;
++
++ if (conn->meta_fake && uid_valid(conn->meta_fake->uid) &&
++ conn->privileged)
++ uid = conn->meta_fake->uid;
++ else
++ uid = conn->cred->uid;
++
++ conn->user = kdbus_user_lookup(ep->bus->domain, uid);
+ if (IS_ERR(conn->user)) {
+ ret = PTR_ERR(conn->user);
+ conn->user = NULL;
@@ -9450,7 +9471,6 @@ index 0000000..d94b417e
+ WARN_ON(delayed_work_pending(&conn->work));
+ WARN_ON(!list_empty(&conn->queue.msg_list));
+ WARN_ON(!list_empty(&conn->names_list));
-+ WARN_ON(!list_empty(&conn->names_queue_list));
+ WARN_ON(!list_empty(&conn->reply_list));
+
+ if (conn->user) {
@@ -9784,12 +9804,13 @@ index 0000000..d94b417e
+ */
+bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name)
+{
-+ struct kdbus_name_entry *e;
++ struct kdbus_name_owner *owner;
+
+ lockdep_assert_held(&conn->ep->bus->name_registry->rwlock);
+
-+ list_for_each_entry(e, &conn->names_list, conn_entry)
-+ if (strcmp(e->name, name) == 0)
++ list_for_each_entry(owner, &conn->names_list, conn_entry)
++ if (!(owner->flags & KDBUS_NAME_IN_QUEUE) &&
++ !strcmp(name, owner->name->name))
+ return true;
+
+ return false;
@@ -10218,6 +10239,7 @@ index 0000000..d94b417e
+ struct kdbus_conn **out_dst)
+{
+ const struct kdbus_msg *msg = staging->msg;
++ struct kdbus_name_owner *owner = NULL;
+ struct kdbus_name_entry *name = NULL;
+ struct kdbus_conn *dst = NULL;
+ int ret;
@@ -10236,7 +10258,9 @@ index 0000000..d94b417e
+ } else {
+ name = kdbus_name_lookup_unlocked(bus->name_registry,
+ staging->dst_name);
-+ if (!name)
++ if (name)
++ owner = kdbus_name_get_owner(name);
++ if (!owner)
+ return -ESRCH;
+
+ /*
@@ -10248,19 +10272,14 @@ index 0000000..d94b417e
+ * owns the given name.
+ */
+ if (msg->dst_id != KDBUS_DST_ID_NAME &&
-+ msg->dst_id != name->conn->id)
++ msg->dst_id != owner->conn->id)
+ return -EREMCHG;
+
-+ if (!name->conn && name->activator)
-+ dst = kdbus_conn_ref(name->activator);
-+ else
-+ dst = kdbus_conn_ref(name->conn);
-+
+ if ((msg->flags & KDBUS_MSG_NO_AUTO_START) &&
-+ kdbus_conn_is_activator(dst)) {
-+ ret = -EADDRNOTAVAIL;
-+ goto error;
-+ }
++ kdbus_conn_is_activator(owner->conn))
++ return -EADDRNOTAVAIL;
++
++ dst = kdbus_conn_ref(owner->conn);
+ }
+
+ *out_name = name;
@@ -10306,7 +10325,7 @@ index 0000000..d94b417e
+ mutex_unlock(&dst->lock);
+
+ if (!reply) {
-+ ret = -EPERM;
++ ret = -EBADSLT;
+ goto exit;
+ }
+
@@ -10549,7 +10568,7 @@ index 0000000..d94b417e
+ struct kdbus_conn *whom,
+ unsigned int access)
+{
-+ struct kdbus_name_entry *ne;
++ struct kdbus_name_owner *owner;
+ bool pass = false;
+ int res;
+
@@ -10558,10 +10577,14 @@ index 0000000..d94b417e
+ down_read(&db->entries_rwlock);
+ mutex_lock(&whom->lock);
+
-+ list_for_each_entry(ne, &whom->names_list, conn_entry) {
-+ res = kdbus_policy_query_unlocked(db, conn_creds ? : conn->cred,
-+ ne->name,
-+ kdbus_strhash(ne->name));
++ list_for_each_entry(owner, &whom->names_list, conn_entry) {
++ if (owner->flags & KDBUS_NAME_IN_QUEUE)
++ continue;
++
++ res = kdbus_policy_query_unlocked(db,
++ conn_creds ? : conn->cred,
++ owner->name->name,
++ kdbus_strhash(owner->name->name));
+ if (res >= (int)access) {
+ pass = true;
+ break;
@@ -10601,7 +10624,7 @@ index 0000000..d94b417e
+ return false;
+ }
+
-+ if (conn->privileged)
++ if (conn->owner)
+ return true;
+
+ res = kdbus_policy_query(&conn->ep->bus->policy_db, conn_creds,
@@ -10631,7 +10654,7 @@ index 0000000..d94b417e
+ to, KDBUS_POLICY_TALK))
+ return false;
+
-+ if (conn->privileged)
++ if (conn->owner)
+ return true;
+ if (uid_eq(conn_creds->euid, to->cred->uid))
+ return true;
@@ -10750,12 +10773,12 @@ index 0000000..d94b417e
+/**
+ * kdbus_cmd_hello() - handle KDBUS_CMD_HELLO
+ * @ep: Endpoint to operate on
-+ * @privileged: Whether the caller is privileged
++ * @file: File this connection is opened on
+ * @argp: Command payload
+ *
+ * Return: NULL or newly created connection on success, ERR_PTR on failure.
+ */
-+struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged,
++struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
+ void __user *argp)
+{
+ struct kdbus_cmd_hello *cmd;
@@ -10790,7 +10813,7 @@ index 0000000..d94b417e
+
+ item_name = argv[1].item ? argv[1].item->str : NULL;
+
-+ c = kdbus_conn_new(ep, privileged, cmd, item_name,
++ c = kdbus_conn_new(ep, file, cmd, item_name,
+ argv[2].item ? &argv[2].item->creds : NULL,
+ argv[3].item ? &argv[3].item->pids : NULL,
+ argv[4].item ? argv[4].item->str : NULL,
@@ -10879,6 +10902,7 @@ index 0000000..d94b417e
+ struct kdbus_meta_conn *conn_meta = NULL;
+ struct kdbus_pool_slice *slice = NULL;
+ struct kdbus_name_entry *entry = NULL;
++ struct kdbus_name_owner *owner = NULL;
+ struct kdbus_conn *owner_conn = NULL;
+ struct kdbus_item *meta_items = NULL;
+ struct kdbus_info info = {};
@@ -10915,15 +10939,17 @@ index 0000000..d94b417e
+
+ if (name) {
+ entry = kdbus_name_lookup_unlocked(bus->name_registry, name);
-+ if (!entry || !entry->conn ||
++ if (entry)
++ owner = kdbus_name_get_owner(entry);
++ if (!owner ||
+ !kdbus_conn_policy_see_name(conn, current_cred(), name) ||
-+ (cmd->id != 0 && entry->conn->id != cmd->id)) {
++ (cmd->id != 0 && owner->conn->id != cmd->id)) {
+ /* pretend a name doesn't exist if you cannot see it */
+ ret = -ESRCH;
+ goto exit;
+ }
+
-+ owner_conn = kdbus_conn_ref(entry->conn);
++ owner_conn = kdbus_conn_ref(owner->conn);
+ } else if (cmd->id > 0) {
+ owner_conn = kdbus_bus_find_conn_by_id(bus, cmd->id);
+ if (!owner_conn || !kdbus_conn_policy_see(conn, current_cred(),
@@ -11390,10 +11416,10 @@ index 0000000..d94b417e
+}
diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h
new file mode 100644
-index 0000000..5ee864e
+index 0000000..1ad0820
--- /dev/null
+++ b/ipc/kdbus/connection.h
-@@ -0,0 +1,261 @@
+@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -11426,6 +11452,7 @@ index 0000000..5ee864e
+ KDBUS_HELLO_POLICY_HOLDER | \
+ KDBUS_HELLO_MONITOR)
+
++struct kdbus_name_entry;
+struct kdbus_quota;
+struct kdbus_staging;
+
@@ -11457,7 +11484,6 @@ index 0000000..5ee864e
+ * @cred: The credentials of the connection at creation time
+ * @pid: Pid at creation time
+ * @root_path: Root path at creation time
-+ * @name_count: Number of owned well-known names
+ * @request_count: Number of pending requests issued by this
+ * connection that are waiting for replies from
+ * other peers
@@ -11466,10 +11492,10 @@ index 0000000..5ee864e
+ * @queue: The message queue associated with this connection
+ * @quota: Array of per-user quota indexed by user->id
+ * @n_quota: Number of elements in quota array
-+ * @activator_of: Well-known name entry this connection acts as an
+ * @names_list: List of well-known names
-+ * @names_queue_list: Well-known names this connection waits for
-+ * @privileged: Whether this connection is privileged on the bus
++ * @name_count: Number of owned well-known names
++ * @privileged: Whether this connection is privileged on the domain
++ * @owner: Owned by the same user as the bus owner
+ */
+struct kdbus_conn {
+ struct kref kref;
@@ -11497,7 +11523,6 @@ index 0000000..5ee864e
+ const struct cred *cred;
+ struct pid *pid;
+ struct path root_path;
-+ atomic_t name_count;
+ atomic_t request_count;
+ atomic_t lost_count;
+ wait_queue_head_t wait;
@@ -11507,11 +11532,11 @@ index 0000000..5ee864e
+ unsigned int n_quota;
+
+ /* protected by registry->rwlock */
-+ struct kdbus_name_entry *activator_of;
+ struct list_head names_list;
-+ struct list_head names_queue_list;
++ unsigned int name_count;
+
+ bool privileged:1;
++ bool owner:1;
+};
+
+struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn);
@@ -11550,7 +11575,7 @@ index 0000000..5ee864e
+ const struct kdbus_msg *msg);
+
+/* command dispatcher */
-+struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged,
++struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
+ void __user *argp);
+int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp);
+int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp);
@@ -12042,10 +12067,10 @@ index 0000000..447a2bd
+#endif
diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c
new file mode 100644
-index 0000000..977964d
+index 0000000..44e7a20
--- /dev/null
+++ b/ipc/kdbus/endpoint.c
-@@ -0,0 +1,275 @@
+@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -12232,6 +12257,34 @@ index 0000000..977964d
+}
+
+/**
++ * kdbus_ep_is_privileged() - check whether a file is privileged
++ * @ep: endpoint to operate on
++ * @file: file to test
++ *
++ * Return: True if @file is privileged in the domain of @ep.
++ */
++bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file)
++{
++ return !ep->user &&
++ file_ns_capable(file, ep->bus->domain->user_namespace,
++ CAP_IPC_OWNER);
++}
++
++/**
++ * kdbus_ep_is_owner() - check whether a file should be treated as bus owner
++ * @ep: endpoint to operate on
++ * @file: file to test
++ *
++ * Return: True if @file should be treated as bus owner on @ep
++ */
++bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file)
++{
++ return !ep->user &&
++ (uid_eq(file->f_cred->euid, ep->bus->node.uid) ||
++ kdbus_ep_is_privileged(ep, file));
++}
++
++/**
+ * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE
+ * @bus: bus to operate on
+ * @argp: command payload
@@ -12323,10 +12376,10 @@ index 0000000..977964d
+}
diff --git a/ipc/kdbus/endpoint.h b/ipc/kdbus/endpoint.h
new file mode 100644
-index 0000000..bc1b94a
+index 0000000..e0da59f
--- /dev/null
+++ b/ipc/kdbus/endpoint.h
-@@ -0,0 +1,67 @@
+@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -12390,6 +12443,9 @@ index 0000000..bc1b94a
+struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep);
+struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep);
+
++bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file);
++bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file);
++
+struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp);
+int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp);
+
@@ -12944,10 +13000,10 @@ index 0000000..62f7d6a
+#endif
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
new file mode 100644
-index 0000000..e0e06b0
+index 0000000..fc60932
--- /dev/null
+++ b/ipc/kdbus/handle.c
-@@ -0,0 +1,709 @@
+@@ -0,0 +1,691 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -13214,7 +13270,6 @@ index 0000000..e0e06b0
+ * @bus_owner: bus this handle owns
+ * @ep_owner: endpoint this handle owns
+ * @conn: connection this handle owns
-+ * @privileged: Flag to mark a handle as privileged
+ */
+struct kdbus_handle {
+ struct mutex lock;
@@ -13225,8 +13280,6 @@ index 0000000..e0e06b0
+ struct kdbus_ep *ep_owner;
+ struct kdbus_conn *conn;
+ };
-+
-+ bool privileged:1;
+};
+
+static int kdbus_handle_open(struct inode *inode, struct file *file)
@@ -13248,23 +13301,6 @@ index 0000000..e0e06b0
+ mutex_init(&handle->lock);
+ handle->type = KDBUS_HANDLE_NONE;
+
-+ if (node->type == KDBUS_NODE_ENDPOINT) {
-+ struct kdbus_ep *ep = kdbus_ep_from_node(node);
-+ struct kdbus_bus *bus = ep->bus;
-+
-+ /*
-+ * A connection is privileged if it is opened on an endpoint
-+ * without custom policy and either:
-+ * * the user has CAP_IPC_OWNER in the domain user namespace
-+ * or
-+ * * the callers euid matches the uid of the bus creator
-+ */
-+ if (!ep->user &&
-+ (ns_capable(bus->domain->user_namespace, CAP_IPC_OWNER) ||
-+ uid_eq(file->f_cred->euid, bus->node.uid)))
-+ handle->privileged = true;
-+ }
-+
+ file->private_data = handle;
+ ret = 0;
+
@@ -13356,6 +13392,7 @@ index 0000000..e0e06b0
+ struct kdbus_handle *handle = file->private_data;
+ struct kdbus_node *node = file_inode(file)->i_private;
+ struct kdbus_ep *ep, *file_ep = kdbus_ep_from_node(node);
++ struct kdbus_bus *bus = file_ep->bus;
+ struct kdbus_conn *conn;
+ int ret = 0;
+
@@ -13363,14 +13400,14 @@ index 0000000..e0e06b0
+ return -ESHUTDOWN;
+
+ switch (cmd) {
-+ case KDBUS_CMD_ENDPOINT_MAKE:
++ case KDBUS_CMD_ENDPOINT_MAKE: {
+ /* creating custom endpoints is a privileged operation */
-+ if (!handle->privileged) {
++ if (!kdbus_ep_is_owner(file_ep, file)) {
+ ret = -EPERM;
+ break;
+ }
+
-+ ep = kdbus_cmd_ep_make(file_ep->bus, buf);
++ ep = kdbus_cmd_ep_make(bus, buf);
+ if (IS_ERR_OR_NULL(ep)) {
+ ret = PTR_ERR_OR_ZERO(ep);
+ break;
@@ -13379,9 +13416,10 @@ index 0000000..e0e06b0
+ handle->ep_owner = ep;
+ ret = KDBUS_HANDLE_EP_OWNER;
+ break;
++ }
+
+ case KDBUS_CMD_HELLO:
-+ conn = kdbus_cmd_hello(file_ep, handle->privileged, buf);
++ conn = kdbus_cmd_hello(file_ep, file, buf);
+ if (IS_ERR_OR_NULL(conn)) {
+ ret = PTR_ERR_OR_ZERO(conn);
+ break;
@@ -13659,7 +13697,7 @@ index 0000000..e0e06b0
+};
diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h
new file mode 100644
-index 0000000..8a36c05
+index 0000000..5dde2c1
--- /dev/null
+++ b/ipc/kdbus/handle.h
@@ -0,0 +1,103 @@
@@ -13710,7 +13748,7 @@ index 0000000..8a36c05
+ * @argv: array of items this command supports
+ * @user: set by parser to user-space location of current command
+ * @cmd: set by parser to kernel copy of command payload
-+ * @cmd_buf: 512 bytes inline buf to avoid kmalloc() on small cmds
++ * @cmd_buf: inline buf to avoid kmalloc() on small cmds
+ * @items: points to item array in @cmd
+ * @items_size: size of @items in bytes
+ * @is_cmd: whether this is a command-payload or msg-payload
@@ -13720,7 +13758,7 @@ index 0000000..8a36c05
+ * the object to kdbus_args_parse(). The parser will copy the command payload
+ * into kernel-space and verify the correctness of the data.
+ *
-+ * We use a 512 bytes buffer for small command payloads, to be allocated on
++ * We use a 256 bytes buffer for small command payloads, to be allocated on
+ * stack on syscall entrance.
+ */
+struct kdbus_args {
@@ -13730,7 +13768,7 @@ index 0000000..8a36c05
+
+ struct kdbus_cmd __user *user;
+ struct kdbus_cmd *cmd;
-+ u8 cmd_buf[512];
++ u8 cmd_buf[256];
+
+ struct kdbus_item *items;
+ size_t items_size;
@@ -14914,7 +14952,7 @@ index 0000000..ceb492f
+#endif
diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c
new file mode 100644
-index 0000000..3520f45
+index 0000000..ae565cd
--- /dev/null
+++ b/ipc/kdbus/message.c
@@ -0,0 +1,1040 @@
@@ -15591,7 +15629,7 @@ index 0000000..3520f45
+ if (!staging)
+ return ERR_PTR(-ENOMEM);
+
-+ staging->msg_seqnum = atomic64_inc_return(&bus->domain->last_id);
++ staging->msg_seqnum = atomic64_inc_return(&bus->last_message_id);
+ staging->n_parts = 0; /* we reserve n_parts, but don't enforce them */
+ staging->parts = (void *)(staging + 1);
+
@@ -15806,9 +15844,9 @@ index 0000000..3520f45
+{
+ struct kdbus_item *item, *meta_items = NULL;
+ struct kdbus_pool_slice *slice = NULL;
-+ size_t off, size, msg_size, meta_size;
++ size_t off, size, meta_size;
+ struct iovec *v;
-+ u64 attach;
++ u64 attach, msg_size;
+ int ret;
+
+ /*
@@ -15840,7 +15878,7 @@ index 0000000..3520f45
+
+ /* msg.size */
+ v->iov_len = sizeof(msg_size);
-+ v->iov_base = &msg_size;
++ v->iov_base = (void __user *)&msg_size;
+ ++v;
+
+ /* msg (after msg.size) plus items */
@@ -15857,7 +15895,7 @@ index 0000000..3520f45
+ if (meta_size > 0) {
+ /* metadata items */
+ v->iov_len = meta_size;
-+ v->iov_base = meta_items;
++ v->iov_base = (void __user *)meta_items;
+ ++v;
+
+ /* padding after metadata */
@@ -16086,10 +16124,10 @@ index 0000000..298f9c9
+#endif
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
new file mode 100644
-index 0000000..d4973a9
+index 0000000..71ca475
--- /dev/null
+++ b/ipc/kdbus/metadata.c
-@@ -0,0 +1,1342 @@
+@@ -0,0 +1,1347 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -16695,7 +16733,7 @@ index 0000000..d4973a9
+static int kdbus_meta_conn_collect_names(struct kdbus_meta_conn *mc,
+ struct kdbus_conn *conn)
+{
-+ const struct kdbus_name_entry *e;
++ const struct kdbus_name_owner *owner;
+ struct kdbus_item *item;
+ size_t slen, size;
+
@@ -16703,9 +16741,11 @@ index 0000000..d4973a9
+
+ size = 0;
+ /* open-code length calculation to avoid final padding */
-+ list_for_each_entry(e, &conn->names_list, conn_entry)
-+ size = KDBUS_ALIGN8(size) + KDBUS_ITEM_HEADER_SIZE +
-+ sizeof(struct kdbus_name) + strlen(e->name) + 1;
++ list_for_each_entry(owner, &conn->names_list, conn_entry)
++ if (!(owner->flags & KDBUS_NAME_IN_QUEUE))
++ size = KDBUS_ALIGN8(size) + KDBUS_ITEM_HEADER_SIZE +
++ sizeof(struct kdbus_name) +
++ strlen(owner->name->name) + 1;
+
+ if (!size)
+ return 0;
@@ -16718,12 +16758,15 @@ index 0000000..d4973a9
+ mc->owned_names_items = item;
+ mc->owned_names_size = size;
+
-+ list_for_each_entry(e, &conn->names_list, conn_entry) {
-+ slen = strlen(e->name) + 1;
++ list_for_each_entry(owner, &conn->names_list, conn_entry) {
++ if (owner->flags & KDBUS_NAME_IN_QUEUE)
++ continue;
++
++ slen = strlen(owner->name->name) + 1;
+ kdbus_item_set(item, KDBUS_ITEM_OWNED_NAME, NULL,
+ sizeof(struct kdbus_name) + slen);
-+ item->name.flags = e->flags;
-+ memcpy(item->name.name, e->name, slen);
++ item->name.flags = owner->flags;
++ memcpy(item->name.name, owner->name->name, slen);
+ item = KDBUS_ITEM_NEXT(item);
+ }
+
@@ -17526,10 +17569,10 @@ index 0000000..dba7cc7
+#endif
diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c
new file mode 100644
-index 0000000..057f806
+index 0000000..bf44ca3
--- /dev/null
+++ b/ipc/kdbus/names.c
-@@ -0,0 +1,770 @@
+@@ -0,0 +1,854 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -17566,167 +17609,128 @@ index 0000000..057f806
+#include "notify.h"
+#include "policy.h"
+
-+struct kdbus_name_pending {
-+ u64 flags;
-+ struct kdbus_conn *conn;
-+ struct kdbus_name_entry *name;
-+ struct list_head conn_entry;
-+ struct list_head name_entry;
-+};
++#define KDBUS_NAME_SAVED_MASK (KDBUS_NAME_ALLOW_REPLACEMENT | \
++ KDBUS_NAME_QUEUE)
+
-+static int kdbus_name_pending_new(struct kdbus_name_entry *e,
-+ struct kdbus_conn *conn, u64 flags)
++static bool kdbus_name_owner_is_used(struct kdbus_name_owner *owner)
+{
-+ struct kdbus_name_pending *p;
-+
-+ kdbus_conn_assert_active(conn);
-+
-+ p = kmalloc(sizeof(*p), GFP_KERNEL);
-+ if (!p)
-+ return -ENOMEM;
-+
-+ p->flags = flags;
-+ p->conn = conn;
-+ p->name = e;
-+ list_add_tail(&p->conn_entry, &conn->names_queue_list);
-+ list_add_tail(&p->name_entry, &e->queue);
-+
-+ return 0;
++ return !list_empty(&owner->name_entry) ||
++ owner == owner->name->activator;
+}
+
-+static void kdbus_name_pending_free(struct kdbus_name_pending *p)
++static struct kdbus_name_owner *
++kdbus_name_owner_new(struct kdbus_conn *conn, struct kdbus_name_entry *name,
++ u64 flags)
+{
-+ if (!p)
-+ return;
++ struct kdbus_name_owner *owner;
+
-+ list_del(&p->name_entry);
-+ list_del(&p->conn_entry);
-+ kfree(p);
-+}
-+
-+static struct kdbus_name_entry *
-+kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash, const char *name)
-+{
-+ struct kdbus_name_entry *e;
-+ size_t namelen;
++ kdbus_conn_assert_active(conn);
+
-+ namelen = strlen(name);
++ if (conn->name_count >= KDBUS_CONN_MAX_NAMES)
++ return ERR_PTR(-E2BIG);
+
-+ e = kmalloc(sizeof(*e) + namelen + 1, GFP_KERNEL);
-+ if (!e)
++ owner = kmalloc(sizeof(*owner), GFP_KERNEL);
++ if (!owner)
+ return ERR_PTR(-ENOMEM);
+
-+ e->name_id = ++r->name_seq_last;
-+ e->flags = 0;
-+ e->conn = NULL;
-+ e->activator = NULL;
-+ INIT_LIST_HEAD(&e->queue);
-+ INIT_LIST_HEAD(&e->conn_entry);
-+ hash_add(r->entries_hash, &e->hentry, hash);
-+ memcpy(e->name, name, namelen + 1);
++ owner->flags = flags & KDBUS_NAME_SAVED_MASK;
++ owner->conn = conn;
++ owner->name = name;
++ list_add_tail(&owner->conn_entry, &conn->names_list);
++ INIT_LIST_HEAD(&owner->name_entry);
+
-+ return e;
++ ++conn->name_count;
++ return owner;
+}
+
-+static void kdbus_name_entry_free(struct kdbus_name_entry *e)
++static void kdbus_name_owner_free(struct kdbus_name_owner *owner)
+{
-+ if (!e)
++ if (!owner)
+ return;
+
-+ WARN_ON(!list_empty(&e->conn_entry));
-+ WARN_ON(!list_empty(&e->queue));
-+ WARN_ON(e->activator);
-+ WARN_ON(e->conn);
-+
-+ hash_del(&e->hentry);
-+ kfree(e);
++ WARN_ON(kdbus_name_owner_is_used(owner));
++ --owner->conn->name_count;
++ list_del(&owner->conn_entry);
++ kfree(owner);
+}
+
-+static void kdbus_name_entry_set_owner(struct kdbus_name_entry *e,
-+ struct kdbus_conn *conn, u64 flags)
++static struct kdbus_name_owner *
++kdbus_name_owner_find(struct kdbus_name_entry *name, struct kdbus_conn *conn)
+{
-+ WARN_ON(e->conn);
++ struct kdbus_name_owner *owner;
++
++ /*
++ * Use conn->names_list over name->queue to make sure boundaries of
++ * this linear search are controlled by the connection itself.
++ * Furthermore, this will find normal owners as well as activators
++ * without any additional code.
++ */
++ list_for_each_entry(owner, &conn->names_list, conn_entry)
++ if (owner->name == name)
++ return owner;
+
-+ e->conn = kdbus_conn_ref(conn);
-+ e->flags = flags;
-+ atomic_inc(&conn->name_count);
-+ list_add_tail(&e->conn_entry, &e->conn->names_list);
++ return NULL;
+}
+
-+static void kdbus_name_entry_remove_owner(struct kdbus_name_entry *e)
++static bool kdbus_name_entry_is_used(struct kdbus_name_entry *name)
+{
-+ WARN_ON(!e->conn);
-+
-+ list_del_init(&e->conn_entry);
-+ atomic_dec(&e->conn->name_count);
-+ e->flags = 0;
-+ e->conn = kdbus_conn_unref(e->conn);
++ return !list_empty(&name->queue) || name->activator;
+}
+
-+static void kdbus_name_entry_replace_owner(struct kdbus_name_entry *e,
-+ struct kdbus_conn *conn, u64 flags)
++static struct kdbus_name_owner *
++kdbus_name_entry_first(struct kdbus_name_entry *name)
+{
-+ if (WARN_ON(!e->conn) || WARN_ON(conn == e->conn))
-+ return;
-+
-+ kdbus_notify_name_change(conn->ep->bus, KDBUS_ITEM_NAME_CHANGE,
-+ e->conn->id, conn->id,
-+ e->flags, flags, e->name);
-+ kdbus_name_entry_remove_owner(e);
-+ kdbus_name_entry_set_owner(e, conn, flags);
++ return list_first_entry_or_null(&name->queue, struct kdbus_name_owner,
++ name_entry);
+}
+
-+/**
-+ * kdbus_name_is_valid() - check if a name is valid
-+ * @p: The name to check
-+ * @allow_wildcard: Whether or not to allow a wildcard name
-+ *
-+ * A name is valid if all of the following criterias are met:
-+ *
-+ * - The name has two or more elements separated by a period ('.') character.
-+ * - All elements must contain at least one character.
-+ * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-"
-+ * and must not begin with a digit.
-+ * - The name must not exceed KDBUS_NAME_MAX_LEN.
-+ * - If @allow_wildcard is true, the name may end on '.*'
-+ */
-+bool kdbus_name_is_valid(const char *p, bool allow_wildcard)
++static struct kdbus_name_entry *
++kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash,
++ const char *name_str)
+{
-+ bool dot, found_dot = false;
-+ const char *q;
++ struct kdbus_name_entry *name;
++ size_t namelen;
+
-+ for (dot = true, q = p; *q; q++) {
-+ if (*q == '.') {
-+ if (dot)
-+ return false;
++ lockdep_assert_held(&r->rwlock);
+
-+ found_dot = true;
-+ dot = true;
-+ } else {
-+ bool good;
++ namelen = strlen(name_str);
+
-+ good = isalpha(*q) || (!dot && isdigit(*q)) ||
-+ *q == '_' || *q == '-' ||
-+ (allow_wildcard && dot &&
-+ *q == '*' && *(q + 1) == '\0');
++ name = kmalloc(sizeof(*name) + namelen + 1, GFP_KERNEL);
++ if (!name)
++ return ERR_PTR(-ENOMEM);
+
-+ if (!good)
-+ return false;
++ name->name_id = ++r->name_seq_last;
++ name->activator = NULL;
++ INIT_LIST_HEAD(&name->queue);
++ hash_add(r->entries_hash, &name->hentry, hash);
++ memcpy(name->name, name_str, namelen + 1);
+
-+ dot = false;
-+ }
-+ }
++ return name;
++}
+
-+ if (q - p > KDBUS_NAME_MAX_LEN)
-+ return false;
++static void kdbus_name_entry_free(struct kdbus_name_entry *name)
++{
++ if (!name)
++ return;
+
-+ if (dot)
-+ return false;
++ WARN_ON(kdbus_name_entry_is_used(name));
++ hash_del(&name->hentry);
++ kfree(name);
++}
+
-+ if (!found_dot)
-+ return false;
++static struct kdbus_name_entry *
++kdbus_name_entry_find(struct kdbus_name_registry *r, u32 hash,
++ const char *name_str)
++{
++ struct kdbus_name_entry *name;
+
-+ return true;
++ lockdep_assert_held(&r->rwlock);
++
++ hash_for_each_possible(r->entries_hash, name, hentry, hash)
++ if (!strcmp(name->name, name_str))
++ return name;
++
++ return NULL;
+}
+
+/**
@@ -17750,32 +17754,19 @@ index 0000000..057f806
+}
+
+/**
-+ * kdbus_name_registry_free() - drop a name reg's reference
-+ * @reg: The name registry, may be %NULL
++ * kdbus_name_registry_free() - free name registry
++ * @r: name registry to free, or NULL
+ *
-+ * Cleanup the name registry's internal structures.
++ * Free a name registry and cleanup all internal objects. This is a no-op if
++ * you pass NULL as registry.
+ */
-+void kdbus_name_registry_free(struct kdbus_name_registry *reg)
++void kdbus_name_registry_free(struct kdbus_name_registry *r)
+{
-+ if (!reg)
++ if (!r)
+ return;
+
-+ WARN_ON(!hash_empty(reg->entries_hash));
-+ kfree(reg);
-+}
-+
-+static struct kdbus_name_entry *
-+kdbus_name_find(struct kdbus_name_registry *reg, u32 hash, const char *name)
-+{
-+ struct kdbus_name_entry *e;
-+
-+ lockdep_assert_held(®->rwlock);
-+
-+ hash_for_each_possible(reg->entries_hash, e, hentry, hash)
-+ if (strcmp(e->name, name) == 0)
-+ return e;
-+
-+ return NULL;
++ WARN_ON(!hash_empty(r->entries_hash));
++ kfree(r);
+}
+
+/**
@@ -17792,169 +17783,286 @@ index 0000000..057f806
+struct kdbus_name_entry *
+kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name)
+{
-+ return kdbus_name_find(reg, kdbus_strhash(name), name);
++ return kdbus_name_entry_find(reg, kdbus_strhash(name), name);
+}
+
-+/**
-+ * kdbus_name_acquire() - acquire a name
-+ * @reg: The name registry
-+ * @conn: The connection to pin this entry to
-+ * @name: The name to acquire
-+ * @flags: Acquisition flags (KDBUS_NAME_*)
-+ * @return_flags: Pointer to return flags for the acquired name
-+ * (KDBUS_NAME_*), may be %NULL
-+ *
-+ * Callers must ensure that @conn is either a privileged bus user or has
-+ * sufficient privileges in the policy-db to own the well-known name @name.
-+ *
-+ * Return: 0 success, negative error number on failure.
-+ */
-+int kdbus_name_acquire(struct kdbus_name_registry *reg,
-+ struct kdbus_conn *conn, const char *name,
-+ u64 flags, u64 *return_flags)
++static int kdbus_name_become_activator(struct kdbus_name_owner *owner,
++ u64 *return_flags)
+{
-+ struct kdbus_name_entry *e;
-+ u64 rflags = 0;
++ if (kdbus_name_owner_is_used(owner))
++ return -EALREADY;
++ if (owner->name->activator)
++ return -EEXIST;
++
++ owner->name->activator = owner;
++ owner->flags |= KDBUS_NAME_ACTIVATOR;
++
++ if (kdbus_name_entry_first(owner->name)) {
++ owner->flags |= KDBUS_NAME_IN_QUEUE;
++ } else {
++ owner->flags |= KDBUS_NAME_PRIMARY;
++ kdbus_notify_name_change(owner->conn->ep->bus,
++ KDBUS_ITEM_NAME_ADD,
++ 0, owner->conn->id,
++ 0, owner->flags,
++ owner->name->name);
++ }
++
++ if (return_flags)
++ *return_flags = owner->flags | KDBUS_NAME_ACQUIRED;
++
++ return 0;
++}
++
++static int kdbus_name_update(struct kdbus_name_owner *owner, u64 flags,
++ u64 *return_flags)
++{
++ struct kdbus_name_owner *primary, *activator;
++ struct kdbus_name_entry *name;
++ struct kdbus_bus *bus;
++ u64 nflags = 0;
+ int ret = 0;
-+ u32 hash;
+
-+ kdbus_conn_assert_active(conn);
++ name = owner->name;
++ bus = owner->conn->ep->bus;
++ primary = kdbus_name_entry_first(name);
++ activator = name->activator;
+
-+ down_write(®->rwlock);
++ /* cannot be activator and acquire a name */
++ if (owner == activator)
++ return -EUCLEAN;
+
-+ if (!kdbus_conn_policy_own_name(conn, current_cred(), name)) {
-+ ret = -EPERM;
-+ goto exit_unlock;
-+ }
++ /* update saved flags */
++ owner->flags = flags & KDBUS_NAME_SAVED_MASK;
+
-+ hash = kdbus_strhash(name);
-+ e = kdbus_name_find(reg, hash, name);
-+ if (!e) {
-+ /* claim new name */
++ if (!primary) {
++ /*
++ * No primary owner (but maybe an activator). Take over the
++ * name.
++ */
+
-+ if (conn->activator_of) {
-+ ret = -EINVAL;
-+ goto exit_unlock;
++ list_add(&owner->name_entry, &name->queue);
++ owner->flags |= KDBUS_NAME_PRIMARY;
++ nflags |= KDBUS_NAME_ACQUIRED;
++
++ /* move messages to new owner on activation */
++ if (activator) {
++ kdbus_conn_move_messages(owner->conn, activator->conn,
++ name->name_id);
++ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE,
++ activator->conn->id, owner->conn->id,
++ activator->flags, owner->flags,
++ name->name);
++ activator->flags &= ~KDBUS_NAME_PRIMARY;
++ activator->flags |= KDBUS_NAME_IN_QUEUE;
++ } else {
++ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_ADD,
++ 0, owner->conn->id,
++ 0, owner->flags,
++ name->name);
+ }
+
-+ e = kdbus_name_entry_new(reg, hash, name);
-+ if (IS_ERR(e)) {
-+ ret = PTR_ERR(e);
-+ goto exit_unlock;
-+ }
++ } else if (owner == primary) {
++ /*
++ * Already the primary owner of the name, flags were already
++ * updated. Nothing to do.
++ */
+
-+ if (kdbus_conn_is_activator(conn)) {
-+ e->activator = kdbus_conn_ref(conn);
-+ conn->activator_of = e;
-+ }
++ owner->flags |= KDBUS_NAME_PRIMARY;
++
++ } else if ((primary->flags & KDBUS_NAME_ALLOW_REPLACEMENT) &&
++ (flags & KDBUS_NAME_REPLACE_EXISTING)) {
++ /*
++ * We're not the primary owner but can replace it. Move us
++ * ahead of the primary owner and acquire the name (possibly
++ * skipping queued owners ahead of us).
++ */
++
++ list_del_init(&owner->name_entry);
++ list_add(&owner->name_entry, &name->queue);
++ owner->flags |= KDBUS_NAME_PRIMARY;
++ nflags |= KDBUS_NAME_ACQUIRED;
+
-+ kdbus_name_entry_set_owner(e, conn, flags);
-+ kdbus_notify_name_change(e->conn->ep->bus, KDBUS_ITEM_NAME_ADD,
-+ 0, e->conn->id, 0, e->flags, e->name);
-+ } else if (e->conn == conn || e == conn->activator_of) {
-+ /* connection already owns that name */
-+ ret = -EALREADY;
-+ } else if (kdbus_conn_is_activator(conn)) {
-+ /* activator claims existing name */
-+
-+ if (conn->activator_of) {
-+ ret = -EINVAL; /* multiple names not allowed */
-+ } else if (e->activator) {
-+ ret = -EEXIST; /* only one activator per name */
++ kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE,
++ primary->conn->id, owner->conn->id,
++ primary->flags, owner->flags,
++ name->name);
++
++ /* requeue old primary, or drop if queueing not wanted */
++ if (primary->flags & KDBUS_NAME_QUEUE) {
++ primary->flags &= ~KDBUS_NAME_PRIMARY;
++ primary->flags |= KDBUS_NAME_IN_QUEUE;
+ } else {
-+ e->activator = kdbus_conn_ref(conn);
-+ conn->activator_of = e;
-+ }
-+ } else if (e->flags & KDBUS_NAME_ACTIVATOR) {
-+ /* claim name of an activator */
-+
-+ kdbus_conn_move_messages(conn, e->activator, 0);
-+ kdbus_name_entry_replace_owner(e, conn, flags);
-+ } else if ((flags & KDBUS_NAME_REPLACE_EXISTING) &&
-+ (e->flags & KDBUS_NAME_ALLOW_REPLACEMENT)) {
-+ /* claim name of a previous owner */
-+
-+ if (e->flags & KDBUS_NAME_QUEUE) {
-+ /* move owner back to queue if they asked for it */
-+ ret = kdbus_name_pending_new(e, e->conn, e->flags);
-+ if (ret < 0)
-+ goto exit_unlock;
++ list_del_init(&primary->name_entry);
++ kdbus_name_owner_free(primary);
+ }
+
-+ kdbus_name_entry_replace_owner(e, conn, flags);
+ } else if (flags & KDBUS_NAME_QUEUE) {
-+ /* add to waiting-queue of the name */
++ /*
++ * Name is already occupied and we cannot take it over, but
++ * queuing is allowed. Put us silently on the queue, if not
++ * already there.
++ */
+
-+ ret = kdbus_name_pending_new(e, conn, flags);
-+ if (ret >= 0)
-+ /* tell the caller that we queued it */
-+ rflags |= KDBUS_NAME_IN_QUEUE;
++ owner->flags |= KDBUS_NAME_IN_QUEUE;
++ if (!kdbus_name_owner_is_used(owner)) {
++ list_add_tail(&owner->name_entry, &name->queue);
++ nflags |= KDBUS_NAME_ACQUIRED;
++ }
++ } else if (kdbus_name_owner_is_used(owner)) {
++ /*
++ * Already queued on name, but re-queueing was not requested.
++ * Make sure to unlink it from the name, the caller is
++ * responsible for releasing it.
++ */
++
++ list_del_init(&owner->name_entry);
+ } else {
-+ /* the name is busy, return a failure */
++ /*
++ * Name is already claimed and queueing is not requested.
++ * Return error to the caller.
++ */
++
+ ret = -EEXIST;
+ }
+
-+ if (ret == 0 && return_flags)
-+ *return_flags = rflags;
++ if (return_flags)
++ *return_flags = owner->flags | nflags;
+
-+exit_unlock:
-+ up_write(®->rwlock);
-+ kdbus_notify_flush(conn->ep->bus);
+ return ret;
+}
+
-+static void kdbus_name_release_unlocked(struct kdbus_name_registry *reg,
-+ struct kdbus_name_entry *e)
++int kdbus_name_acquire(struct kdbus_name_registry *reg,
++ struct kdbus_conn *conn, const char *name_str,
++ u64 flags, u64 *return_flags)
+{
-+ struct kdbus_name_pending *p;
++ struct kdbus_name_entry *name = NULL;
++ struct kdbus_name_owner *owner = NULL;
++ u32 hash;
++ int ret;
++
++ kdbus_conn_assert_active(conn);
+
-+ lockdep_assert_held(®->rwlock);
++ down_write(®->rwlock);
+
-+ p = list_first_entry_or_null(&e->queue, struct kdbus_name_pending,
-+ name_entry);
++ /*
++ * Verify the connection has access to the name. Do this before testing
++ * for double-acquisitions and other errors to make sure we do not leak
++ * information about this name through possible custom endpoints.
++ */
++ if (!kdbus_conn_policy_own_name(conn, current_cred(), name_str)) {
++ ret = -EPERM;
++ goto exit;
++ }
+
-+ if (p) {
-+ /* give it to first active waiter in the queue */
-+ kdbus_name_entry_replace_owner(e, p->conn, p->flags);
-+ kdbus_name_pending_free(p);
-+ } else if (e->activator && e->activator != e->conn) {
-+ /* hand it back to an active activator connection */
-+ kdbus_conn_move_messages(e->activator, e->conn, e->name_id);
-+ kdbus_name_entry_replace_owner(e, e->activator,
-+ KDBUS_NAME_ACTIVATOR);
++ /*
++ * Lookup the name entry. If it already exists, search for an owner
++ * entry as we might already own that name. If either does not exist,
++ * we will allocate a fresh one.
++ */
++ hash = kdbus_strhash(name_str);
++ name = kdbus_name_entry_find(reg, hash, name_str);
++ if (name) {
++ owner = kdbus_name_owner_find(name, conn);
+ } else {
-+ /* release the name */
-+ kdbus_notify_name_change(e->conn->ep->bus,
-+ KDBUS_ITEM_NAME_REMOVE,
-+ e->conn->id, 0, e->flags, 0, e->name);
-+ kdbus_name_entry_remove_owner(e);
-+ kdbus_name_entry_free(e);
++ name = kdbus_name_entry_new(reg, hash, name_str);
++ if (IS_ERR(name)) {
++ ret = PTR_ERR(name);
++ name = NULL;
++ goto exit;
++ }
++ }
++
++ /* create name owner object if not already queued */
++ if (!owner) {
++ owner = kdbus_name_owner_new(conn, name, flags);
++ if (IS_ERR(owner)) {
++ ret = PTR_ERR(owner);
++ owner = NULL;
++ goto exit;
++ }
++ }
++
++ if (flags & KDBUS_NAME_ACTIVATOR)
++ ret = kdbus_name_become_activator(owner, return_flags);
++ else
++ ret = kdbus_name_update(owner, flags, return_flags);
++ if (ret < 0)
++ goto exit;
++
++exit:
++ if (owner && !kdbus_name_owner_is_used(owner))
++ kdbus_name_owner_free(owner);
++ if (name && !kdbus_name_entry_is_used(name))
++ kdbus_name_entry_free(name);
++ up_write(®->rwlock);
++ kdbus_notify_flush(conn->ep->bus);
++ return ret;
++}
++
++static void kdbus_name_release_unlocked(struct kdbus_name_owner *owner)
++{
++ struct kdbus_name_owner *primary, *next;
++ struct kdbus_name_entry *name;
++
++ name = owner->name;
++ primary = kdbus_name_entry_first(name);
++
++ list_del_init(&owner->name_entry);
++ if (owner == name->activator)
++ name->activator = NULL;
++
++ if (!primary || owner == primary) {
++ next = kdbus_name_entry_first(name);
++ if (!next)
++ next = name->activator;
++
++ if (next) {
++ /* hand to next in queue */
++ next->flags &= ~KDBUS_NAME_IN_QUEUE;
++ next->flags |= KDBUS_NAME_PRIMARY;
++ if (next == name->activator)
++ kdbus_conn_move_messages(next->conn,
++ owner->conn,
++ name->name_id);
++
++ kdbus_notify_name_change(owner->conn->ep->bus,
++ KDBUS_ITEM_NAME_CHANGE,
++ owner->conn->id, next->conn->id,
++ owner->flags, next->flags,
++ name->name);
++ } else {
++ kdbus_notify_name_change(owner->conn->ep->bus,
++ KDBUS_ITEM_NAME_REMOVE,
++ owner->conn->id, 0,
++ owner->flags, 0,
++ name->name);
++ }
+ }
++
++ kdbus_name_owner_free(owner);
++ if (!kdbus_name_entry_is_used(name))
++ kdbus_name_entry_free(name);
+}
+
+static int kdbus_name_release(struct kdbus_name_registry *reg,
+ struct kdbus_conn *conn,
-+ const char *name)
++ const char *name_str)
+{
-+ struct kdbus_name_pending *p;
-+ struct kdbus_name_entry *e;
++ struct kdbus_name_owner *owner;
++ struct kdbus_name_entry *name;
+ int ret = 0;
+
+ down_write(®->rwlock);
-+ e = kdbus_name_find(reg, kdbus_strhash(name), name);
-+ if (!e) {
-+ ret = -ESRCH;
-+ } else if (e->conn == conn) {
-+ kdbus_name_release_unlocked(reg, e);
++ name = kdbus_name_entry_find(reg, kdbus_strhash(name_str), name_str);
++ if (name) {
++ owner = kdbus_name_owner_find(name, conn);
++ if (owner)
++ kdbus_name_release_unlocked(owner);
++ else
++ ret = -EADDRINUSE;
+ } else {
-+ ret = -EADDRINUSE;
-+ list_for_each_entry(p, &e->queue, name_entry) {
-+ if (p->conn == conn) {
-+ kdbus_name_pending_free(p);
-+ ret = 0;
-+ break;
-+ }
-+ }
++ ret = -ESRCH;
+ }
+ up_write(®->rwlock);
+
@@ -17970,33 +18078,74 @@ index 0000000..057f806
+void kdbus_name_release_all(struct kdbus_name_registry *reg,
+ struct kdbus_conn *conn)
+{
-+ struct kdbus_name_pending *p;
-+ struct kdbus_conn *activator = NULL;
-+ struct kdbus_name_entry *e;
++ struct kdbus_name_owner *owner;
+
+ down_write(®->rwlock);
+
-+ if (conn->activator_of) {
-+ activator = conn->activator_of->activator;
-+ conn->activator_of->activator = NULL;
-+ }
-+
-+ while ((p = list_first_entry_or_null(&conn->names_queue_list,
-+ struct kdbus_name_pending,
-+ conn_entry)))
-+ kdbus_name_pending_free(p);
-+ while ((e = list_first_entry_or_null(&conn->names_list,
-+ struct kdbus_name_entry,
-+ conn_entry)))
-+ kdbus_name_release_unlocked(reg, e);
++ while ((owner = list_first_entry_or_null(&conn->names_list,
++ struct kdbus_name_owner,
++ conn_entry)))
++ kdbus_name_release_unlocked(owner);
+
+ up_write(®->rwlock);
+
-+ kdbus_conn_unref(activator);
+ kdbus_notify_flush(conn->ep->bus);
+}
+
+/**
++ * kdbus_name_is_valid() - check if a name is valid
++ * @p: The name to check
++ * @allow_wildcard: Whether or not to allow a wildcard name
++ *
++ * A name is valid if all of the following criterias are met:
++ *
++ * - The name has two or more elements separated by a period ('.') character.
++ * - All elements must contain at least one character.
++ * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-"
++ * and must not begin with a digit.
++ * - The name must not exceed KDBUS_NAME_MAX_LEN.
++ * - If @allow_wildcard is true, the name may end on '.*'
++ */
++bool kdbus_name_is_valid(const char *p, bool allow_wildcard)
++{
++ bool dot, found_dot = false;
++ const char *q;
++
++ for (dot = true, q = p; *q; q++) {
++ if (*q == '.') {
++ if (dot)
++ return false;
++
++ found_dot = true;
++ dot = true;
++ } else {
++ bool good;
++
++ good = isalpha(*q) || (!dot && isdigit(*q)) ||
++ *q == '_' || *q == '-' ||
++ (allow_wildcard && dot &&
++ *q == '*' && *(q + 1) == '\0');
++
++ if (!good)
++ return false;
++
++ dot = false;
++ }
++ }
++
++ if (q - p > KDBUS_NAME_MAX_LEN)
++ return false;
++
++ if (dot)
++ return false;
++
++ if (!found_dot)
++ return false;
++
++ return true;
++}
++
++/**
+ * kdbus_cmd_name_acquire() - handle KDBUS_CMD_NAME_ACQUIRE
+ * @conn: connection to operate on
+ * @argp: command payload
@@ -18035,20 +18184,9 @@ index 0000000..057f806
+ goto exit;
+ }
+
-+ /*
-+ * Do atomic_inc_return here to reserve our slot, then decrement
-+ * it before returning.
-+ */
-+ if (atomic_inc_return(&conn->name_count) > KDBUS_CONN_MAX_NAMES) {
-+ ret = -E2BIG;
-+ goto exit_dec;
-+ }
-+
+ ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name,
+ cmd->flags, &cmd->return_flags);
+
-+exit_dec:
-+ atomic_dec(&conn->name_count);
+exit:
+ return kdbus_args_clear(&args, ret);
+}
@@ -18091,7 +18229,7 @@ index 0000000..057f806
+ struct kdbus_conn *c,
+ struct kdbus_pool_slice *slice,
+ size_t *pos,
-+ struct kdbus_name_entry *e,
++ struct kdbus_name_owner *o,
+ bool write)
+{
+ struct kvec kvec[4];
@@ -18112,22 +18250,22 @@ index 0000000..057f806
+ u64 flags;
+ } h = {};
+
-+ if (e && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(),
-+ e->name))
++ if (o && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(),
++ o->name->name))
+ return 0;
+
+ kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size);
+
+ /* append name */
-+ if (e) {
-+ size_t slen = strlen(e->name) + 1;
++ if (o) {
++ size_t slen = strlen(o->name->name) + 1;
+
+ h.size = offsetof(struct kdbus_item, name.name) + slen;
+ h.type = KDBUS_ITEM_OWNED_NAME;
-+ h.flags = e->flags;
++ h.flags = o->flags;
+
+ kdbus_kvec_set(&kvec[cnt++], &h, sizeof(h), &info.size);
-+ kdbus_kvec_set(&kvec[cnt++], e->name, slen, &info.size);
++ kdbus_kvec_set(&kvec[cnt++], o->name->name, slen, &info.size);
+ cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size);
+ }
+
@@ -18157,63 +18295,52 @@ index 0000000..057f806
+ if (kdbus_conn_is_monitor(c))
+ continue;
+
-+ /* skip activators */
-+ if (!(flags & KDBUS_LIST_ACTIVATORS) &&
-+ kdbus_conn_is_activator(c))
-+ continue;
-+
+ /* all names the connection owns */
-+ if (flags & (KDBUS_LIST_NAMES | KDBUS_LIST_ACTIVATORS)) {
-+ struct kdbus_name_entry *e;
++ if (flags & (KDBUS_LIST_NAMES |
++ KDBUS_LIST_ACTIVATORS |
++ KDBUS_LIST_QUEUED)) {
++ struct kdbus_name_owner *o;
+
-+ list_for_each_entry(e, &c->names_list, conn_entry) {
-+ struct kdbus_conn *a = e->activator;
++ list_for_each_entry(o, &c->names_list, conn_entry) {
++ if (o->flags & KDBUS_NAME_ACTIVATOR) {
++ if (!(flags & KDBUS_LIST_ACTIVATORS))
++ continue;
+
-+ if ((flags & KDBUS_LIST_ACTIVATORS) &&
-+ a && a != c) {
-+ ret = kdbus_list_write(conn, a, slice,
-+ &p, e, write);
++ ret = kdbus_list_write(conn, c, slice,
++ &p, o, write);
+ if (ret < 0) {
+ mutex_unlock(&c->lock);
+ return ret;
+ }
+
+ added = true;
-+ }
++ } else if (o->flags & KDBUS_NAME_IN_QUEUE) {
++ if (!(flags & KDBUS_LIST_QUEUED))
++ continue;
+
-+ if (flags & KDBUS_LIST_NAMES ||
-+ kdbus_conn_is_activator(c)) {
+ ret = kdbus_list_write(conn, c, slice,
-+ &p, e, write);
++ &p, o, write);
+ if (ret < 0) {
+ mutex_unlock(&c->lock);
+ return ret;
+ }
+
+ added = true;
-+ }
-+ }
-+ }
++ } else if (flags & KDBUS_LIST_NAMES) {
++ ret = kdbus_list_write(conn, c, slice,
++ &p, o, write);
++ if (ret < 0) {
++ mutex_unlock(&c->lock);
++ return ret;
++ }
+
-+ /* queue of names the connection is currently waiting for */
-+ if (flags & KDBUS_LIST_QUEUED) {
-+ struct kdbus_name_pending *q;
-+
-+ list_for_each_entry(q, &c->names_queue_list,
-+ conn_entry) {
-+ ret = kdbus_list_write(conn, c, slice, &p,
-+ q->name, write);
-+ if (ret < 0) {
-+ mutex_unlock(&c->lock);
-+ return ret;
++ added = true;
+ }
-+
-+ added = true;
+ }
+ }
+
+ /* nothing added so far, just add the unique ID */
-+ if (!added && flags & KDBUS_LIST_UNIQUE) {
++ if (!added && (flags & KDBUS_LIST_UNIQUE)) {
+ ret = kdbus_list_write(conn, c, slice, &p, NULL, write);
+ if (ret < 0)
+ return ret;
@@ -18302,10 +18429,10 @@ index 0000000..057f806
+}
diff --git a/ipc/kdbus/names.h b/ipc/kdbus/names.h
new file mode 100644
-index 0000000..3dd2589
+index 0000000..edac59d
--- /dev/null
+++ b/ipc/kdbus/names.h
-@@ -0,0 +1,74 @@
+@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -18326,6 +18453,10 @@ index 0000000..3dd2589
+#include <linux/hashtable.h>
+#include <linux/rwsem.h>
+
++struct kdbus_name_entry;
++struct kdbus_name_owner;
++struct kdbus_name_registry;
++
+/**
+ * struct kdbus_name_registry - names registered for a bus
+ * @entries_hash: Map of entries
@@ -18340,27 +18471,37 @@ index 0000000..3dd2589
+
+/**
+ * struct kdbus_name_entry - well-know name entry
-+ * @name_id: Sequence number of name entry to be able to uniquely
++ * @name_id: sequence number of name entry to be able to uniquely
+ * identify a name over its registration lifetime
-+ * @flags: KDBUS_NAME_* flags
-+ * @conn: Connection owning the name
-+ * @activator: Connection of the activator queuing incoming messages
-+ * @queue: List of queued connections
-+ * @conn_entry: Entry in connection
-+ * @hentry: Entry in registry map
-+ * @name: The well-known name
++ * @activator: activator of this name, or NULL
++ * @queue: list of queued owners
++ * @hentry: entry in registry map
++ * @name: well-known name
+ */
+struct kdbus_name_entry {
+ u64 name_id;
-+ u64 flags;
-+ struct kdbus_conn *conn;
-+ struct kdbus_conn *activator;
++ struct kdbus_name_owner *activator;
+ struct list_head queue;
-+ struct list_head conn_entry;
+ struct hlist_node hentry;
+ char name[];
+};
+
++/**
++ * struct kdbus_name_owner - owner of a well-known name
++ * @flags: KDBUS_NAME_* flags of this owner
++ * @conn: connection owning the name
++ * @name: name that is owned
++ * @conn_entry: link into @conn
++ * @name_entry: link into @name
++ */
++struct kdbus_name_owner {
++ u64 flags;
++ struct kdbus_conn *conn;
++ struct kdbus_name_entry *name;
++ struct list_head conn_entry;
++ struct list_head name_entry;
++};
++
+bool kdbus_name_is_valid(const char *p, bool allow_wildcard);
+
+struct kdbus_name_registry *kdbus_name_registry_new(void);
@@ -18379,6 +18520,23 @@ index 0000000..3dd2589
+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp);
+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp);
+
++/**
++ * kdbus_name_get_owner() - get current owner of a name
++ * @name: name to get current owner of
++ *
++ * This returns a pointer to the current owner of a name (or its activator if
++ * there is no owner). The caller must make sure @name is valid and does not
++ * vanish.
++ *
++ * Return: Pointer to current owner or NULL if there is none.
++ */
++static inline struct kdbus_name_owner *
++kdbus_name_get_owner(struct kdbus_name_entry *name)
++{
++ return list_first_entry_or_null(&name->queue, struct kdbus_name_owner,
++ name_entry) ? : name->activator;
++}
++
+#endif
diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c
new file mode 100644
@@ -22164,10 +22322,10 @@ index 0000000..7f3abae
+#endif /* KDBUS_API_H */
diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c
new file mode 100644
-index 0000000..c3ba958
+index 0000000..5a6dfdc
--- /dev/null
+++ b/samples/kdbus/kdbus-workers.c
-@@ -0,0 +1,1345 @@
+@@ -0,0 +1,1346 @@
+/*
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ *
@@ -22229,9 +22387,11 @@ index 0000000..c3ba958
+
+#include <stdio.h>
+#include <stdlib.h>
++#include <sys/syscall.h>
+
+/* glibc < 2.7 does not ship sys/signalfd.h */
-+#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7
++/* we require kernels with __NR_memfd_create */
++#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7 && defined(__NR_memfd_create)
+
+#include <ctype.h>
+#include <errno.h>
@@ -22245,7 +22405,6 @@ index 0000000..c3ba958
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/signalfd.h>
-+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <time.h>
@@ -23710,10 +23869,10 @@ index 0000000..ed28cca
+const char *enum_PAYLOAD(long long id);
diff --git a/tools/testing/selftests/kdbus/kdbus-test.c b/tools/testing/selftests/kdbus/kdbus-test.c
new file mode 100644
-index 0000000..db732e5
+index 0000000..db57381
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-test.c
-@@ -0,0 +1,899 @@
+@@ -0,0 +1,905 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
@@ -23834,6 +23993,12 @@ index 0000000..db732e5
+ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ },
+ {
++ .name = "name-takeover",
++ .desc = "takeover of names",
++ .func = kdbus_test_name_takeover,
++ .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
++ },
++ {
+ .name = "message-basic",
+ .desc = "basic message handling",
+ .func = kdbus_test_message_basic,
@@ -24615,10 +24780,10 @@ index 0000000..db732e5
+}
diff --git a/tools/testing/selftests/kdbus/kdbus-test.h b/tools/testing/selftests/kdbus/kdbus-test.h
new file mode 100644
-index 0000000..a5c6ae8
+index 0000000..ee937f9
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-test.h
-@@ -0,0 +1,83 @@
+@@ -0,0 +1,84 @@
+#ifndef _TEST_KDBUS_H_
+#define _TEST_KDBUS_H_
+
@@ -24693,6 +24858,7 @@ index 0000000..a5c6ae8
+int kdbus_test_name_basic(struct kdbus_test_env *env);
+int kdbus_test_name_conflict(struct kdbus_test_env *env);
+int kdbus_test_name_queue(struct kdbus_test_env *env);
++int kdbus_test_name_takeover(struct kdbus_test_env *env);
+int kdbus_test_policy(struct kdbus_test_env *env);
+int kdbus_test_policy_ns(struct kdbus_test_env *env);
+int kdbus_test_policy_priv(struct kdbus_test_env *env);
@@ -24704,10 +24870,10 @@ index 0000000..a5c6ae8
+#endif /* _TEST_KDBUS_H_ */
diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
new file mode 100644
-index 0000000..a5e54ca
+index 0000000..82fa89b
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-util.c
-@@ -0,0 +1,1611 @@
+@@ -0,0 +1,1612 @@
+/*
+ * Copyright (C) 2013-2015 Daniel Mack
+ * Copyright (C) 2013-2015 Kay Sievers
@@ -25865,11 +26031,12 @@ index 0000000..a5e54ca
+ if (item->type == KDBUS_ITEM_OWNED_NAME) {
+ n = item->name.name;
+ flags = item->name.flags;
-+ }
+
-+ kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
-+ name->id, (unsigned long long) flags,
-+ name->flags, n);
++ kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
++ name->id,
++ (unsigned long long) flags,
++ name->flags, n);
++ }
+ }
+ kdbus_printf("\n");
+
@@ -27507,10 +27674,10 @@ index 0000000..762fb30
+}
diff --git a/tools/testing/selftests/kdbus/test-chat.c b/tools/testing/selftests/kdbus/test-chat.c
new file mode 100644
-index 0000000..71a92d8
+index 0000000..41e5b53
--- /dev/null
+++ b/tools/testing/selftests/kdbus/test-chat.c
-@@ -0,0 +1,122 @@
+@@ -0,0 +1,124 @@
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
@@ -27554,8 +27721,10 @@ index 0000000..71a92d8
+ ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL);
+ ASSERT_RETURN(ret == 0);
+
-+ ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL);
-+ ASSERT_RETURN(ret == -EALREADY);
++ flags = 0;
++ ret = kdbus_name_acquire(conn_a, "foo.bar.double", &flags);
++ ASSERT_RETURN(ret == 0);
++ ASSERT_RETURN(!(flags & KDBUS_NAME_ACQUIRED));
+
+ ret = kdbus_name_release(conn_a, "foo.bar.double");
+ ASSERT_RETURN(ret == 0);
@@ -29979,7 +30148,7 @@ index 0000000..2360dc1
+}
diff --git a/tools/testing/selftests/kdbus/test-message.c b/tools/testing/selftests/kdbus/test-message.c
new file mode 100644
-index 0000000..ddc1e0a
+index 0000000..563dc85
--- /dev/null
+++ b/tools/testing/selftests/kdbus/test-message.c
@@ -0,0 +1,734 @@
@@ -30060,7 +30229,7 @@ index 0000000..ddc1e0a
+
+ /* Faked replies with a valid reply cookie are rejected */
+ ret = kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id);
-+ ASSERT_RETURN(ret == -EPERM);
++ ASSERT_RETURN(ret == -EBADSLT);
+
+ ret = kdbus_free(conn, offset);
+ ASSERT_RETURN(ret == 0);
@@ -31407,10 +31576,10 @@ index 0000000..e00d738
+}
diff --git a/tools/testing/selftests/kdbus/test-names.c b/tools/testing/selftests/kdbus/test-names.c
new file mode 100644
-index 0000000..66ebb47
+index 0000000..e400dc8
--- /dev/null
+++ b/tools/testing/selftests/kdbus/test-names.c
-@@ -0,0 +1,194 @@
+@@ -0,0 +1,272 @@
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
@@ -31430,39 +31599,68 @@ index 0000000..66ebb47
+#include "kdbus-enum.h"
+#include "kdbus-test.h"
+
-+static int conn_is_name_owner(const struct kdbus_conn *conn,
-+ const char *needle)
++struct test_name {
++ const char *name;
++ __u64 owner_id;
++ __u64 flags;
++};
++
++static bool conn_test_names(const struct kdbus_conn *conn,
++ const struct test_name *tests,
++ unsigned int n_tests)
+{
-+ struct kdbus_cmd_list cmd_list = { .size = sizeof(cmd_list) };
++ struct kdbus_cmd_list cmd_list = {};
+ struct kdbus_info *name, *list;
-+ bool found = false;
++ unsigned int i;
+ int ret;
+
-+ cmd_list.flags = KDBUS_LIST_NAMES;
++ cmd_list.size = sizeof(cmd_list);
++ cmd_list.flags = KDBUS_LIST_NAMES |
++ KDBUS_LIST_ACTIVATORS |
++ KDBUS_LIST_QUEUED;
+
+ ret = kdbus_cmd_list(conn->fd, &cmd_list);
+ ASSERT_RETURN(ret == 0);
+
+ list = (struct kdbus_info *)(conn->buf + cmd_list.offset);
-+ KDBUS_FOREACH(name, list, cmd_list.list_size) {
-+ struct kdbus_item *item;
-+ const char *n = NULL;
+
-+ KDBUS_ITEM_FOREACH(item, name, items)
-+ if (item->type == KDBUS_ITEM_OWNED_NAME)
-+ n = item->name.name;
++ for (i = 0; i < n_tests; i++) {
++ const struct test_name *t = tests + i;
++ bool found = false;
+
-+ if (name->id == conn->id &&
-+ n && strcmp(needle, n) == 0) {
-+ found = true;
-+ break;
++ KDBUS_FOREACH(name, list, cmd_list.list_size) {
++ struct kdbus_item *item;
++
++ KDBUS_ITEM_FOREACH(item, name, items) {
++ if (item->type != KDBUS_ITEM_OWNED_NAME ||
++ strcmp(item->name.name, t->name) != 0)
++ continue;
++
++ if (t->owner_id == name->id &&
++ t->flags == item->name.flags) {
++ found = true;
++ break;
++ }
++ }
+ }
++
++ if (!found)
++ return false;
+ }
+
-+ ret = kdbus_free(conn, cmd_list.offset);
-+ ASSERT_RETURN(ret == 0);
++ return true;
++}
++
++static bool conn_is_name_primary_owner(const struct kdbus_conn *conn,
++ const char *needle)
++{
++ struct test_name t = {
++ .name = needle,
++ .owner_id = conn->id,
++ .flags = KDBUS_NAME_PRIMARY,
++ };
+
-+ return found ? 0 : -1;
++ return conn_test_names(conn, &t, 1);
+}
+
+int kdbus_test_name_basic(struct kdbus_test_env *env)
@@ -31498,15 +31696,15 @@ index 0000000..66ebb47
+ ret = kdbus_name_acquire(env->conn, name, NULL);
+ ASSERT_RETURN(ret == 0);
+
-+ ret = conn_is_name_owner(env->conn, name);
-+ ASSERT_RETURN(ret == 0);
++ ret = conn_is_name_primary_owner(env->conn, name);
++ ASSERT_RETURN(ret == true);
+
+ /* ... and release it again */
+ ret = kdbus_name_release(env->conn, name);
+ ASSERT_RETURN(ret == 0);
+
-+ ret = conn_is_name_owner(env->conn, name);
-+ ASSERT_RETURN(ret != 0);
++ ret = conn_is_name_primary_owner(env->conn, name);
++ ASSERT_RETURN(ret == false);
+
+ /* check that we can't release it again */
+ ret = kdbus_name_release(env->conn, name);
@@ -31548,12 +31746,8 @@ index 0000000..66ebb47
+ ret = kdbus_name_acquire(env->conn, name, NULL);
+ ASSERT_RETURN(ret == 0);
+
-+ ret = conn_is_name_owner(env->conn, name);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /* check that we can't acquire it again from the 1st connection */
-+ ret = kdbus_name_acquire(env->conn, name, NULL);
-+ ASSERT_RETURN(ret == -EALREADY);
++ ret = conn_is_name_primary_owner(env->conn, name);
++ ASSERT_RETURN(ret == true);
+
+ /* check that we also can't acquire it again from the 2nd connection */
+ ret = kdbus_name_acquire(conn, name, NULL);
@@ -31567,13 +31761,14 @@ index 0000000..66ebb47
+int kdbus_test_name_queue(struct kdbus_test_env *env)
+{
+ struct kdbus_conn *conn;
++ struct test_name t[2];
+ const char *name;
+ uint64_t flags;
+ int ret;
+
+ name = "foo.bla.blaz";
+
-+ flags = KDBUS_NAME_ALLOW_REPLACEMENT;
++ flags = 0;
+
+ /* create a 2nd connection */
+ conn = kdbus_hello(env->buspath, 0, NULL, 0);
@@ -31584,8 +31779,8 @@ index 0000000..66ebb47
+ ret = kdbus_name_acquire(env->conn, name, &flags);
+ ASSERT_RETURN(ret == 0);
+
-+ ret = conn_is_name_owner(env->conn, name);
-+ ASSERT_RETURN(ret == 0);
++ ret = conn_is_name_primary_owner(env->conn, name);
++ ASSERT_RETURN(ret == true);
+
+ /* queue the 2nd connection as waiting owner */
+ flags = KDBUS_NAME_QUEUE;
@@ -31593,13 +31788,65 @@ index 0000000..66ebb47
+ ASSERT_RETURN(ret == 0);
+ ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE);
+
++ t[0].name = name;
++ t[0].owner_id = env->conn->id;
++ t[0].flags = KDBUS_NAME_PRIMARY;
++ t[1].name = name;
++ t[1].owner_id = conn->id;
++ t[1].flags = KDBUS_NAME_QUEUE | KDBUS_NAME_IN_QUEUE;
++ ret = conn_test_names(conn, t, 2);
++ ASSERT_RETURN(ret == true);
++
+ /* release name from 1st connection */
+ ret = kdbus_name_release(env->conn, name);
+ ASSERT_RETURN(ret == 0);
+
+ /* now the name should be owned by the 2nd connection */
-+ ret = conn_is_name_owner(conn, name);
++ t[0].name = name;
++ t[0].owner_id = conn->id;
++ t[0].flags = KDBUS_NAME_PRIMARY | KDBUS_NAME_QUEUE;
++ ret = conn_test_names(conn, t, 1);
++ ASSERT_RETURN(ret == true);
++
++ kdbus_conn_free(conn);
++
++ return TEST_OK;
++}
++
++int kdbus_test_name_takeover(struct kdbus_test_env *env)
++{
++ struct kdbus_conn *conn;
++ struct test_name t;
++ const char *name;
++ uint64_t flags;
++ int ret;
++
++ name = "foo.bla.blaz";
++
++ flags = KDBUS_NAME_ALLOW_REPLACEMENT;
++
++ /* create a 2nd connection */
++ conn = kdbus_hello(env->buspath, 0, NULL, 0);
++ ASSERT_RETURN(conn != NULL);
++
++ /* acquire name for 1st connection */
++ ret = kdbus_name_acquire(env->conn, name, &flags);
++ ASSERT_RETURN(ret == 0);
++
++ t.name = name;
++ t.owner_id = env->conn->id;
++ t.flags = KDBUS_NAME_ALLOW_REPLACEMENT | KDBUS_NAME_PRIMARY;
++ ret = conn_test_names(conn, &t, 1);
++ ASSERT_RETURN(ret == true);
++
++ /* now steal name with 2nd connection */
++ flags = KDBUS_NAME_REPLACE_EXISTING;
++ ret = kdbus_name_acquire(conn, name, &flags);
+ ASSERT_RETURN(ret == 0);
++ ASSERT_RETURN(flags & KDBUS_NAME_ACQUIRED);
++
++ ret = conn_is_name_primary_owner(conn, name);
++ ASSERT_RETURN(ret == true);
+
+ kdbus_conn_free(conn);
+
@@ -33622,7 +33869,7 @@ index 0000000..96d20d5
+}
diff --git a/tools/testing/selftests/kdbus/test-sync.c b/tools/testing/selftests/kdbus/test-sync.c
new file mode 100644
-index 0000000..e2be910
+index 0000000..0655a54
--- /dev/null
+++ b/tools/testing/selftests/kdbus/test-sync.c
@@ -0,0 +1,369 @@
@@ -33863,7 +34110,7 @@ index 0000000..e2be910
+
+ /* using an unknown cookie must fail */
+ ret = kdbus_msg_send_reply(conn_a, ~cookie, conn_b->id);
-+ if (ret != -EPERM) {
++ if (ret != -EBADSLT) {
+ status = TEST_ERR;
+ goto exit_thread;
+ }
next reply other threads:[~2015-08-12 14:17 UTC|newest]
Thread overview: 71+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-12 14:17 Mike Pagano [this message]
-- strict thread matches above, loose matches on Subject: below --
2018-05-29 10:34 [gentoo-commits] proj/linux-patches:4.1 commit in: / Mike Pagano
2018-01-23 9:37 Alice Ferrazzi
2017-12-15 20:22 Alice Ferrazzi
2017-12-08 14:48 Mike Pagano
2017-12-07 18:53 Mike Pagano
2017-10-18 11:51 Mike Pagano
2017-09-13 19:38 Mike Pagano
2017-08-06 18:01 Mike Pagano
2017-04-14 19:17 Mike Pagano
2017-03-14 11:39 Mike Pagano
2017-03-02 16:31 Mike Pagano
2017-03-02 16:31 Mike Pagano
2017-02-24 16:11 Mike Pagano
2017-01-18 23:50 Alice Ferrazzi
2017-01-10 4:02 Alice Ferrazzi
2016-12-08 0:43 Mike Pagano
2016-11-30 11:45 Mike Pagano
2016-11-23 11:25 Mike Pagano
2016-10-28 10:19 Mike Pagano
2016-10-12 19:52 Mike Pagano
2016-09-18 12:47 Mike Pagano
2016-08-22 23:29 Mike Pagano
2016-08-10 12:55 Mike Pagano
2016-07-31 16:01 Mike Pagano
2016-07-15 14:18 Mike Pagano
2016-07-13 23:38 Mike Pagano
2016-07-02 15:31 Mike Pagano
2016-07-01 19:56 Mike Pagano
2016-06-23 11:45 Mike Pagano
2016-06-08 11:17 Mike Pagano
2016-05-24 12:39 Mike Pagano
2016-05-12 0:12 Mike Pagano
2016-04-28 18:56 Mike Pagano
2016-04-22 18:06 Mike Pagano
2016-04-20 11:23 Mike Pagano
2016-04-06 11:23 Mike Pagano
2016-03-22 22:47 Mike Pagano
2016-03-17 22:52 Mike Pagano
2016-03-05 23:38 Mike Pagano
2016-02-16 15:28 Mike Pagano
2016-01-31 23:29 Mike Pagano
2016-01-23 18:30 Mike Pagano
2016-01-20 13:54 Mike Pagano
2015-12-15 11:17 Mike Pagano
2015-12-10 13:54 Mike Pagano
2015-11-10 0:30 Mike Pagano
2015-11-05 23:29 Mike Pagano
2015-11-05 23:29 Mike Pagano
2015-10-27 13:19 Mike Pagano
2015-10-26 20:51 Mike Pagano
2015-10-26 20:49 Mike Pagano
2015-10-03 16:07 Mike Pagano
2015-10-02 12:08 Mike Pagano
2015-09-29 17:50 Mike Pagano
2015-09-28 23:57 Mike Pagano
2015-09-21 22:16 Mike Pagano
2015-09-14 15:20 Mike Pagano
2015-08-17 15:38 Mike Pagano
2015-08-10 23:42 Mike Pagano
2015-08-03 19:01 Mike Pagano
2015-07-22 10:31 Mike Pagano
2015-07-22 10:09 Mike Pagano
2015-07-19 18:55 Mike Pagano
2015-07-17 15:24 Mike Pagano
2015-07-10 23:47 Mike Pagano
2015-07-01 15:33 Mike Pagano
2015-06-27 19:50 Mike Pagano
2015-06-26 22:36 Mike Pagano
2015-06-20 17:37 Mike Pagano
2015-06-08 17:59 Mike Pagano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1439389049.bf5ec0ef3757347790f7c0269c3a657e2d1fdd2b.mpagano@gentoo \
--to=mpagano@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox