summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2015-06-27 15:50:31 -0400
committerMike Pagano <mpagano@gentoo.org>2015-06-27 15:50:31 -0400
commit45ecdfc0d977755e3f15ba10a6b4fdb93581357b (patch)
treefa4a7d9cd282593daa1d05e948e934fb71ee3971
parentAdd the kernel-level IPC implementation kdbus as an optional patch. (diff)
downloadlinux-patches-45ecdfc0d977755e3f15ba10a6b4fdb93581357b.tar.gz
linux-patches-45ecdfc0d977755e3f15ba10a6b4fdb93581357b.tar.bz2
linux-patches-45ecdfc0d977755e3f15ba10a6b4fdb93581357b.zip
Update kdbus patch, rename for clarity4.1-44.1-3
-rw-r--r--0000_README2
-rw-r--r--5015_kdbus-6-27-15.patch (renamed from 5015_kdbus-4.1-rc1.patch)1753
2 files changed, 498 insertions, 1257 deletions
diff --git a/0000_README b/0000_README
index d33ec2f1..dd82b403 100644
--- a/0000_README
+++ b/0000_README
@@ -83,6 +83,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-4.1-rc1.patch
+Patch: 5015_kdbus-6-27-15.patch
From: https://lkml.org
Desc: Kernel-level IPC implementation
diff --git a/5015_kdbus-4.1-rc1.patch b/5015_kdbus-6-27-15.patch
index a5169bd4..bc17abe7 100644
--- a/5015_kdbus-4.1-rc1.patch
+++ b/5015_kdbus-6-27-15.patch
@@ -1,15 +1,15 @@
diff --git a/Documentation/Makefile b/Documentation/Makefile
-index 6883a1b..5e3fde6 100644
+index bc05482..e2127a7 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,4 +1,4 @@
- subdir-y := accounting arm auxdisplay blackfin connector \
+ subdir-y := accounting auxdisplay blackfin connector \
- filesystems filesystems ia64 laptops mic misc-devices \
+ filesystems filesystems ia64 kdbus laptops mic misc-devices \
networking pcmcia prctl ptp spi timers vDSO video4linux \
watchdog
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
-index 8136e1f..54e091e 100644
+index 51f4221..ec7c81b 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -292,6 +292,7 @@ Code Seq#(hex) Include File Comments
@@ -2262,7 +2262,7 @@ index 0000000..8c2a90e
+</refentry>
diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml
new file mode 100644
-index 0000000..09f8b90
+index 0000000..ee09dfa
--- /dev/null
+++ b/Documentation/kdbus/kdbus.item.xml
@@ -0,0 +1,839 @@
@@ -2337,13 +2337,13 @@ index 0000000..09f8b90
+#define KDBUS_ALIGN8(val) (((val) + 7) & ~7)
+
+#define KDBUS_ITEM_NEXT(item) \
-+ (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
++ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
+
+#define KDBUS_ITEM_FOREACH(item, head, first) \
-+ for (item = (head)->first; \
++ for ((item) = (head)->first; \
+ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
+ ((uint8_t *)(item) >= (uint8_t *)(head)); \
-+ item = KDBUS_ITEM_NEXT(item))
++ (item) = KDBUS_ITEM_NEXT(item))
+ ]]></programlisting>
+ </refsect2>
+ </refsect1>
@@ -7450,10 +7450,10 @@ index 0000000..52565ea
+ </template>
+</stylesheet>
diff --git a/MAINTAINERS b/MAINTAINERS
-index 6239a30..e924246 100644
+index d8afd29..02f7668 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
-@@ -5503,6 +5503,19 @@ S: Maintained
+@@ -5585,6 +5585,19 @@ S: Maintained
F: Documentation/kbuild/kconfig-language.txt
F: scripts/kconfig/
@@ -7474,10 +7474,10 @@ index 6239a30..e924246 100644
M: Vivek Goyal <vgoyal@redhat.com>
M: Haren Myneni <hbabu@us.ibm.com>
diff --git a/Makefile b/Makefile
-index 1100ff3..08c9818 100644
+index f5c8983..a1c8d57 100644
--- a/Makefile
+++ b/Makefile
-@@ -1350,6 +1350,7 @@ $(help-board-dirs): help-%:
+@@ -1343,6 +1343,7 @@ $(help-board-dirs): help-%:
%docs: scripts_basic FORCE
$(Q)$(MAKE) $(build)=scripts build_docproc
$(Q)$(MAKE) $(build)=Documentation/DocBook $@
@@ -7486,10 +7486,10 @@ index 1100ff3..08c9818 100644
else # KBUILD_EXTMOD
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
-index 68ceb97..ddc413e 100644
+index 1a0006a..4842a98 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
-@@ -214,6 +214,7 @@ header-y += ixjuser.h
+@@ -215,6 +215,7 @@ header-y += ixjuser.h
header-y += jffs2.h
header-y += joystick.h
header-y += kcmp.h
@@ -8483,10 +8483,10 @@ index 0000000..00a6e14
+
+#endif /* _UAPI_KDBUS_H_ */
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
-index 7d664ea..1cf05c0 100644
+index 7b1425a..ce2ac5a 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
-@@ -74,4 +74,6 @@
+@@ -76,4 +76,6 @@
#define BTRFS_TEST_MAGIC 0x73727279
#define NSFS_MAGIC 0x6e736673
@@ -8494,7 +8494,7 @@ index 7d664ea..1cf05c0 100644
+
#endif /* __LINUX_MAGIC_H__ */
diff --git a/init/Kconfig b/init/Kconfig
-index f5dbc6d..6bda631 100644
+index dc24dec..9388071 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -261,6 +261,19 @@ config POSIX_MQUEUE_SYSCTL
@@ -8557,10 +8557,10 @@ index 0000000..7ee9271
+obj-$(CONFIG_KDBUS) += kdbus.o
diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c
new file mode 100644
-index 0000000..9d0679e
+index 0000000..bbdf0f2
--- /dev/null
+++ b/ipc/kdbus/bus.c
-@@ -0,0 +1,560 @@
+@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -8848,8 +8848,6 @@ index 0000000..9d0679e
+ continue;
+
+ if (conn_src) {
-+ u64 attach_flags;
-+
+ /*
+ * Anyone can send broadcasts, as they have no
+ * destination. But a receiver needs TALK access to
@@ -8858,19 +8856,12 @@ index 0000000..9d0679e
+ if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src))
+ continue;
+
-+ attach_flags = kdbus_meta_calc_attach_flags(conn_src,
-+ conn_dst);
-+
-+ /*
-+ * Keep sending messages even if we cannot acquire the
-+ * requested metadata. It's up to the receiver to drop
-+ * messages that lack expected metadata.
-+ */
-+ if (!conn_src->faked_meta)
-+ kdbus_meta_proc_collect(kmsg->proc_meta,
-+ attach_flags);
-+ kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
-+ attach_flags);
++ ret = kdbus_kmsg_collect_metadata(kmsg, conn_src,
++ conn_dst);
++ if (ret < 0) {
++ kdbus_conn_lost_message(conn_dst);
++ continue;
++ }
+ } else {
+ /*
+ * Check if there is a policy db that prevents the
@@ -8916,22 +8907,13 @@ index 0000000..9d0679e
+
+ down_read(&bus->conn_rwlock);
+ list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) {
-+ /*
-+ * Collect metadata requested by the destination connection.
-+ * Ignore errors, as receivers need to check metadata
-+ * availability, anyway. So it's still better to send messages
-+ * that lack data, than to skip it entirely.
-+ */
+ if (conn_src) {
-+ u64 attach_flags;
-+
-+ attach_flags = kdbus_meta_calc_attach_flags(conn_src,
-+ conn_dst);
-+ if (!conn_src->faked_meta)
-+ kdbus_meta_proc_collect(kmsg->proc_meta,
-+ attach_flags);
-+ kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
-+ attach_flags);
++ ret = kdbus_kmsg_collect_metadata(kmsg, conn_src,
++ conn_dst);
++ if (ret < 0) {
++ kdbus_conn_lost_message(conn_dst);
++ continue;
++ }
+ }
+
+ ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL);
@@ -8946,7 +8928,7 @@ index 0000000..9d0679e
+ * @domain: domain to operate on
+ * @argp: command payload
+ *
-+ * Return: Newly created bus on success, ERR_PTR on failure.
++ * Return: NULL or newly created bus on success, ERR_PTR on failure.
+ */
+struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain,
+ void __user *argp)
@@ -9040,7 +9022,7 @@ index 0000000..9d0679e
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp)
+{
@@ -9230,10 +9212,10 @@ index 0000000..5bea5ef
+#endif
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
new file mode 100644
-index 0000000..ab476fa
+index 0000000..9993753
--- /dev/null
+++ b/ipc/kdbus/connection.c
-@@ -0,0 +1,2214 @@
+@@ -0,0 +1,2178 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -9668,7 +9650,7 @@ index 0000000..ab476fa
+ * directly, and won't cause any notifications.
+ */
+ if (!kdbus_conn_is_monitor(conn)) {
-+ ret = kdbus_notify_id_change(conn->ep->bus, KDBUS_ITEM_ID_ADD,
++ ret = kdbus_notify_id_change(bus, KDBUS_ITEM_ID_ADD,
+ conn->id, conn->flags);
+ if (ret < 0)
+ goto exit_disconnect;
@@ -9795,17 +9777,16 @@ index 0000000..ab476fa
+ hash_for_each(bus->conn_hash, i, c, hentry) {
+ mutex_lock(&c->lock);
+ list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) {
-+ if (r->reply_src == conn) {
-+ if (r->sync) {
-+ kdbus_sync_reply_wakeup(r, -EPIPE);
-+ kdbus_reply_unlink(r);
-+ continue;
-+ }
++ if (r->reply_src != conn)
++ continue;
+
++ if (r->sync)
++ kdbus_sync_reply_wakeup(r, -EPIPE);
++ else
+ /* send a 'connection dead' notification */
+ kdbus_notify_reply_dead(bus, c->id, r->cookie);
-+ kdbus_reply_unlink(r);
-+ }
++
++ kdbus_reply_unlink(r);
+ }
+ mutex_unlock(&c->lock);
+ }
@@ -9989,7 +9970,7 @@ index 0000000..ab476fa
+ *
+ * kdbus is reliable. That means, we try hard to never lose messages. However,
+ * memory is limited, so we cannot rely on transmissions to never fail.
-+ * Therefore, we use quota-limits to let callers know if there unicast message
++ * Therefore, we use quota-limits to let callers know if their unicast message
+ * cannot be transmitted to a peer. This works fine for unicasts, but for
+ * broadcasts we cannot make the caller handle the transmission failure.
+ * Instead, we must let the destination know that it couldn't receive a
@@ -10011,8 +9992,6 @@ index 0000000..ab476fa
+ const struct kdbus_kmsg *kmsg,
+ struct kdbus_user *user)
+{
-+ struct kdbus_queue_entry *entry;
-+
+ /* The remote connection was disconnected */
+ if (!kdbus_conn_active(conn_dst))
+ return ERR_PTR(-ECONNRESET);
@@ -10029,11 +10008,7 @@ index 0000000..ab476fa
+ kmsg->res && kmsg->res->fds_count > 0)
+ return ERR_PTR(-ECOMM);
+
-+ entry = kdbus_queue_entry_new(conn_dst, kmsg, user);
-+ if (IS_ERR(entry))
-+ return entry;
-+
-+ return entry;
++ return kdbus_queue_entry_new(conn_dst, kmsg, user);
+}
+
+/*
@@ -10334,7 +10309,6 @@ index 0000000..ab476fa
+ struct kdbus_reply *reply, *wake = NULL;
+ struct kdbus_conn *dst = NULL;
+ struct kdbus_bus *bus = src->ep->bus;
-+ u64 attach;
+ int ret;
+
+ if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) ||
@@ -10367,15 +10341,7 @@ index 0000000..ab476fa
+
+ /* attach metadata */
+
-+ attach = kdbus_meta_calc_attach_flags(src, dst);
-+
-+ if (!src->faked_meta) {
-+ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
-+ if (ret < 0)
-+ goto exit;
-+ }
-+
-+ ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
++ ret = kdbus_kmsg_collect_metadata(kmsg, src, dst);
+ if (ret < 0)
+ goto exit;
+
@@ -10403,7 +10369,6 @@ index 0000000..ab476fa
+ struct kdbus_reply *wait = NULL;
+ struct kdbus_conn *dst = NULL;
+ struct kdbus_bus *bus = src->ep->bus;
-+ u64 attach;
+ int ret;
+
+ if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) ||
@@ -10454,15 +10419,7 @@ index 0000000..ab476fa
+
+ /* attach metadata */
+
-+ attach = kdbus_meta_calc_attach_flags(src, dst);
-+
-+ if (!src->faked_meta) {
-+ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
-+ if (ret < 0)
-+ goto exit;
-+ }
-+
-+ ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
++ ret = kdbus_kmsg_collect_metadata(kmsg, src, dst);
+ if (ret < 0)
+ goto exit;
+
@@ -10493,7 +10450,6 @@ index 0000000..ab476fa
+ struct kdbus_conn *dst = NULL;
+ struct kdbus_bus *bus = src->ep->bus;
+ bool is_signal = (kmsg->msg.flags & KDBUS_MSG_SIGNAL);
-+ u64 attach;
+ int ret = 0;
+
+ if (WARN_ON(kmsg->msg.dst_id == KDBUS_DST_ID_BROADCAST) ||
@@ -10532,16 +10488,8 @@ index 0000000..ab476fa
+
+ /* attach metadata */
+
-+ attach = kdbus_meta_calc_attach_flags(src, dst);
-+
-+ if (!src->faked_meta) {
-+ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
-+ if (ret < 0 && !is_signal)
-+ goto exit;
-+ }
-+
-+ ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
-+ if (ret < 0 && !is_signal)
++ ret = kdbus_kmsg_collect_metadata(kmsg, src, dst);
++ if (ret < 0)
+ goto exit;
+
+ /* send message */
@@ -10824,10 +10772,8 @@ index 0000000..ab476fa
+ * to a peer if, and only if, that peer can see the name this
+ * notification is for.
+ *
-+ * KDBUS_ITEM_ID_{ADD,REMOVE}: As new peers cannot have names, and all
-+ * names are dropped before a peer is removed, those notifications
-+ * cannot be seen on custom endpoints. Thus, we only pass them
-+ * through on default endpoints.
++ * KDBUS_ITEM_ID_{ADD,REMOVE}: Notifications for ID changes are
++ * broadcast to everyone, to allow tracking peers.
+ */
+
+ switch (kmsg->notify_type) {
@@ -10839,7 +10785,7 @@ index 0000000..ab476fa
+
+ case KDBUS_ITEM_ID_ADD:
+ case KDBUS_ITEM_ID_REMOVE:
-+ return !conn->ep->user;
++ return true;
+
+ default:
+ WARN(1, "Invalid type for notification broadcast: %llu\n",
@@ -10854,7 +10800,7 @@ index 0000000..ab476fa
+ * @privileged: Whether the caller is privileged
+ * @argp: Command payload
+ *
-+ * Return: Newly created connection on success, ERR_PTR on failure.
++ * Return: NULL or newly created connection on success, ERR_PTR on failure.
+ */
+struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, bool privileged,
+ void __user *argp)
@@ -10941,7 +10887,7 @@ index 0000000..ab476fa
+ *
+ * The caller must not hold any active reference to @conn or this will deadlock.
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp)
+{
@@ -10973,7 +10919,7 @@ index 0000000..ab476fa
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
+{
@@ -11103,7 +11049,7 @@ index 0000000..ab476fa
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp)
+{
@@ -11200,7 +11146,7 @@ index 0000000..ab476fa
+ * @f: file this command was called on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp)
+{
@@ -11296,7 +11242,7 @@ index 0000000..ab476fa
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp)
+{
@@ -11419,7 +11365,7 @@ index 0000000..ab476fa
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp)
+{
@@ -12098,7 +12044,7 @@ index 0000000..447a2bd
+#endif
diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c
new file mode 100644
-index 0000000..174d274
+index 0000000..9a95a5e
--- /dev/null
+++ b/ipc/kdbus/endpoint.c
@@ -0,0 +1,275 @@
@@ -12292,7 +12238,7 @@ index 0000000..174d274
+ * @bus: bus to operate on
+ * @argp: command payload
+ *
-+ * Return: Newly created endpoint on success, ERR_PTR on failure.
++ * Return: NULL or newly created endpoint on success, ERR_PTR on failure.
+ */
+struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp)
+{
@@ -12351,7 +12297,7 @@ index 0000000..174d274
+ * @ep: endpoint to operate on
+ * @argp: command payload
+ *
-+ * Return: Newly created endpoint on success, ERR_PTR on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp)
+{
@@ -13002,10 +12948,10 @@ index 0000000..62f7d6a
+#endif
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
new file mode 100644
-index 0000000..f72dbe5
+index 0000000..0752799
--- /dev/null
+++ b/ipc/kdbus/handle.c
-@@ -0,0 +1,617 @@
+@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -13026,6 +12972,7 @@ index 0000000..f72dbe5
+#include <linux/init.h>
+#include <linux/kdev_t.h>
+#include <linux/module.h>
++#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/rwsem.h>
+#include <linux/sched.h>
@@ -13079,10 +13026,6 @@ index 0000000..f72dbe5
+ if (!KDBUS_ITEMS_END(item, args->items, args->items_size))
+ return -EINVAL;
+
-+ for (i = 0; i < args->argc; ++i)
-+ if (args->argv[i].mandatory && !args->argv[i].item)
-+ return -EINVAL;
-+
+ return 0;
+}
+
@@ -13157,11 +13100,32 @@ index 0000000..f72dbe5
+int __kdbus_args_parse(struct kdbus_args *args, void __user *argp,
+ size_t type_size, size_t items_offset, void **out)
+{
-+ int ret;
++ u64 user_size;
++ int ret, i;
++
++ ret = kdbus_copy_from_user(&user_size, argp, sizeof(user_size));
++ if (ret < 0)
++ return ret;
++
++ if (user_size < type_size)
++ return -EINVAL;
++ if (user_size > KDBUS_CMD_MAX_SIZE)
++ return -EMSGSIZE;
++
++ if (user_size <= sizeof(args->cmd_buf)) {
++ if (copy_from_user(args->cmd_buf, argp, user_size))
++ return -EFAULT;
++ args->cmd = (void*)args->cmd_buf;
++ } else {
++ args->cmd = memdup_user(argp, user_size);
++ if (IS_ERR(args->cmd))
++ return PTR_ERR(args->cmd);
++ }
+
-+ args->cmd = kdbus_memdup_user(argp, type_size, KDBUS_CMD_MAX_SIZE);
-+ if (IS_ERR(args->cmd))
-+ return PTR_ERR(args->cmd);
++ if (args->cmd->size != user_size) {
++ ret = -EINVAL;
++ goto error;
++ }
+
+ args->cmd->return_flags = 0;
+ args->user = argp;
@@ -13181,6 +13145,15 @@ index 0000000..f72dbe5
+ if (ret < 0)
+ goto error;
+
++ /* mandatory items must be given (but not on negotiation) */
++ if (!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE)) {
++ for (i = 0; i < args->argc; ++i)
++ if (args->argv[i].mandatory && !args->argv[i].item) {
++ ret = -EINVAL;
++ goto error;
++ }
++ }
++
+ *out = args->cmd;
+ return !!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE);
+
@@ -13209,7 +13182,8 @@ index 0000000..f72dbe5
+ if (put_user(args->cmd->return_flags,
+ &args->user->return_flags))
+ ret = -EFAULT;
-+ kfree(args->cmd);
++ if (args->cmd != (void*)args->cmd_buf)
++ kfree(args->cmd);
+ args->cmd = NULL;
+ }
+
@@ -13232,7 +13206,7 @@ index 0000000..f72dbe5
+
+/**
+ * struct kdbus_handle - handle to the kdbus system
-+ * @rwlock: handle lock
++ * @lock: handle lock
+ * @type: type of this handle (KDBUS_HANDLE_*)
+ * @bus_owner: bus this handle owns
+ * @ep_owner: endpoint this handle owns
@@ -13240,7 +13214,7 @@ index 0000000..f72dbe5
+ * @privileged: Flag to mark a handle as privileged
+ */
+struct kdbus_handle {
-+ struct rw_semaphore rwlock;
++ struct mutex lock;
+
+ enum kdbus_handle_type type;
+ union {
@@ -13268,7 +13242,7 @@ index 0000000..f72dbe5
+ goto exit;
+ }
+
-+ init_rwsem(&handle->rwlock);
++ mutex_init(&handle->lock);
+ handle->type = KDBUS_HANDLE_NONE;
+
+ if (node->type == KDBUS_NODE_ENDPOINT) {
@@ -13358,8 +13332,8 @@ index 0000000..f72dbe5
+ break;
+ }
+
-+ handle->type = KDBUS_HANDLE_BUS_OWNER;
+ handle->bus_owner = bus;
++ ret = KDBUS_HANDLE_BUS_OWNER;
+ break;
+ }
+
@@ -13399,8 +13373,8 @@ index 0000000..f72dbe5
+ break;
+ }
+
-+ handle->type = KDBUS_HANDLE_EP_OWNER;
+ handle->ep_owner = ep;
++ ret = KDBUS_HANDLE_EP_OWNER;
+ break;
+
+ case KDBUS_CMD_HELLO:
@@ -13410,8 +13384,8 @@ index 0000000..f72dbe5
+ break;
+ }
+
-+ handle->type = KDBUS_HANDLE_CONNECTED;
+ handle->conn = conn;
++ ret = KDBUS_HANDLE_CONNECTED;
+ break;
+
+ default:
@@ -13525,19 +13499,41 @@ index 0000000..f72dbe5
+ case KDBUS_CMD_BUS_MAKE:
+ case KDBUS_CMD_ENDPOINT_MAKE:
+ case KDBUS_CMD_HELLO:
-+ /* bail out early if already typed */
-+ if (handle->type != KDBUS_HANDLE_NONE)
-+ break;
-+
-+ down_write(&handle->rwlock);
++ mutex_lock(&handle->lock);
+ if (handle->type == KDBUS_HANDLE_NONE) {
+ if (node->type == KDBUS_NODE_CONTROL)
+ ret = kdbus_handle_ioctl_control(file, cmd,
+ argp);
+ else if (node->type == KDBUS_NODE_ENDPOINT)
+ ret = kdbus_handle_ioctl_ep(file, cmd, argp);
++
++ if (ret > 0) {
++ /*
++ * The data given via open() is not sufficient
++ * to setup a kdbus handle. Hence, we require
++ * the user to perform a setup ioctl. This setup
++ * can only be performed once and defines the
++ * type of the handle. The different setup
++ * ioctls are locked against each other so they
++ * cannot race. Once the handle type is set,
++ * the type-dependent ioctls are enabled. To
++ * improve performance, we don't lock those via
++ * handle->lock. Instead, we issue a
++ * write-barrier before performing the
++ * type-change, which pairs with smp_rmb() in
++ * all handlers that access the type field. This
++ * guarantees the handle is fully setup, if
++ * handle->type is set. If handle->type is
++ * unset, you must not make any assumptions
++ * without taking handle->lock.
++ * Note that handle->type is only set once. It
++ * will never change afterwards.
++ */
++ smp_wmb();
++ handle->type = ret;
++ }
+ }
-+ up_write(&handle->rwlock);
++ mutex_unlock(&handle->lock);
+ break;
+
+ case KDBUS_CMD_ENDPOINT_UPDATE:
@@ -13552,14 +13548,30 @@ index 0000000..f72dbe5
+ case KDBUS_CMD_MATCH_REMOVE:
+ case KDBUS_CMD_SEND:
+ case KDBUS_CMD_RECV:
-+ case KDBUS_CMD_FREE:
-+ down_read(&handle->rwlock);
-+ if (handle->type == KDBUS_HANDLE_EP_OWNER)
++ case KDBUS_CMD_FREE: {
++ enum kdbus_handle_type type;
++
++ /*
++ * This read-barrier pairs with smp_wmb() of the handle setup.
++ * it guarantees the handle is fully written, in case the
++ * type has been set. It allows us to access the handle without
++ * taking handle->lock, given the guarantee that the type is
++ * only ever set once, and stays constant afterwards.
++ * Furthermore, the handle object itself is not modified in any
++ * way after the type is set. That is, the type-field is the
++ * last field that is written on any handle. If it has not been
++ * set, we must not access the handle here.
++ */
++ type = handle->type;
++ smp_rmb();
++
++ if (type == KDBUS_HANDLE_EP_OWNER)
+ ret = kdbus_handle_ioctl_ep_owner(file, cmd, argp);
-+ else if (handle->type == KDBUS_HANDLE_CONNECTED)
++ else if (type == KDBUS_HANDLE_CONNECTED)
+ ret = kdbus_handle_ioctl_connected(file, cmd, argp);
-+ up_read(&handle->rwlock);
++
+ break;
++ }
+ default:
+ ret = -ENOTTY;
+ break;
@@ -13572,42 +13584,61 @@ index 0000000..f72dbe5
+ struct poll_table_struct *wait)
+{
+ struct kdbus_handle *handle = file->private_data;
++ enum kdbus_handle_type type;
+ unsigned int mask = POLLOUT | POLLWRNORM;
-+ int ret;
+
-+ /* Only a connected endpoint can read/write data */
-+ down_read(&handle->rwlock);
-+ if (handle->type != KDBUS_HANDLE_CONNECTED) {
-+ up_read(&handle->rwlock);
-+ return POLLERR | POLLHUP;
-+ }
-+ up_read(&handle->rwlock);
++ /*
++ * This pairs with smp_wmb() during handle setup. It guarantees that
++ * _iff_ the handle type is set, handle->conn is valid. Furthermore,
++ * _iff_ the type is set, the handle object is constant and never
++ * changed again. If it's not set, we must not access the handle but
++ * bail out. We also must assume no setup has taken place, yet.
++ */
++ type = handle->type;
++ smp_rmb();
+
-+ ret = kdbus_conn_acquire(handle->conn);
-+ if (ret < 0)
++ /* Only a connected endpoint can read/write data */
++ if (type != KDBUS_HANDLE_CONNECTED)
+ return POLLERR | POLLHUP;
+
+ poll_wait(file, &handle->conn->wait, wait);
+
++ /*
++ * Verify the connection hasn't been deactivated _after_ adding the
++ * wait-queue. This guarantees, that if the connection is deactivated
++ * after we checked it, the waitqueue is signaled and we're called
++ * again.
++ */
++ if (!kdbus_conn_active(handle->conn))
++ return POLLERR | POLLHUP;
++
+ if (!list_empty(&handle->conn->queue.msg_list) ||
+ atomic_read(&handle->conn->lost_count) > 0)
+ mask |= POLLIN | POLLRDNORM;
+
-+ kdbus_conn_release(handle->conn);
-+
+ return mask;
+}
+
+static int kdbus_handle_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct kdbus_handle *handle = file->private_data;
++ enum kdbus_handle_type type;
+ int ret = -EBADFD;
+
-+ if (down_read_trylock(&handle->rwlock)) {
-+ if (handle->type == KDBUS_HANDLE_CONNECTED)
-+ ret = kdbus_pool_mmap(handle->conn->pool, vma);
-+ up_read(&handle->rwlock);
-+ }
++ /*
++ * This pairs with smp_wmb() during handle setup. It guarantees that
++ * _iff_ the handle type is set, handle->conn is valid. Furthermore,
++ * _iff_ the type is set, the handle object is constant and never
++ * changed again. If it's not set, we must not access the handle but
++ * bail out. We also must assume no setup has taken place, yet.
++ */
++ type = handle->type;
++ smp_rmb();
++
++ /* Only connected handles have a pool we can map */
++ if (type == KDBUS_HANDLE_CONNECTED)
++ ret = kdbus_pool_mmap(handle->conn->pool, vma);
++
+ return ret;
+}
+
@@ -13625,10 +13656,10 @@ index 0000000..f72dbe5
+};
diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h
new file mode 100644
-index 0000000..93a372d
+index 0000000..13c59d9
--- /dev/null
+++ b/ipc/kdbus/handle.h
-@@ -0,0 +1,85 @@
+@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -13676,6 +13707,7 @@ index 0000000..93a372d
+ * @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
+ * @items: points to item array in @cmd
+ * @items_size: size of @items in bytes
+ *
@@ -13683,6 +13715,9 @@ index 0000000..93a372d
+ * The ioctl handler has to pre-fill the flags and allowed items before passing
+ * 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
++ * stack on syscall entrance.
+ */
+struct kdbus_args {
+ u64 allowed_flags;
@@ -13691,6 +13726,7 @@ index 0000000..93a372d
+
+ struct kdbus_cmd __user *user;
+ struct kdbus_cmd *cmd;
++ u8 cmd_buf[512];
+
+ struct kdbus_item *items;
+ size_t items_size;
@@ -13716,10 +13752,10 @@ index 0000000..93a372d
+#endif
diff --git a/ipc/kdbus/item.c b/ipc/kdbus/item.c
new file mode 100644
-index 0000000..745ad54
+index 0000000..1ee72c2
--- /dev/null
+++ b/ipc/kdbus/item.c
-@@ -0,0 +1,339 @@
+@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -13818,12 +13854,6 @@ index 0000000..745ad54
+ break;
+
+ case KDBUS_ITEM_PAYLOAD_VEC:
-+ if (payload_size != sizeof(struct kdbus_vec))
-+ return -EINVAL;
-+ if (item->vec.size == 0 || item->vec.size > SIZE_MAX)
-+ return -EINVAL;
-+ break;
-+
+ case KDBUS_ITEM_PAYLOAD_OFF:
+ if (payload_size != sizeof(struct kdbus_vec))
+ return -EINVAL;
@@ -14061,7 +14091,7 @@ index 0000000..745ad54
+}
diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h
new file mode 100644
-index 0000000..eeefd8b
+index 0000000..bca63b4
--- /dev/null
+++ b/ipc/kdbus/item.h
@@ -0,0 +1,64 @@
@@ -14088,17 +14118,17 @@ index 0000000..eeefd8b
+#include "util.h"
+
+/* generic access and iterators over a stream of items */
-+#define KDBUS_ITEM_NEXT(_i) (typeof(_i))(((u8 *)_i) + KDBUS_ALIGN8((_i)->size))
-+#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*_h), _is))
++#define KDBUS_ITEM_NEXT(_i) (typeof(_i))((u8 *)(_i) + KDBUS_ALIGN8((_i)->size))
++#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*(_h)), _is))
+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
+#define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s))
+#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE)
+
+#define KDBUS_ITEMS_FOREACH(_i, _is, _s) \
-+ for (_i = _is; \
++ for ((_i) = (_is); \
+ ((u8 *)(_i) < (u8 *)(_is) + (_s)) && \
+ ((u8 *)(_i) >= (u8 *)(_is)); \
-+ _i = KDBUS_ITEM_NEXT(_i))
++ (_i) = KDBUS_ITEM_NEXT(_i))
+
+#define KDBUS_ITEM_VALID(_i, _is, _s) \
+ ((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \
@@ -14107,7 +14137,7 @@ index 0000000..eeefd8b
+ (u8 *)(_i) >= (u8 *)(_is))
+
+#define KDBUS_ITEMS_END(_i, _is, _s) \
-+ ((u8 *)_i == ((u8 *)(_is) + KDBUS_ALIGN8(_s)))
++ ((u8 *)(_i) == ((u8 *)(_is) + KDBUS_ALIGN8(_s)))
+
+/**
+ * struct kdbus_item_header - Describes the fix part of an item
@@ -14201,10 +14231,10 @@ index 0000000..6450f58
+#endif
diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c
new file mode 100644
-index 0000000..785f529
+index 0000000..1ad4dc8
--- /dev/null
+++ b/ipc/kdbus/main.c
-@@ -0,0 +1,125 @@
+@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -14222,7 +14252,6 @@ index 0000000..785f529
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
-+#include <linux/moduleparam.h>
+
+#include "util.h"
+#include "fs.h"
@@ -14286,17 +14315,6 @@ index 0000000..785f529
+/* kdbus mount-point /sys/fs/kdbus */
+static struct kobject *kdbus_dir;
+
-+/* global module option to apply a mask to exported metadata */
-+unsigned long long kdbus_meta_attach_mask = KDBUS_ATTACH_TIMESTAMP |
-+ KDBUS_ATTACH_CREDS |
-+ KDBUS_ATTACH_PIDS |
-+ KDBUS_ATTACH_AUXGROUPS |
-+ KDBUS_ATTACH_NAMES |
-+ KDBUS_ATTACH_SECLABEL |
-+ KDBUS_ATTACH_CONN_DESCRIPTION;
-+MODULE_PARM_DESC(attach_flags_mask, "Attach-flags mask for exported metadata");
-+module_param_named(attach_flags_mask, kdbus_meta_attach_mask, ullong, 0644);
-+
+static int __init kdbus_init(void)
+{
+ int ret;
@@ -14323,6 +14341,7 @@ index 0000000..785f529
+{
+ kdbus_fs_exit();
+ kobject_put(kdbus_dir);
++ ida_destroy(&kdbus_node_ida);
+}
+
+module_init(kdbus_init);
@@ -14332,7 +14351,7 @@ index 0000000..785f529
+MODULE_ALIAS_FS(KBUILD_MODNAME "fs");
diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c
new file mode 100644
-index 0000000..30cec1c
+index 0000000..cc083b4
--- /dev/null
+++ b/ipc/kdbus/match.c
@@ -0,0 +1,559 @@
@@ -14706,7 +14725,7 @@ index 0000000..30cec1c
+ * are used to match messages from userspace, while the others apply to
+ * kernel-generated notifications.
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp)
+{
@@ -14866,7 +14885,7 @@ index 0000000..30cec1c
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp)
+{
@@ -14938,10 +14957,10 @@ index 0000000..ea42929
+#endif
diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c
new file mode 100644
-index 0000000..8096075
+index 0000000..066e816
--- /dev/null
+++ b/ipc/kdbus/message.c
-@@ -0,0 +1,616 @@
+@@ -0,0 +1,640 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -15558,12 +15577,36 @@ index 0000000..8096075
+ kdbus_kmsg_free(m);
+ return ERR_PTR(ret);
+}
++
++/**
++ * kdbus_kmsg_collect_metadata() - collect metadata
++ * @kmsg: message to collect metadata on
++ * @src: source connection of message
++ * @dst: destination connection of message
++ *
++ * Return: 0 on success, negative error code on failure.
++ */
++int kdbus_kmsg_collect_metadata(struct kdbus_kmsg *kmsg, struct kdbus_conn *src,
++ struct kdbus_conn *dst)
++{
++ u64 attach;
++ int ret;
++
++ attach = kdbus_meta_calc_attach_flags(src, dst);
++ if (!src->faked_meta) {
++ ret = kdbus_meta_proc_collect(kmsg->proc_meta, attach);
++ if (ret < 0)
++ return ret;
++ }
++
++ return kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, src, attach);
++}
diff --git a/ipc/kdbus/message.h b/ipc/kdbus/message.h
new file mode 100644
-index 0000000..af47758
+index 0000000..cdaa65c
--- /dev/null
+++ b/ipc/kdbus/message.h
-@@ -0,0 +1,133 @@
+@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -15695,14 +15738,16 @@ index 0000000..af47758
+struct kdbus_kmsg *kdbus_kmsg_new_from_cmd(struct kdbus_conn *conn,
+ struct kdbus_cmd_send *cmd_send);
+void kdbus_kmsg_free(struct kdbus_kmsg *kmsg);
++int kdbus_kmsg_collect_metadata(struct kdbus_kmsg *kmsg, struct kdbus_conn *src,
++ struct kdbus_conn *dst);
+
+#endif
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
new file mode 100644
-index 0000000..3adc6c2
+index 0000000..c36b9cc
--- /dev/null
+++ b/ipc/kdbus/metadata.c
-@@ -0,0 +1,1159 @@
+@@ -0,0 +1,1184 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -15734,7 +15779,6 @@ index 0000000..3adc6c2
+#include <linux/uidgid.h>
+#include <linux/uio.h>
+#include <linux/user_namespace.h>
-+#include <linux/version.h>
+
+#include "bus.h"
+#include "connection.h"
@@ -15769,8 +15813,7 @@ index 0000000..3adc6c2
+ * @root_path: Root-FS path
+ * @cmdline: Command-line
+ * @cgroup: Full cgroup path
-+ * @caps: Capabilities
-+ * @caps_namespace: User-namespace of @caps
++ * @cred: Credentials
+ * @seclabel: Seclabel
+ * @audit_loginuid: Audit login-UID
+ * @audit_sessionid: Audit session-ID
@@ -15810,14 +15853,7 @@ index 0000000..3adc6c2
+ char *cgroup;
+
+ /* KDBUS_ITEM_CAPS */
-+ struct caps {
-+ /* binary compatible to kdbus_caps */
-+ u32 last_cap;
-+ struct {
-+ u32 caps[_KERNEL_CAPABILITY_U32S];
-+ } set[4];
-+ } caps;
-+ struct user_namespace *caps_namespace;
++ const struct cred *cred;
+
+ /* KDBUS_ITEM_SECLABEL */
+ char *seclabel;
@@ -15855,6 +15891,14 @@ index 0000000..3adc6c2
+ char *conn_description;
+};
+
++/* fixed size equivalent of "kdbus_caps" */
++struct kdbus_meta_caps {
++ u32 last_cap;
++ struct {
++ u32 caps[_KERNEL_CAPABILITY_U32S];
++ } set[4];
++};
++
+/**
+ * kdbus_meta_proc_new() - Create process metadata object
+ *
@@ -15881,7 +15925,8 @@ index 0000000..3adc6c2
+
+ path_put(&mp->exe_path);
+ path_put(&mp->root_path);
-+ put_user_ns(mp->caps_namespace);
++ if (mp->cred)
++ put_cred(mp->cred);
+ put_pid(mp->ppid);
+ put_pid(mp->tgid);
+ put_pid(mp->pid);
@@ -15951,25 +15996,23 @@ index 0000000..3adc6c2
+
+static int kdbus_meta_proc_collect_auxgroups(struct kdbus_meta_proc *mp)
+{
-+ struct group_info *info;
++ const struct group_info *info;
+ size_t i;
+
-+ info = get_current_groups();
++ /* no need to lock/ref, current creds cannot change */
++ info = current_cred()->group_info;
+
+ if (info->ngroups > 0) {
+ mp->auxgrps = kmalloc_array(info->ngroups, sizeof(kgid_t),
+ GFP_KERNEL);
-+ if (!mp->auxgrps) {
-+ put_group_info(info);
++ if (!mp->auxgrps)
+ return -ENOMEM;
-+ }
+
+ for (i = 0; i < info->ngroups; i++)
+ mp->auxgrps[i] = GROUP_AT(info, i);
+ }
+
+ mp->n_auxgrps = info->ngroups;
-+ put_group_info(info);
+ mp->valid |= KDBUS_ATTACH_AUXGROUPS;
+
+ return 0;
@@ -15989,42 +16032,29 @@ index 0000000..3adc6c2
+
+static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp)
+{
-+ struct mm_struct *mm;
-+
-+ mm = get_task_mm(current);
-+ if (!mm)
-+ return;
++ struct file *exe_file;
+
-+ down_read(&mm->mmap_sem);
-+ if (mm->exe_file) {
-+ mp->exe_path = mm->exe_file->f_path;
++ rcu_read_lock();
++ exe_file = rcu_dereference(current->mm->exe_file);
++ if (exe_file) {
++ mp->exe_path = exe_file->f_path;
+ path_get(&mp->exe_path);
+ get_fs_root(current->fs, &mp->root_path);
+ mp->valid |= KDBUS_ATTACH_EXE;
+ }
-+ up_read(&mm->mmap_sem);
-+
-+ mmput(mm);
++ rcu_read_unlock();
+}
+
+static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp)
+{
-+ struct mm_struct *mm;
++ struct mm_struct *mm = current->mm;
+ char *cmdline;
+
-+ mm = get_task_mm(current);
-+ if (!mm)
++ if (!mm->arg_end)
+ return 0;
+
-+ if (!mm->arg_end) {
-+ mmput(mm);
-+ return 0;
-+ }
-+
+ cmdline = strndup_user((const char __user *)mm->arg_start,
+ mm->arg_end - mm->arg_start);
-+ mmput(mm);
-+
+ if (IS_ERR(cmdline))
+ return PTR_ERR(cmdline);
+
@@ -16062,25 +16092,7 @@ index 0000000..3adc6c2
+
+static void kdbus_meta_proc_collect_caps(struct kdbus_meta_proc *mp)
+{
-+ const struct cred *c = current_cred();
-+ int i;
-+
-+ /* ABI: "last_cap" equals /proc/sys/kernel/cap_last_cap */
-+ mp->caps.last_cap = CAP_LAST_CAP;
-+ mp->caps_namespace = get_user_ns(current_user_ns());
-+
-+ CAP_FOR_EACH_U32(i) {
-+ mp->caps.set[0].caps[i] = c->cap_inheritable.cap[i];
-+ mp->caps.set[1].caps[i] = c->cap_permitted.cap[i];
-+ mp->caps.set[2].caps[i] = c->cap_effective.cap[i];
-+ mp->caps.set[3].caps[i] = c->cap_bset.cap[i];
-+ }
-+
-+ /* clear unused bits */
-+ for (i = 0; i < 4; i++)
-+ mp->caps.set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
-+ CAP_LAST_U32_VALID_MASK;
-+
++ mp->cred = get_current_cred();
+ mp->valid |= KDBUS_ATTACH_CAPS;
+}
+
@@ -16543,7 +16555,6 @@ index 0000000..3adc6c2
+ }
+
+ *mask &= valid;
-+ *mask &= kdbus_meta_attach_mask;
+
+ if (!*mask)
+ goto exit;
@@ -16589,7 +16600,7 @@ index 0000000..3adc6c2
+ size += KDBUS_ITEM_SIZE(strlen(mp->cgroup) + 1);
+
+ if (mp && (*mask & KDBUS_ATTACH_CAPS))
-+ size += KDBUS_ITEM_SIZE(sizeof(mp->caps));
++ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_meta_caps));
+
+ if (mp && (*mask & KDBUS_ATTACH_SECLABEL))
+ size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1);
@@ -16626,6 +16637,69 @@ index 0000000..3adc6c2
+ return 2 + !!kdbus_kvec_pad(kvec++, size);
+}
+
++static void kdbus_meta_export_caps(struct kdbus_meta_caps *out,
++ struct kdbus_meta_proc *mp)
++{
++ struct user_namespace *iter;
++ const struct cred *cred = mp->cred;
++ bool parent = false, owner = false;
++ int i;
++
++ /*
++ * This translates the effective capabilities of 'cred' into the current
++ * user-namespace. If the current user-namespace is a child-namespace of
++ * the user-namespace of 'cred', the mask can be copied verbatim. If
++ * not, the mask is cleared.
++ * There's one exception: If 'cred' is the owner of any user-namespace
++ * in the path between the current user-namespace and the user-namespace
++ * of 'cred', then it has all effective capabilities set. This means,
++ * the user who created a user-namespace always has all effective
++ * capabilities in any child namespaces. Note that this is based on the
++ * uid of the namespace creator, not the task hierarchy.
++ */
++ for (iter = current_user_ns(); iter; iter = iter->parent) {
++ if (iter == cred->user_ns) {
++ parent = true;
++ break;
++ }
++
++ if (iter == &init_user_ns)
++ break;
++
++ if ((iter->parent == cred->user_ns) &&
++ uid_eq(iter->owner, cred->euid)) {
++ owner = true;
++ break;
++ }
++ }
++
++ out->last_cap = CAP_LAST_CAP;
++
++ CAP_FOR_EACH_U32(i) {
++ if (parent) {
++ out->set[0].caps[i] = cred->cap_inheritable.cap[i];
++ out->set[1].caps[i] = cred->cap_permitted.cap[i];
++ out->set[2].caps[i] = cred->cap_effective.cap[i];
++ out->set[3].caps[i] = cred->cap_bset.cap[i];
++ } else if (owner) {
++ out->set[0].caps[i] = 0U;
++ out->set[1].caps[i] = ~0U;
++ out->set[2].caps[i] = ~0U;
++ out->set[3].caps[i] = ~0U;
++ } else {
++ out->set[0].caps[i] = 0U;
++ out->set[1].caps[i] = 0U;
++ out->set[2].caps[i] = 0U;
++ out->set[3].caps[i] = 0U;
++ }
++ }
++
++ /* clear unused bits */
++ for (i = 0; i < 4; i++)
++ out->set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
++ CAP_LAST_U32_VALID_MASK;
++}
++
+/* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */
+static uid_t kdbus_from_kuid_keep(kuid_t uid)
+{
@@ -16684,14 +16758,6 @@ index 0000000..3adc6c2
+
+ hdr = &item_hdr[0];
+
-+ /*
-+ * TODO: We currently have no sane way of translating a set of caps
-+ * between different user namespaces. Until that changes, we have
-+ * to drop such items.
-+ */
-+ if (mp && mp->caps_namespace != user_ns)
-+ mask &= ~KDBUS_ATTACH_CAPS;
-+
+ if (mask == 0) {
+ *real_size = 0;
+ return 0;
@@ -16797,10 +16863,14 @@ index 0000000..3adc6c2
+ KDBUS_ITEM_CGROUP, mp->cgroup,
+ strlen(mp->cgroup) + 1, &size);
+
-+ if (mp && (mask & KDBUS_ATTACH_CAPS))
++ if (mp && (mask & KDBUS_ATTACH_CAPS)) {
++ struct kdbus_meta_caps caps = {};
++
++ kdbus_meta_export_caps(&caps, mp);
+ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++,
-+ KDBUS_ITEM_CAPS, &mp->caps,
-+ sizeof(mp->caps), &size);
++ KDBUS_ITEM_CAPS, &caps,
++ sizeof(caps), &size);
++ }
+
+ if (mp && (mask & KDBUS_ATTACH_SECLABEL))
+ cnt += kdbus_meta_push_kvec(kvec + cnt, hdr++,
@@ -16864,10 +16934,10 @@ index 0000000..3adc6c2
+}
diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h
new file mode 100644
-index 0000000..42c942b
+index 0000000..79b6ac3
--- /dev/null
+++ b/ipc/kdbus/metadata.h
-@@ -0,0 +1,57 @@
+@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -16894,8 +16964,6 @@ index 0000000..42c942b
+struct kdbus_meta_proc;
+struct kdbus_meta_conn;
+
-+extern unsigned long long kdbus_meta_attach_mask;
-+
+struct kdbus_meta_proc *kdbus_meta_proc_new(void);
+struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp);
+struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp);
@@ -16927,10 +16995,10 @@ index 0000000..42c942b
+#endif
diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c
new file mode 100644
-index 0000000..657008e
+index 0000000..d77ee08
--- /dev/null
+++ b/ipc/kdbus/names.c
-@@ -0,0 +1,772 @@
+@@ -0,0 +1,770 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -17402,7 +17470,7 @@ index 0000000..657008e
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp)
+{
@@ -17447,8 +17515,6 @@ index 0000000..657008e
+
+ ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name,
+ cmd->flags, &cmd->return_flags);
-+ if (ret < 0)
-+ goto exit_dec;
+
+exit_dec:
+ atomic_dec(&conn->name_count);
@@ -17461,7 +17527,7 @@ index 0000000..657008e
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp)
+{
@@ -17632,7 +17698,7 @@ index 0000000..657008e
+ * @conn: connection to operate on
+ * @argp: command payload
+ *
-+ * Return: 0 on success, negative error code on failure.
++ * Return: >=0 on success, negative error code on failure.
+ */
+int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp)
+{
@@ -17785,10 +17851,10 @@ index 0000000..3dd2589
+#endif
diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c
new file mode 100644
-index 0000000..520df00
+index 0000000..0d65c65
--- /dev/null
+++ b/ipc/kdbus/node.c
-@@ -0,0 +1,910 @@
+@@ -0,0 +1,897 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -17969,7 +18035,7 @@ index 0000000..520df00
+ * accessed by other callers to properly initialize
+ * filesystem nodes.
+ *
-+ * * node->id: This is an unsigned 32bit integer allocated by an IDR. It is
++ * * node->id: This is an unsigned 32bit integer allocated by an IDA. It is
+ * always kept as small as possible during allocation and is
+ * globally unique across all nodes allocated by this module. 0
+ * is reserved as "not assigned" and is the default.
@@ -18024,8 +18090,7 @@ index 0000000..520df00
+#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4)
+
+/* global unique ID mapping for kdbus nodes */
-+static DEFINE_IDR(kdbus_node_idr);
-+static DECLARE_RWSEM(kdbus_node_idr_lock);
++DEFINE_IDA(kdbus_node_ida);
+
+/**
+ * kdbus_node_name_hash() - hash a name
@@ -18128,15 +18193,11 @@ index 0000000..520df00
+ node->hash = kdbus_node_name_hash(name);
+ }
+
-+ down_write(&kdbus_node_idr_lock);
-+ ret = idr_alloc(&kdbus_node_idr, node, 1, 0, GFP_KERNEL);
-+ if (ret >= 0)
-+ node->id = ret;
-+ up_write(&kdbus_node_idr_lock);
-+
++ ret = ida_simple_get(&kdbus_node_ida, 1, 0, GFP_KERNEL);
+ if (ret < 0)
+ return ret;
+
++ node->id = ret;
+ ret = 0;
+
+ if (parent) {
@@ -18231,16 +18292,8 @@ index 0000000..520df00
+
+ if (node->free_cb)
+ node->free_cb(node);
-+
-+ down_write(&kdbus_node_idr_lock);
+ if (safe.id > 0)
-+ idr_remove(&kdbus_node_idr, safe.id);
-+ /* drop caches after last node to not leak memory on unload */
-+ if (idr_is_empty(&kdbus_node_idr)) {
-+ idr_destroy(&kdbus_node_idr);
-+ idr_init(&kdbus_node_idr);
-+ }
-+ up_write(&kdbus_node_idr_lock);
++ ida_simple_remove(&kdbus_node_ida, safe.id);
+
+ kfree(safe.name);
+
@@ -18701,10 +18754,10 @@ index 0000000..520df00
+}
diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h
new file mode 100644
-index 0000000..be125ce
+index 0000000..970e02b
--- /dev/null
+++ b/ipc/kdbus/node.h
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -18765,6 +18818,8 @@ index 0000000..be125ce
+
+#define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb)
+
++extern struct ida kdbus_node_ida;
++
+void kdbus_node_init(struct kdbus_node *node, unsigned int type);
+
+int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
@@ -19633,7 +19688,7 @@ index 0000000..15dd7bc
+#endif
diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c
new file mode 100644
-index 0000000..139bb77
+index 0000000..45dcdea
--- /dev/null
+++ b/ipc/kdbus/pool.c
@@ -0,0 +1,728 @@
@@ -20314,7 +20369,7 @@ index 0000000..139bb77
+ }
+
+ kaddr = (char __force __user *)kmap(page) + page_off;
-+ n_read = f_src->f_op->read(f_src, kaddr, copy_len, &off_src);
++ n_read = __vfs_read(f_src, kaddr, copy_len, &off_src);
+ kunmap(page);
+ mark_page_accessed(page);
+ flush_dcache_page(page);
@@ -20419,7 +20474,7 @@ index 0000000..a903821
+#endif
diff --git a/ipc/kdbus/queue.c b/ipc/kdbus/queue.c
new file mode 100644
-index 0000000..a449464
+index 0000000..25bb3ad
--- /dev/null
+++ b/ipc/kdbus/queue.c
@@ -0,0 +1,678 @@
@@ -21062,7 +21117,7 @@ index 0000000..a449464
+ lockdep_assert_held(&src->lock);
+ lockdep_assert_held(&dst->lock);
+
-+ if (WARN_ON(IS_ERR(e->user)) || WARN_ON(list_empty(&e->entry)))
++ if (WARN_ON(list_empty(&e->entry)))
+ return -EINVAL;
+ if (src == dst)
+ return 0;
@@ -21201,10 +21256,10 @@ index 0000000..7f2db96
+#endif /* __KDBUS_QUEUE_H */
diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c
new file mode 100644
-index 0000000..008dca8
+index 0000000..e6791d8
--- /dev/null
+++ b/ipc/kdbus/reply.c
-@@ -0,0 +1,257 @@
+@@ -0,0 +1,252 @@
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
@@ -21244,7 +21299,7 @@ index 0000000..008dca8
+ bool sync)
+{
+ struct kdbus_reply *r;
-+ int ret = 0;
++ int ret;
+
+ if (atomic_inc_return(&reply_dst->request_count) >
+ KDBUS_CONN_MAX_REQUESTS_PENDING) {
@@ -21271,13 +21326,11 @@ index 0000000..008dca8
+ r->waiting = true;
+ }
+
-+exit_dec_request_count:
-+ if (ret < 0) {
-+ atomic_dec(&reply_dst->request_count);
-+ return ERR_PTR(ret);
-+ }
-+
+ return r;
++
++exit_dec_request_count:
++ atomic_dec(&reply_dst->request_count);
++ return ERR_PTR(ret);
+}
+
+static void __kdbus_reply_free(struct kref *kref)
@@ -21347,8 +21400,7 @@ index 0000000..008dca8
+ * @reply: The reply object
+ * @err: Error code to set on the remote side
+ *
-+ * Remove the synchronous reply object from its connection reply_list, and
-+ * wake up remote peer (method origin) with the appropriate synchronous reply
++ * Wake up remote peer (method origin) with the appropriate synchronous reply
+ * code.
+ */
+void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err)
@@ -21379,17 +21431,15 @@ index 0000000..008dca8
+ struct kdbus_conn *reply_dst,
+ u64 cookie)
+{
-+ struct kdbus_reply *r, *reply = NULL;
++ struct kdbus_reply *r;
+
+ list_for_each_entry(r, &reply_dst->reply_list, entry) {
+ if (r->cookie == cookie &&
-+ (!replying || r->reply_src == replying)) {
-+ reply = r;
-+ break;
-+ }
++ (!replying || r->reply_src == replying))
++ return r;
+ }
+
-+ return reply;
++ return NULL;
+}
+
+/**
@@ -21538,10 +21588,10 @@ index 0000000..68d5232
+#endif /* __KDBUS_REPLY_H */
diff --git a/ipc/kdbus/util.c b/ipc/kdbus/util.c
new file mode 100644
-index 0000000..eaa806a
+index 0000000..72b1883
--- /dev/null
+++ b/ipc/kdbus/util.c
-@@ -0,0 +1,201 @@
+@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -21594,51 +21644,6 @@ index 0000000..eaa806a
+}
+
+/**
-+ * kdbus_memdup_user() - copy dynamically sized object from user-space
-+ * @user_ptr: user-provided source buffer
-+ * @sz_min: minimum object size
-+ * @sz_max: maximum object size
-+ *
-+ * This copies a dynamically sized object from user-space into kernel-space. We
-+ * require the object to have a 64bit size field at offset 0. We read it out
-+ * first, allocate a suitably sized buffer and then copy all data.
-+ *
-+ * The @sz_min and @sz_max parameters define possible min and max object sizes
-+ * so user-space cannot trigger un-bound kernel-space allocations.
-+ *
-+ * The same alignment-restrictions as described in kdbus_copy_from_user() apply.
-+ *
-+ * Return: pointer to dynamically allocated copy, or ERR_PTR() on failure.
-+ */
-+void *kdbus_memdup_user(void __user *user_ptr, size_t sz_min, size_t sz_max)
-+{
-+ void *ptr;
-+ u64 size;
-+ int ret;
-+
-+ ret = kdbus_copy_from_user(&size, user_ptr, sizeof(size));
-+ if (ret < 0)
-+ return ERR_PTR(ret);
-+
-+ if (size < sz_min)
-+ return ERR_PTR(-EINVAL);
-+
-+ if (size > sz_max)
-+ return ERR_PTR(-EMSGSIZE);
-+
-+ ptr = memdup_user(user_ptr, size);
-+ if (IS_ERR(ptr))
-+ return ptr;
-+
-+ if (*(u64 *)ptr != size) {
-+ kfree(ptr);
-+ return ERR_PTR(-EINVAL);
-+ }
-+
-+ return ptr;
-+}
-+
-+/**
+ * kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name
+ * @name: user-supplied name to verify
+ * @user_ns: user-namespace to act in
@@ -21745,10 +21750,10 @@ index 0000000..eaa806a
+}
diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h
new file mode 100644
-index 0000000..740b198
+index 0000000..5297166
--- /dev/null
+++ b/ipc/kdbus/util.h
-@@ -0,0 +1,74 @@
+@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -21791,7 +21796,7 @@ index 0000000..740b198
+({ \
+ u64 __user *_sz = \
+ (void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \
-+ copy_to_user(_sz, _s, sizeof(((_t *)0)->_m)); \
++ copy_to_user(_sz, _s, FIELD_SIZEOF(_t, _m)); \
+})
+
+/**
@@ -21815,7 +21820,6 @@ index 0000000..740b198
+int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags);
+
+int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size);
-+void *kdbus_memdup_user(void __user *user_ptr, size_t sz_min, size_t sz_max);
+
+struct kvec;
+
@@ -21876,7 +21880,7 @@ index 0000000..137f842
+HOSTLOADLIBES_kdbus-workers := -lrt
diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h
new file mode 100644
-index 0000000..5ed5907
+index 0000000..7f3abae
--- /dev/null
+++ b/samples/kdbus/kdbus-api.h
@@ -0,0 +1,114 @@
@@ -21890,12 +21894,12 @@ index 0000000..5ed5907
+#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
+#define KDBUS_ITEM_NEXT(item) \
-+ (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
++ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
+#define KDBUS_FOREACH(iter, first, _size) \
-+ for (iter = (first); \
++ for ((iter) = (first); \
+ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
+ ((uint8_t *)(iter) >= (uint8_t *)(first)); \
-+ iter = (void*)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
++ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size)))
+
+static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd)
+{
@@ -21996,10 +22000,10 @@ index 0000000..5ed5907
+#endif /* KDBUS_API_H */
diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c
new file mode 100644
-index 0000000..d331e01
+index 0000000..c3ba958
--- /dev/null
+++ b/samples/kdbus/kdbus-workers.c
-@@ -0,0 +1,1326 @@
+@@ -0,0 +1,1345 @@
+/*
+ * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
+ *
@@ -22059,6 +22063,12 @@ index 0000000..d331e01
+ * top-down, but requires some forward-declarations. Just ignore those.
+ */
+
++#include <stdio.h>
++#include <stdlib.h>
++
++/* glibc < 2.7 does not ship sys/signalfd.h */
++#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7
++
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
@@ -22067,8 +22077,6 @@ index 0000000..d331e01
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
-+#include <stdio.h>
-+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
@@ -23326,8 +23334,23 @@ index 0000000..d331e01
+
+ return fd;
+}
++
++#else
++
++#warning "Skipping compilation due to unsupported libc version"
++
++int main(int argc, char **argv)
++{
++ fprintf(stderr,
++ "Compilation of %s was skipped due to unsupported libc.\n",
++ argv[0]);
++
++ return EXIT_FAILURE;
++}
++
++#endif /* libc sanity check */
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
-index 4e51122..7b51cce 100644
+index 95abddc..b57100c 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -5,6 +5,7 @@ TARGETS += exec
@@ -23347,10 +23370,10 @@ index 0000000..d3ef42f
+kdbus-test
diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile
new file mode 100644
-index 0000000..de8242f
+index 0000000..8f36cb5
--- /dev/null
+++ b/tools/testing/selftests/kdbus/Makefile
-@@ -0,0 +1,48 @@
+@@ -0,0 +1,49 @@
+CFLAGS += -I../../../../usr/include/
+CFLAGS += -I../../../../samples/kdbus/
+CFLAGS += -I../../../../include/uapi/
@@ -23364,7 +23387,6 @@ index 0000000..de8242f
+ kdbus-test.o \
+ kdbus-test.o \
+ test-activator.o \
-+ test-attach-flags.o \
+ test-benchmark.o \
+ test-bus.o \
+ test-chat.o \
@@ -23388,12 +23410,14 @@ index 0000000..de8242f
+
+include ../lib.mk
+
-+%.o: %.c
++%.o: %.c kdbus-enum.h kdbus-test.h kdbus-util.h
+ $(CC) $(CFLAGS) -c $< -o $@
+
+kdbus-test: $(OBJS)
+ $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@
+
++TEST_PROGS := kdbus-test
++
+run_tests:
+ ./kdbus-test --tap
+
@@ -23501,10 +23525,10 @@ index 0000000..4f1e579
+LOOKUP(PAYLOAD);
diff --git a/tools/testing/selftests/kdbus/kdbus-enum.h b/tools/testing/selftests/kdbus/kdbus-enum.h
new file mode 100644
-index 0000000..a67cec3
+index 0000000..ed28cca
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-enum.h
-@@ -0,0 +1,14 @@
+@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ *
@@ -23513,6 +23537,7 @@ index 0000000..a67cec3
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
++
+#pragma once
+
+const char *enum_CMD(long long id);
@@ -23521,10 +23546,10 @@ index 0000000..a67cec3
+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..a43674c
+index 0000000..294e82a
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-test.c
-@@ -0,0 +1,923 @@
+@@ -0,0 +1,900 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
@@ -23575,7 +23600,6 @@ index 0000000..a43674c
+ char *root;
+ char *test;
+ char *busname;
-+ char *mask_param_path;
+};
+
+static const struct kdbus_test tests[] = {
@@ -23801,13 +23825,6 @@ index 0000000..a43674c
+ .func = kdbus_test_benchmark_uds,
+ .flags = TEST_CREATE_BUS,
+ },
-+ {
-+ /* Last test */
-+ .name = "attach-flags",
-+ .desc = "attach flags mask",
-+ .func = kdbus_test_attach_flags,
-+ .flags = 0,
-+ },
+};
+
+#define N_TESTS ((int) (sizeof(tests) / sizeof(tests[0])))
@@ -23850,7 +23867,6 @@ index 0000000..a43674c
+
+ env->root = args->root;
+ env->module = args->module;
-+ env->mask_param_path = args->mask_param_path;
+
+ return 0;
+}
@@ -24281,8 +24297,7 @@ index 0000000..a43674c
+{
+ int ret;
+ bool namespaces;
-+ uint64_t kdbus_param_mask;
-+ static char fspath[4096], parampath[4096];
++ static char fspath[4096];
+
+ namespaces = (kdbus_args->mntns || kdbus_args->pidns ||
+ kdbus_args->userns);
@@ -24318,19 +24333,6 @@ index 0000000..a43674c
+ kdbus_args->root = fspath;
+ }
+
-+ snprintf(parampath, sizeof(parampath),
-+ "/sys/module/%s/parameters/attach_flags_mask",
-+ kdbus_args->module);
-+ kdbus_args->mask_param_path = parampath;
-+
-+ ret = kdbus_sysfs_get_parameter_mask(kdbus_args->mask_param_path,
-+ &kdbus_param_mask);
-+ if (ret < 0)
-+ return TEST_ERR;
-+
-+ printf("# Starting tests with an attach_flags_mask=0x%llx\n",
-+ (unsigned long long)kdbus_param_mask);
-+
+ /* Start tests */
+ if (namespaces)
+ ret = run_tests_in_namespaces(kdbus_args);
@@ -24450,10 +24452,10 @@ index 0000000..a43674c
+}
diff --git a/tools/testing/selftests/kdbus/kdbus-test.h b/tools/testing/selftests/kdbus/kdbus-test.h
new file mode 100644
-index 0000000..6473318
+index 0000000..a5c6ae8
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-test.h
-@@ -0,0 +1,85 @@
+@@ -0,0 +1,83 @@
+#ifndef _TEST_KDBUS_H_
+#define _TEST_KDBUS_H_
+
@@ -24461,7 +24463,6 @@ index 0000000..6473318
+ char *buspath;
+ const char *root;
+ const char *module;
-+ const char *mask_param_path;
+ int control_fd;
+ struct kdbus_conn *conn;
+};
@@ -24500,7 +24501,6 @@ index 0000000..6473318
+ ASSERT_EXIT_VAL(cond, EXIT_FAILURE)
+
+int kdbus_test_activator(struct kdbus_test_env *env);
-+int kdbus_test_attach_flags(struct kdbus_test_env *env);
+int kdbus_test_benchmark(struct kdbus_test_env *env);
+int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env);
+int kdbus_test_benchmark_uds(struct kdbus_test_env *env);
@@ -24541,10 +24541,10 @@ index 0000000..6473318
+#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..4b376ec
+index 0000000..29a0cb1
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-util.c
-@@ -0,0 +1,1615 @@
+@@ -0,0 +1,1617 @@
+/*
+ * Copyright (C) 2013-2015 Daniel Mack
+ * Copyright (C) 2013-2015 Kay Sievers
@@ -24955,11 +24955,9 @@ index 0000000..4b376ec
+{
+ int ret, fd;
+
-+ ret = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING);
-+ if (ret < 0)
-+ return ret;
-+
-+ fd = ret;
++ fd = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING);
++ if (fd < 0)
++ return fd;
+
+ ret = ftruncate(fd, size);
+ if (ret < 0) {
@@ -25001,8 +24999,8 @@ index 0000000..4b376ec
+ uint64_t cmd_flags,
+ int cancel_fd)
+{
-+ struct kdbus_cmd_send *cmd;
-+ struct kdbus_msg *msg;
++ struct kdbus_cmd_send *cmd = NULL;
++ struct kdbus_msg *msg = NULL;
+ const char ref1[1024 * 128 + 3] = "0123456789_0";
+ const char ref2[] = "0123456789_1";
+ struct kdbus_item *item;
@@ -25011,10 +25009,7 @@ index 0000000..4b376ec
+ int memfd = -1;
+ int ret;
+
-+ size = sizeof(*msg);
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
++ size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
+
+ if (dst_id == KDBUS_DST_ID_BROADCAST)
+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
@@ -25028,14 +25023,14 @@ index 0000000..4b376ec
+ if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
+ ret = -errno;
+ kdbus_printf("writing to memfd failed: %m\n");
-+ return ret;
++ goto out;
+ }
+
+ ret = sys_memfd_seal_set(memfd);
+ if (ret < 0) {
+ ret = -errno;
+ kdbus_printf("memfd sealing failed: %m\n");
-+ return ret;
++ goto out;
+ }
+
+ size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
@@ -25048,7 +25043,7 @@ index 0000000..4b376ec
+ if (!msg) {
+ ret = -errno;
+ kdbus_printf("unable to malloc()!?\n");
-+ return ret;
++ goto out;
+ }
+
+ if (dst_id == KDBUS_DST_ID_BROADCAST)
@@ -25066,7 +25061,7 @@ index 0000000..4b376ec
+ if (timeout) {
+ ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
+ if (ret < 0)
-+ return ret;
++ goto out;
+
+ msg->timeout_ns = now.tv_sec * 1000000000ULL +
+ now.tv_nsec + timeout;
@@ -25117,6 +25112,12 @@ index 0000000..4b376ec
+ size += KDBUS_ITEM_SIZE(sizeof(cancel_fd));
+
+ cmd = malloc(size);
++ if (!cmd) {
++ ret = -errno;
++ kdbus_printf("unable to malloc()!?\n");
++ goto out;
++ }
++
+ cmd->size = size;
+ cmd->flags = cmd_flags;
+ cmd->msg_address = (uintptr_t)msg;
@@ -25131,12 +25132,9 @@ index 0000000..4b376ec
+ }
+
+ ret = kdbus_cmd_send(conn->fd, cmd);
-+ if (memfd >= 0)
-+ close(memfd);
-+
+ if (ret < 0) {
+ kdbus_printf("error sending message: %d (%m)\n", ret);
-+ return ret;
++ goto out;
+ }
+
+ if (cmd_flags & KDBUS_SEND_SYNC_REPLY) {
@@ -25150,13 +25148,17 @@ index 0000000..4b376ec
+
+ ret = kdbus_free(conn, cmd->reply.offset);
+ if (ret < 0)
-+ return ret;
++ goto out;
+ }
+
++out:
+ free(msg);
+ free(cmd);
+
-+ return 0;
++ if (memfd >= 0)
++ close(memfd);
++
++ return ret < 0 ? ret : 0;
+}
+
+int kdbus_msg_send(const struct kdbus_conn *conn, const char *name,
@@ -25900,7 +25902,7 @@ index 0000000..4b376ec
+ return 0;
+}
+
-+int all_uids_gids_are_mapped()
++int all_uids_gids_are_mapped(void)
+{
+ int ret;
+
@@ -26094,7 +26096,7 @@ index 0000000..4b376ec
+ cap_t caps;
+
+ caps = cap_get_proc();
-+ if (!cap) {
++ if (!caps) {
+ ret = -errno;
+ kdbus_printf("error cap_get_proc(): %d (%m)\n", ret);
+ return ret;
@@ -26162,10 +26164,10 @@ index 0000000..4b376ec
+}
diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h
new file mode 100644
-index 0000000..50ff071
+index 0000000..d1a0f1b
--- /dev/null
+++ b/tools/testing/selftests/kdbus/kdbus-util.h
-@@ -0,0 +1,222 @@
+@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2013-2015 Kay Sievers
+ * Copyright (C) 2013-2015 Daniel Mack
@@ -26175,6 +26177,7 @@ index 0000000..50ff071
+ * Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ */
++
+#pragma once
+
+#define BIT(X) (1 << (X))
@@ -26194,28 +26197,26 @@ index 0000000..50ff071
+#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
+
+#define KDBUS_ITEM_NEXT(item) \
-+ (typeof(item))(((uint8_t *)item) + KDBUS_ALIGN8((item)->size))
++ (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
+#define KDBUS_ITEM_FOREACH(item, head, first) \
-+ for (item = (head)->first; \
++ for ((item) = (head)->first; \
+ ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
-+ ((uint8_t *)(item) >= (uint8_t *)(head)); \
-+ item = KDBUS_ITEM_NEXT(item))
++ ((uint8_t *)(item) >= (uint8_t *)(head)); \
++ (item) = KDBUS_ITEM_NEXT(item))
+#define KDBUS_FOREACH(iter, first, _size) \
-+ for (iter = (first); \
++ for ((iter) = (first); \
+ ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
+ ((uint8_t *)(iter) >= (uint8_t *)(first)); \
-+ iter = (void*)(((uint8_t *)iter) + KDBUS_ALIGN8((iter)->size)))
-+
++ (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size)))
+
-+#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL))
++#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL))
+
+/* Sum of KDBUS_ITEM_* that reflects _KDBUS_ATTACH_ALL */
-+#define KDBUS_ATTACH_ITEMS_TYPE_SUM \
-+ ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \
-+ ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2 ) + \
++#define KDBUS_ATTACH_ITEMS_TYPE_SUM \
++ ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \
++ ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2) + \
+ (_KDBUS_ITEM_ATTACH_BASE * _KDBUS_ATTACH_BITS_SET_NR))
+
-+
+#define POOL_SIZE (16 * 1024LU * 1024LU)
+
+#define UNPRIV_UID 65534
@@ -26273,7 +26274,7 @@ index 0000000..50ff071
+ _setup_; \
+ efd = eventfd(0, EFD_CLOEXEC); \
+ ASSERT_RETURN(efd >= 0); \
-+ *clone_ret = 0; \
++ *(clone_ret) = 0; \
+ pid = syscall(__NR_clone, flags, NULL); \
+ if (pid == 0) { \
+ eventfd_t event_status = 0; \
@@ -26298,7 +26299,7 @@ index 0000000..50ff071
+ ret = TEST_OK; \
+ } else { \
+ ret = -errno; \
-+ *clone_ret = -errno; \
++ *(clone_ret) = -errno; \
+ } \
+ close(efd); \
+ ret; \
@@ -26375,14 +26376,12 @@ index 0000000..50ff071
+ uint64_t type, uint64_t id);
+int kdbus_add_match_empty(struct kdbus_conn *conn);
+
-+int all_uids_gids_are_mapped();
++int all_uids_gids_are_mapped(void);
+int drop_privileges(uid_t uid, gid_t gid);
+uint64_t now(clockid_t clock);
+char *unique_name(const char *prefix);
+
-+int userns_map_uid_gid(pid_t pid,
-+ const char *map_uid,
-+ const char *map_gid);
++int userns_map_uid_gid(pid_t pid, const char *map_uid, const char *map_gid);
+int test_is_capable(int cap, ...);
+int config_user_ns_is_enabled(void);
+int config_auditsyscall_is_enabled(void);
@@ -26712,762 +26711,6 @@ index 0000000..3d1b763
+
+ return TEST_OK;
+}
-diff --git a/tools/testing/selftests/kdbus/test-attach-flags.c b/tools/testing/selftests/kdbus/test-attach-flags.c
-new file mode 100644
-index 0000000..deee7c3
---- /dev/null
-+++ b/tools/testing/selftests/kdbus/test-attach-flags.c
-@@ -0,0 +1,750 @@
-+#include <stdio.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <stdbool.h>
-+#include <stddef.h>
-+#include <fcntl.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <errno.h>
-+#include <assert.h>
-+#include <sys/capability.h>
-+#include <sys/mman.h>
-+#include <sys/stat.h>
-+#include <sys/types.h>
-+#include <linux/unistd.h>
-+
-+#include "kdbus-api.h"
-+#include "kdbus-test.h"
-+#include "kdbus-util.h"
-+#include "kdbus-enum.h"
-+
-+/*
-+ * Should be the sum of the currently supported and compiled-in
-+ * KDBUS_ITEMS_* that reflect KDBUS_ATTACH_* flags.
-+ */
-+static unsigned int KDBUS_TEST_ITEMS_SUM = KDBUS_ATTACH_ITEMS_TYPE_SUM;
-+
-+static struct kdbus_conn *__kdbus_hello(const char *path, uint64_t flags,
-+ uint64_t attach_flags_send,
-+ uint64_t attach_flags_recv)
-+{
-+ struct kdbus_cmd_free cmd_free = {};
-+ int ret, fd;
-+ struct kdbus_conn *conn;
-+ struct {
-+ struct kdbus_cmd_hello hello;
-+
-+ struct {
-+ uint64_t size;
-+ uint64_t type;
-+ char str[16];
-+ } conn_name;
-+
-+ uint8_t extra_items[0];
-+ } h;
-+
-+ memset(&h, 0, sizeof(h));
-+
-+ kdbus_printf("-- opening bus connection %s\n", path);
-+ fd = open(path, O_RDWR|O_CLOEXEC);
-+ if (fd < 0) {
-+ kdbus_printf("--- error %d (%m)\n", fd);
-+ return NULL;
-+ }
-+
-+ h.hello.flags = flags | KDBUS_HELLO_ACCEPT_FD;
-+ h.hello.attach_flags_send = attach_flags_send;
-+ h.hello.attach_flags_recv = attach_flags_recv;
-+ h.conn_name.type = KDBUS_ITEM_CONN_DESCRIPTION;
-+ strcpy(h.conn_name.str, "this-is-my-name");
-+ h.conn_name.size = KDBUS_ITEM_HEADER_SIZE + strlen(h.conn_name.str) + 1;
-+
-+ h.hello.size = sizeof(h);
-+ h.hello.pool_size = POOL_SIZE;
-+
-+ ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello);
-+ if (ret < 0) {
-+ kdbus_printf("--- error when saying hello: %d (%m)\n", ret);
-+ return NULL;
-+ }
-+
-+ kdbus_printf("-- New connection ID : %llu\n",
-+ (unsigned long long)h.hello.id);
-+
-+ cmd_free.size = sizeof(cmd_free);
-+ cmd_free.offset = h.hello.offset;
-+ ret = kdbus_cmd_free(fd, &cmd_free);
-+ if (ret < 0)
-+ return NULL;
-+
-+ conn = malloc(sizeof(*conn));
-+ if (!conn) {
-+ kdbus_printf("unable to malloc()!?\n");
-+ return NULL;
-+ }
-+
-+ conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
-+ if (conn->buf == MAP_FAILED) {
-+ ret = -errno;
-+ free(conn);
-+ close(fd);
-+ kdbus_printf("--- error mmap: %d (%m)\n", ret);
-+ return NULL;
-+ }
-+
-+ conn->fd = fd;
-+ conn->id = h.hello.id;
-+ return conn;
-+}
-+
-+static int kdbus_test_peers_creation(struct kdbus_test_env *env)
-+{
-+ int ret;
-+ int control_fd;
-+ char *path;
-+ char *busname;
-+ char buspath[2048];
-+ char control_path[2048];
-+ uint64_t attach_flags_mask;
-+ struct kdbus_conn *conn;
-+
-+ snprintf(control_path, sizeof(control_path),
-+ "%s/control", env->root);
-+
-+ /*
-+ * Set kdbus system-wide mask to 0, this has nothing
-+ * to do with the following tests, bus and connection
-+ * creation nor connection update, but we do it so we are
-+ * sure that everything work as expected
-+ */
-+
-+ attach_flags_mask = 0;
-+ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path,
-+ attach_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+
-+ /*
-+ * Create bus with a full set of ATTACH flags
-+ */
-+
-+ control_fd = open(control_path, O_RDWR);
-+ ASSERT_RETURN(control_fd >= 0);
-+
-+ busname = unique_name("test-peers-creation-bus");
-+ ASSERT_RETURN(busname);
-+
-+ ret = kdbus_create_bus(control_fd, busname, _KDBUS_ATTACH_ALL,
-+ 0, &path);
-+ ASSERT_RETURN(ret == 0);
-+
-+ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path);
-+
-+ /*
-+ * Create a connection with an empty send attach flags, or
-+ * with just KDBUS_ATTACH_CREDS, this should fail
-+ */
-+ conn = __kdbus_hello(buspath, 0, 0, 0);
-+ ASSERT_RETURN(conn == NULL);
-+ ASSERT_RETURN(errno == ECONNREFUSED);
-+
-+ conn = __kdbus_hello(buspath, 0, KDBUS_ATTACH_CREDS,
-+ _KDBUS_ATTACH_ALL);
-+ ASSERT_RETURN(conn == NULL);
-+ ASSERT_RETURN(errno == ECONNREFUSED);
-+
-+ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0);
-+ ASSERT_RETURN(conn);
-+
-+ /* Try to cut back some send attach flags */
-+ ret = kdbus_conn_update_attach_flags(conn,
-+ KDBUS_ATTACH_CREDS|
-+ KDBUS_ATTACH_PIDS,
-+ _KDBUS_ATTACH_ALL);
-+ ASSERT_RETURN(ret == -EINVAL);
-+
-+ ret = kdbus_conn_update_attach_flags(conn,
-+ _KDBUS_ATTACH_ALL, 0);
-+ ASSERT_RETURN(ret == 0);
-+
-+ kdbus_conn_free(conn);
-+ free(path);
-+ free(busname);
-+ close(control_fd);
-+
-+
-+ /* Test a new bus with KDBUS_ATTACH_PIDS */
-+
-+ control_fd = open(control_path, O_RDWR);
-+ ASSERT_RETURN(control_fd >= 0);
-+
-+ busname = unique_name("test-peer-flags-bus");
-+ ASSERT_RETURN(busname);
-+
-+ ret = kdbus_create_bus(control_fd, busname, KDBUS_ATTACH_PIDS,
-+ 0, &path);
-+ ASSERT_RETURN(ret == 0);
-+
-+ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path);
-+
-+ /*
-+ * Create a connection with an empty send attach flags, or
-+ * all flags except KDBUS_ATTACH_PIDS
-+ */
-+ conn = __kdbus_hello(buspath, 0, 0, 0);
-+ ASSERT_RETURN(conn == NULL);
-+ ASSERT_RETURN(errno == ECONNREFUSED);
-+
-+ conn = __kdbus_hello(buspath, 0,
-+ _KDBUS_ATTACH_ALL & ~KDBUS_ATTACH_PIDS,
-+ _KDBUS_ATTACH_ALL);
-+ ASSERT_RETURN(conn == NULL);
-+ ASSERT_RETURN(errno == ECONNREFUSED);
-+
-+ /* The following should succeed */
-+ conn = __kdbus_hello(buspath, 0, KDBUS_ATTACH_PIDS, 0);
-+ ASSERT_RETURN(conn);
-+ kdbus_conn_free(conn);
-+
-+ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0);
-+ ASSERT_RETURN(conn);
-+
-+ ret = kdbus_conn_update_attach_flags(conn,
-+ _KDBUS_ATTACH_ALL &
-+ ~KDBUS_ATTACH_PIDS,
-+ _KDBUS_ATTACH_ALL);
-+ ASSERT_RETURN(ret == -EINVAL);
-+
-+ ret = kdbus_conn_update_attach_flags(conn, 0,
-+ _KDBUS_ATTACH_ALL);
-+ ASSERT_RETURN(ret == -EINVAL);
-+
-+ /* Now we want only KDBUS_ATTACH_PIDS */
-+ ret = kdbus_conn_update_attach_flags(conn,
-+ KDBUS_ATTACH_PIDS, 0);
-+ ASSERT_RETURN(ret == 0);
-+
-+ kdbus_conn_free(conn);
-+ free(path);
-+ free(busname);
-+ close(control_fd);
-+
-+
-+ /*
-+ * Create bus with 0 as ATTACH flags, the bus does not
-+ * require any attach flags
-+ */
-+
-+ control_fd = open(control_path, O_RDWR);
-+ ASSERT_RETURN(control_fd >= 0);
-+
-+ busname = unique_name("test-peer-flags-bus");
-+ ASSERT_RETURN(busname);
-+
-+ ret = kdbus_create_bus(control_fd, busname, 0, 0, &path);
-+ ASSERT_RETURN(ret == 0);
-+
-+ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path);
-+
-+ /* Bus is open it does not require any send attach flags */
-+ conn = __kdbus_hello(buspath, 0, 0, 0);
-+ ASSERT_RETURN(conn);
-+ kdbus_conn_free(conn);
-+
-+ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0);
-+ ASSERT_RETURN(conn);
-+
-+ ret = kdbus_conn_update_attach_flags(conn, 0, 0);
-+ ASSERT_RETURN(ret == 0);
-+
-+ ret = kdbus_conn_update_attach_flags(conn, KDBUS_ATTACH_CREDS, 0);
-+ ASSERT_RETURN(ret == 0);
-+
-+ kdbus_conn_free(conn);
-+ free(path);
-+ free(busname);
-+ close(control_fd);
-+
-+ return 0;
-+}
-+
-+static int kdbus_test_peers_info(struct kdbus_test_env *env)
-+{
-+ int ret;
-+ int control_fd;
-+ char *path;
-+ char *busname;
-+ unsigned int i = 0;
-+ uint64_t offset = 0;
-+ char buspath[2048];
-+ char control_path[2048];
-+ uint64_t attach_flags_mask;
-+ struct kdbus_item *item;
-+ struct kdbus_info *info;
-+ struct kdbus_conn *conn;
-+ struct kdbus_conn *reader;
-+ unsigned long long attach_count = 0;
-+
-+ snprintf(control_path, sizeof(control_path),
-+ "%s/control", env->root);
-+
-+ attach_flags_mask = 0;
-+ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path,
-+ attach_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+ control_fd = open(control_path, O_RDWR);
-+ ASSERT_RETURN(control_fd >= 0);
-+
-+ busname = unique_name("test-peers-info-bus");
-+ ASSERT_RETURN(busname);
-+
-+ ret = kdbus_create_bus(control_fd, busname, _KDBUS_ATTACH_ALL,
-+ 0, &path);
-+ ASSERT_RETURN(ret == 0);
-+
-+ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path);
-+
-+ /* Create connections with the appropriate flags */
-+ conn = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0);
-+ ASSERT_RETURN(conn);
-+
-+ reader = __kdbus_hello(buspath, 0, _KDBUS_ATTACH_ALL, 0);
-+ ASSERT_RETURN(reader);
-+
-+ ret = kdbus_conn_info(reader, conn->id, NULL,
-+ _KDBUS_ATTACH_ALL, &offset);
-+ ASSERT_RETURN(ret == 0);
-+
-+ info = (struct kdbus_info *)(reader->buf + offset);
-+ ASSERT_RETURN(info->id == conn->id);
-+
-+ /* all attach flags are masked, no metadata */
-+ KDBUS_ITEM_FOREACH(item, info, items)
-+ i++;
-+
-+ ASSERT_RETURN(i == 0);
-+
-+ kdbus_free(reader, offset);
-+
-+ /* Set the mask to _KDBUS_ATTACH_ANY */
-+ attach_flags_mask = _KDBUS_ATTACH_ANY;
-+ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path,
-+ attach_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+ ret = kdbus_conn_info(reader, conn->id, NULL,
-+ _KDBUS_ATTACH_ALL, &offset);
-+ ASSERT_RETURN(ret == 0);
-+
-+ info = (struct kdbus_info *)(reader->buf + offset);
-+ ASSERT_RETURN(info->id == conn->id);
-+
-+ attach_count = 0;
-+ KDBUS_ITEM_FOREACH(item, info, items)
-+ attach_count += item->type;
-+
-+ /*
-+ * All flags have been returned except for:
-+ * KDBUS_ITEM_TIMESTAMP and
-+ * KDBUS_ITEM_OWNED_NAME we do not own any name.
-+ */
-+ ASSERT_RETURN(attach_count == (KDBUS_TEST_ITEMS_SUM -
-+ KDBUS_ITEM_OWNED_NAME -
-+ KDBUS_ITEM_TIMESTAMP));
-+
-+ kdbus_free(reader, offset);
-+
-+ /* Request only OWNED names */
-+ ret = kdbus_conn_info(reader, conn->id, NULL,
-+ KDBUS_ATTACH_NAMES, &offset);
-+ ASSERT_RETURN(ret == 0);
-+
-+ info = (struct kdbus_info *)(reader->buf + offset);
-+ ASSERT_RETURN(info->id == conn->id);
-+
-+ attach_count = 0;
-+ KDBUS_ITEM_FOREACH(item, info, items)
-+ attach_count += item->type;
-+
-+ /* we should not get any metadata since we do not own names */
-+ ASSERT_RETURN(attach_count == 0);
-+
-+ kdbus_free(reader, offset);
-+
-+ kdbus_conn_free(conn);
-+ kdbus_conn_free(reader);
-+
-+ return 0;
-+}
-+
-+/**
-+ * @kdbus_mask_param: kdbus module mask parameter (system-wide)
-+ * @requested_meta: The bus owner metadata that we want
-+ * @expected_items: The returned KDBUS_ITEMS_* sum. Used to
-+ * validate the returned metadata items
-+ */
-+static int kdbus_cmp_bus_creator_metadata(struct kdbus_test_env *env,
-+ struct kdbus_conn *conn,
-+ uint64_t kdbus_mask_param,
-+ uint64_t requested_meta,
-+ unsigned long expected_items)
-+{
-+ int ret;
-+ uint64_t offset = 0;
-+ struct kdbus_info *info;
-+ struct kdbus_item *item;
-+ unsigned long attach_count = 0;
-+
-+ ret = kdbus_sysfs_set_parameter_mask(env->mask_param_path,
-+ kdbus_mask_param);
-+ ASSERT_RETURN(ret == 0);
-+
-+ ret = kdbus_bus_creator_info(conn, requested_meta, &offset);
-+ ASSERT_RETURN(ret == 0);
-+
-+ info = (struct kdbus_info *)(conn->buf + offset);
-+
-+ KDBUS_ITEM_FOREACH(item, info, items)
-+ attach_count += item->type;
-+
-+ ASSERT_RETURN(attach_count == expected_items);
-+
-+ ret = kdbus_free(conn, offset);
-+ ASSERT_RETURN(ret == 0);
-+
-+ return 0;
-+}
-+
-+static int kdbus_test_bus_creator_info(struct kdbus_test_env *env)
-+{
-+ int ret;
-+ int control_fd;
-+ char *path;
-+ char *busname;
-+ char buspath[2048];
-+ char control_path[2048];
-+ uint64_t attach_flags_mask;
-+ struct kdbus_conn *conn;
-+ unsigned long expected_items = 0;
-+
-+ snprintf(control_path, sizeof(control_path),
-+ "%s/control", env->root);
-+
-+ control_fd = open(control_path, O_RDWR);
-+ ASSERT_RETURN(control_fd >= 0);
-+
-+ busname = unique_name("test-peers-info-bus");
-+ ASSERT_RETURN(busname);
-+
-+ /*
-+ * Now the bus allows us to see all its KDBUS_ATTACH_*
-+ * items
-+ */
-+ ret = kdbus_create_bus(control_fd, busname, 0,
-+ _KDBUS_ATTACH_ALL, &path);
-+ ASSERT_RETURN(ret == 0);
-+
-+ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path);
-+
-+ conn = __kdbus_hello(buspath, 0, 0, 0);
-+ ASSERT_RETURN(conn);
-+
-+ /*
-+ * Start with a kdbus module mask set to _KDBUS_ATTACH_ANY
-+ */
-+ attach_flags_mask = _KDBUS_ATTACH_ANY;
-+
-+ /*
-+ * All flags will be returned except for:
-+ * KDBUS_ITEM_TIMESTAMP
-+ * KDBUS_ITEM_OWNED_NAME
-+ * KDBUS_ITEM_CONN_DESCRIPTION
-+ *
-+ * An extra flags is always returned KDBUS_ITEM_MAKE_NAME
-+ * which contains the bus name
-+ */
-+ expected_items = KDBUS_TEST_ITEMS_SUM + KDBUS_ITEM_MAKE_NAME;
-+ expected_items -= KDBUS_ITEM_TIMESTAMP +
-+ KDBUS_ITEM_OWNED_NAME +
-+ KDBUS_ITEM_CONN_DESCRIPTION;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /*
-+ * We should have:
-+ * KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS + KDBUS_ITEM_MAKE_NAME
-+ */
-+ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS +
-+ KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ KDBUS_ATTACH_PIDS |
-+ KDBUS_ATTACH_CREDS,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /* KDBUS_ITEM_MAKE_NAME is always returned */
-+ expected_items = KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ 0, expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /*
-+ * Restrict kdbus system-wide mask to KDBUS_ATTACH_PIDS
-+ */
-+
-+ attach_flags_mask = KDBUS_ATTACH_PIDS;
-+
-+ /*
-+ * We should have:
-+ * KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME
-+ */
-+ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+
-+ /* system-wide mask to 0 */
-+ attach_flags_mask = 0;
-+
-+ /* we should only see: KDBUS_ITEM_MAKE_NAME */
-+ expected_items = KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ kdbus_conn_free(conn);
-+ free(path);
-+ free(busname);
-+ close(control_fd);
-+
-+
-+ /*
-+ * A new bus that hides all its owner metadata
-+ */
-+
-+ control_fd = open(control_path, O_RDWR);
-+ ASSERT_RETURN(control_fd >= 0);
-+
-+ busname = unique_name("test-peers-info-bus");
-+ ASSERT_RETURN(busname);
-+
-+ ret = kdbus_create_bus(control_fd, busname, 0, 0, &path);
-+ ASSERT_RETURN(ret == 0);
-+
-+ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path);
-+
-+ conn = __kdbus_hello(buspath, 0, 0, 0);
-+ ASSERT_RETURN(conn);
-+
-+ /*
-+ * Start with a kdbus module mask set to _KDBUS_ATTACH_ANY
-+ */
-+ attach_flags_mask = _KDBUS_ATTACH_ANY;
-+
-+ /*
-+ * We only get the KDBUS_ITEM_MAKE_NAME
-+ */
-+ expected_items = KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /*
-+ * We still get only kdbus_ITEM_MAKE_NAME
-+ */
-+ attach_flags_mask = 0;
-+ expected_items = KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ kdbus_conn_free(conn);
-+ free(path);
-+ free(busname);
-+ close(control_fd);
-+
-+
-+ /*
-+ * A new bus that shows only the PID and CREDS metadata
-+ * of the bus owner.
-+ */
-+ control_fd = open(control_path, O_RDWR);
-+ ASSERT_RETURN(control_fd >= 0);
-+
-+ busname = unique_name("test-peers-info-bus");
-+ ASSERT_RETURN(busname);
-+
-+ ret = kdbus_create_bus(control_fd, busname, 0,
-+ KDBUS_ATTACH_PIDS|
-+ KDBUS_ATTACH_CREDS, &path);
-+ ASSERT_RETURN(ret == 0);
-+
-+ snprintf(buspath, sizeof(buspath), "%s/%s/bus", env->root, path);
-+
-+ conn = __kdbus_hello(buspath, 0, 0, 0);
-+ ASSERT_RETURN(conn);
-+
-+ /*
-+ * Start with a kdbus module mask set to _KDBUS_ATTACH_ANY
-+ */
-+ attach_flags_mask = _KDBUS_ATTACH_ANY;
-+
-+ /*
-+ * We should have:
-+ * KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS + KDBUS_ITEM_MAKE_NAME
-+ */
-+ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_CREDS +
-+ KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ expected_items = KDBUS_ITEM_CREDS + KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ KDBUS_ATTACH_CREDS,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /* KDBUS_ITEM_MAKE_NAME is always returned */
-+ expected_items = KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ 0, expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /*
-+ * Restrict kdbus system-wide mask to KDBUS_ATTACH_PIDS
-+ */
-+
-+ attach_flags_mask = KDBUS_ATTACH_PIDS;
-+ /*
-+ * We should have:
-+ * KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME
-+ */
-+ expected_items = KDBUS_ITEM_PIDS + KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /* No KDBUS_ATTACH_CREDS */
-+ expected_items = KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ KDBUS_ATTACH_CREDS,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /* system-wide mask to 0 */
-+ attach_flags_mask = 0;
-+
-+ /* we should only see: KDBUS_ITEM_MAKE_NAME */
-+ expected_items = KDBUS_ITEM_MAKE_NAME;
-+ ret = kdbus_cmp_bus_creator_metadata(env, conn,
-+ attach_flags_mask,
-+ _KDBUS_ATTACH_ALL,
-+ expected_items);
-+ ASSERT_RETURN(ret == 0);
-+
-+
-+ kdbus_conn_free(conn);
-+ free(path);
-+ free(busname);
-+ close(control_fd);
-+
-+ return 0;
-+}
-+
-+int kdbus_test_attach_flags(struct kdbus_test_env *env)
-+{
-+ int ret;
-+ uint64_t flags_mask;
-+ uint64_t old_kdbus_flags_mask;
-+
-+ /* We need CAP_DAC_OVERRIDE to overwrite the kdbus mask */
-+ ret = test_is_capable(CAP_DAC_OVERRIDE, -1);
-+ ASSERT_RETURN(ret >= 0);
-+
-+ /* no enough privileges, SKIP test */
-+ if (!ret)
-+ return TEST_SKIP;
-+
-+ /*
-+ * We need to be able to write to
-+ * "/sys/module/kdbus/parameters/attach_flags_mask"
-+ * perhaps we are unprvileged/privileged in its userns
-+ */
-+ ret = access(env->mask_param_path, W_OK);
-+ if (ret < 0) {
-+ kdbus_printf("--- access() '%s' failed: %d (%m)\n",
-+ env->mask_param_path, -errno);
-+ return TEST_SKIP;
-+ }
-+
-+ ret = kdbus_sysfs_get_parameter_mask(env->mask_param_path,
-+ &old_kdbus_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /* setup the right KDBUS_TEST_ITEMS_SUM */
-+ if (!config_auditsyscall_is_enabled())
-+ KDBUS_TEST_ITEMS_SUM -= KDBUS_ITEM_AUDIT;
-+
-+ if (!config_cgroups_is_enabled())
-+ KDBUS_TEST_ITEMS_SUM -= KDBUS_ITEM_CGROUP;
-+
-+ if (!config_security_is_enabled())
-+ KDBUS_TEST_ITEMS_SUM -= KDBUS_ITEM_SECLABEL;
-+
-+ /*
-+ * Test the connection creation attach flags
-+ */
-+ ret = kdbus_test_peers_creation(env);
-+ /* Restore previous kdbus mask */
-+ kdbus_sysfs_set_parameter_mask(env->mask_param_path,
-+ old_kdbus_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /*
-+ * Test the CONN_INFO attach flags
-+ */
-+ ret = kdbus_test_peers_info(env);
-+ /* Restore previous kdbus mask */
-+ kdbus_sysfs_set_parameter_mask(env->mask_param_path,
-+ old_kdbus_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+ /*
-+ * Test the Bus creator info and its attach flags
-+ */
-+ ret = kdbus_test_bus_creator_info(env);
-+ /* Restore previous kdbus mask */
-+ kdbus_sysfs_set_parameter_mask(env->mask_param_path,
-+ old_kdbus_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+ ret = kdbus_sysfs_get_parameter_mask(env->mask_param_path,
-+ &flags_mask);
-+ ASSERT_RETURN(ret == 0 && old_kdbus_flags_mask == flags_mask);
-+
-+ return TEST_OK;
-+}
diff --git a/tools/testing/selftests/kdbus/test-benchmark.c b/tools/testing/selftests/kdbus/test-benchmark.c
new file mode 100644
index 0000000..8a9744b
@@ -28236,10 +27479,10 @@ index 0000000..71a92d8
+}
diff --git a/tools/testing/selftests/kdbus/test-connection.c b/tools/testing/selftests/kdbus/test-connection.c
new file mode 100644
-index 0000000..5c2bf35
+index 0000000..e7c4866
--- /dev/null
+++ b/tools/testing/selftests/kdbus/test-connection.c
-@@ -0,0 +1,616 @@
+@@ -0,0 +1,606 @@
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
@@ -28427,13 +27670,10 @@ index 0000000..5c2bf35
+ int ret;
+ unsigned int cnt = 0;
+ uint64_t offset = 0;
-+ uint64_t kdbus_flags_mask;
+ struct kdbus_info *info;
+ struct kdbus_conn *conn;
+ struct kdbus_conn *privileged;
+ const struct kdbus_item *item;
-+ uint64_t valid_flags_set;
-+ uint64_t invalid_flags_set;
+ uint64_t valid_flags = KDBUS_ATTACH_NAMES |
+ KDBUS_ATTACH_CREDS |
+ KDBUS_ATTACH_PIDS |
@@ -28469,13 +27709,6 @@ index 0000000..5c2bf35
+ .ppid = getppid(),
+ };
+
-+ ret = kdbus_sysfs_get_parameter_mask(env->mask_param_path,
-+ &kdbus_flags_mask);
-+ ASSERT_RETURN(ret == 0);
-+
-+ valid_flags_set = valid_flags & kdbus_flags_mask;
-+ invalid_flags_set = invalid_flags & kdbus_flags_mask;
-+
+ ret = kdbus_conn_info(env->conn, env->conn->id, NULL,
+ valid_flags, &offset);
+ ASSERT_RETURN(ret == 0);
@@ -28488,7 +27721,7 @@ index 0000000..5c2bf35
+ ASSERT_RETURN(item == NULL);
+
+ item = kdbus_get_item(info, KDBUS_ITEM_CONN_DESCRIPTION);
-+ if (valid_flags_set & KDBUS_ATTACH_CONN_DESCRIPTION) {
++ if (valid_flags & KDBUS_ATTACH_CONN_DESCRIPTION) {
+ ASSERT_RETURN(item);
+ } else {
+ ASSERT_RETURN(item == NULL);
@@ -28513,7 +27746,7 @@ index 0000000..5c2bf35
+ ASSERT_RETURN(item == NULL);
+
+ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS);
-+ if (valid_flags_set & KDBUS_ATTACH_CREDS) {
++ if (valid_flags & KDBUS_ATTACH_CREDS) {
+ ASSERT_RETURN(cnt == 1);
+
+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS);
@@ -28527,7 +27760,7 @@ index 0000000..5c2bf35
+ }
+
+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS);
-+ if (valid_flags_set & KDBUS_ATTACH_PIDS) {
++ if (valid_flags & KDBUS_ATTACH_PIDS) {
+ ASSERT_RETURN(item);
+
+ /* Compare item->pids with cached PIDs */
@@ -28554,7 +27787,7 @@ index 0000000..5c2bf35
+ ASSERT_RETURN(info->id == conn->id);
+
+ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME);
-+ if (valid_flags_set & KDBUS_ATTACH_NAMES) {
++ if (valid_flags & KDBUS_ATTACH_NAMES) {
+ ASSERT_RETURN(item && !strcmp(item->name.name, "com.example.a"));
+ } else {
+ ASSERT_RETURN(item == NULL);
@@ -28582,14 +27815,14 @@ index 0000000..5c2bf35
+ info = (struct kdbus_info *)(conn->buf + offset);
+ ASSERT_EXIT(info->id == conn->id);
+
-+ if (valid_flags_set & KDBUS_ATTACH_NAMES) {
++ if (valid_flags & KDBUS_ATTACH_NAMES) {
+ item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME);
+ ASSERT_EXIT(item &&
+ strcmp(item->name.name,
+ "com.example.a") == 0);
+ }
+
-+ if (valid_flags_set & KDBUS_ATTACH_CREDS) {
++ if (valid_flags & KDBUS_ATTACH_CREDS) {
+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS);
+ ASSERT_EXIT(item);
+
@@ -28598,7 +27831,7 @@ index 0000000..5c2bf35
+ sizeof(struct kdbus_creds)) == 0);
+ }
+
-+ if (valid_flags_set & KDBUS_ATTACH_PIDS) {
++ if (valid_flags & KDBUS_ATTACH_PIDS) {
+ item = kdbus_get_item(info, KDBUS_ITEM_PIDS);
+ ASSERT_EXIT(item);
+
@@ -28627,7 +27860,7 @@ index 0000000..5c2bf35
+ * it points to the cached creds.
+ */
+ cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS);
-+ if (invalid_flags_set & KDBUS_ATTACH_CREDS) {
++ if (invalid_flags & KDBUS_ATTACH_CREDS) {
+ ASSERT_EXIT(cnt == 1);
+
+ item = kdbus_get_item(info, KDBUS_ITEM_CREDS);
@@ -28640,7 +27873,7 @@ index 0000000..5c2bf35
+ ASSERT_EXIT(cnt == 0);
+ }
+
-+ if (invalid_flags_set & KDBUS_ATTACH_PIDS) {
++ if (invalid_flags & KDBUS_ATTACH_PIDS) {
+ cnt = kdbus_count_item(info, KDBUS_ITEM_PIDS);
+ ASSERT_EXIT(cnt == 1);
+
@@ -28653,14 +27886,14 @@ index 0000000..5c2bf35
+ }
+
+ cnt = kdbus_count_item(info, KDBUS_ITEM_CGROUP);
-+ if (invalid_flags_set & KDBUS_ATTACH_CGROUP) {
++ if (invalid_flags & KDBUS_ATTACH_CGROUP) {
+ ASSERT_EXIT(cnt == 1);
+ } else {
+ ASSERT_EXIT(cnt == 0);
+ }
+
+ cnt = kdbus_count_item(info, KDBUS_ITEM_CAPS);
-+ if (invalid_flags_set & KDBUS_ATTACH_CAPS) {
++ if (invalid_flags & KDBUS_ATTACH_CAPS) {
+ ASSERT_EXIT(cnt == 1);
+ } else {
+ ASSERT_EXIT(cnt == 0);
@@ -28684,7 +27917,7 @@ index 0000000..5c2bf35
+ ASSERT_RETURN(info->id == conn->id);
+
+ cnt = kdbus_count_item(info, KDBUS_ITEM_OWNED_NAME);
-+ if (valid_flags_set & KDBUS_ATTACH_NAMES) {
++ if (valid_flags & KDBUS_ATTACH_NAMES) {
+ ASSERT_RETURN(cnt == 2);
+ } else {
+ ASSERT_RETURN(cnt == 0);
@@ -28929,10 +28162,10 @@ index 0000000..8bc2386
+}
diff --git a/tools/testing/selftests/kdbus/test-endpoint.c b/tools/testing/selftests/kdbus/test-endpoint.c
new file mode 100644
-index 0000000..dcc6ab9
+index 0000000..34a7be4
--- /dev/null
+++ b/tools/testing/selftests/kdbus/test-endpoint.c
-@@ -0,0 +1,341 @@
+@@ -0,0 +1,352 @@
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
@@ -29190,6 +28423,13 @@ index 0000000..dcc6ab9
+ ep_conn = kdbus_hello(ep, 0, NULL, 0);
+ ASSERT_RETURN(ep_conn);
+
++ /* Check that the reader got the IdAdd notification */
++ ret = kdbus_msg_recv(reader, &msg, NULL);
++ ASSERT_RETURN(ret == 0);
++ ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD);
++ ASSERT_RETURN(msg->items[0].id_change.id == ep_conn->id);
++ kdbus_msg_free(msg);
++
+ /*
+ * Add a name add match on the endpoint connection, acquire name from
+ * the unfiltered connection, and make sure the filtered connection
@@ -29218,7 +28458,7 @@ index 0000000..dcc6ab9
+ ret = kdbus_conn_info(ep_conn, 0x0fffffffffffffffULL, NULL, 0, NULL);
+ ASSERT_RETURN(ret == -ENXIO);
+
-+ /* Check that the reader did not receive anything */
++ /* Check that the reader did not receive the name notification */
+ ret = kdbus_msg_recv(reader, NULL, NULL);
+ ASSERT_RETURN(ret == -EAGAIN);
+
@@ -29230,6 +28470,10 @@ index 0000000..dcc6ab9
+ ret = kdbus_name_release(env->conn, name);
+ ASSERT_RETURN(ret == 0);
+
++ /* Check that the reader did not receive the name notification */
++ ret = kdbus_msg_recv(reader, NULL, NULL);
++ ASSERT_RETURN(ret == -EAGAIN);
++
+ ret = update_endpoint(ep_fd, name);
+ ASSERT_RETURN(ret == 0);
+
@@ -31325,10 +30569,10 @@ index 0000000..f1615da
+}
diff --git a/tools/testing/selftests/kdbus/test-metadata-ns.c b/tools/testing/selftests/kdbus/test-metadata-ns.c
new file mode 100644
-index 0000000..2cb1d4d
+index 0000000..ccdfae0
--- /dev/null
+++ b/tools/testing/selftests/kdbus/test-metadata-ns.c
-@@ -0,0 +1,506 @@
+@@ -0,0 +1,503 @@
+/*
+ * Test metadata in new namespaces. Even if our tests can run
+ * in a namespaced setup, this test is necessary so we can inspect
@@ -31612,16 +30856,13 @@ index 0000000..2cb1d4d
+static int kdbus_clone_userns_test(const char *bus,
+ struct kdbus_conn *conn)
+{
-+ int ret;
-+ int status;
-+ int efd = -1;
++ int ret, status, efd;
+ pid_t pid, ppid;
-+ uint64_t unpriv_conn_id = 0;
-+ uint64_t userns_conn_id = 0;
++ uint64_t unpriv_conn_id, userns_conn_id;
+ struct kdbus_msg *msg;
+ const struct kdbus_item *item;
+ struct kdbus_pids expected_pids;
-+ struct kdbus_conn *monitor = NULL;
++ struct kdbus_conn *monitor;
+
+ kdbus_printf("STARTING TEST 'metadata-ns'.\n");
+