aboutsummaryrefslogtreecommitdiffstats
path: root/0001-kdbus-interprocess-message-router.patch
diff options
Diffstat (limited to '0001-kdbus-interprocess-message-router.patch')
-rw-r--r--0001-kdbus-interprocess-message-router.patch1618
1 files changed, 0 insertions, 1618 deletions
diff --git a/0001-kdbus-interprocess-message-router.patch b/0001-kdbus-interprocess-message-router.patch
deleted file mode 100644
index c563642cdf968c..00000000000000
--- a/0001-kdbus-interprocess-message-router.patch
+++ /dev/null
@@ -1,1618 +0,0 @@
-Subject: kdbus: interprocess message router
-
-Nothing to see here, move along...
-
-
----
- drivers/Kconfig | 2
- drivers/Makefile | 1
- drivers/kdbus/Kconfig | 5
- drivers/kdbus/Makefile | 4
- drivers/kdbus/bus.c | 122 ++++++++
- drivers/kdbus/ep.c | 200 ++++++++++++++
- drivers/kdbus/kdbus.c | 611 +++++++++++++++++++++++++++++++++++++++++++++
- drivers/kdbus/kdbus.h | 185 +++++++++++++
- drivers/kdbus/ns.c | 217 +++++++++++++++
- include/uapi/kdbus/kdbus.h | 123 +++++++++
- include/uapi/linux/major.h | 2
- kdbus.c | 77 +++++
- 12 files changed, 1549 insertions(+)
-
---- a/drivers/Kconfig
-+++ b/drivers/Kconfig
-@@ -158,4 +158,6 @@ source "drivers/irqchip/Kconfig"
-
- source "drivers/ipack/Kconfig"
-
-+source "drivers/kdbus/Kconfig"
-+
- endmenu
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -146,3 +146,4 @@ obj-$(CONFIG_MEMORY) += memory/
- obj-$(CONFIG_IIO) += iio/
- obj-$(CONFIG_VME_BUS) += vme/
- obj-$(CONFIG_IPACK_BUS) += ipack/
-+obj-$(CONFIG_KDBUS) += kdbus/
---- /dev/null
-+++ b/drivers/kdbus/Kconfig
-@@ -0,0 +1,5 @@
-+config KDBUS
-+ tristate "kdbus interprocess message router"
-+ help
-+ kdbus provides efficient kernel-aided message exchange and routing
-+ between processes. It is used as the low-level transport of D-Bus.
---- /dev/null
-+++ b/drivers/kdbus/Makefile
-@@ -0,0 +1,4 @@
-+dbus-y := kdbus.o ep.o bus.o ns.o
-+
-+obj-$(CONFIG_KDBUS) += dbus.o
-+
---- /dev/null
-+++ b/drivers/kdbus/bus.c
-@@ -0,0 +1,122 @@
-+/*
-+ * Copyright (C) 2013 Kay Sievers
-+ * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+ * Copyright (C) 2013 Linux Foundation
-+ *
-+ * kdbus is free software; you can redistribute it and/or modify it under
-+ * the terms of the GNU Lesser General Public License as published by the
-+ * Free Software Foundation; either version 2.1 of the License, or (at
-+ * your option) any later version.
-+ *
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/module.h>
-+#include <linux/device.h>
-+#include <linux/idr.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <uapi/kdbus/kdbus.h>
-+
-+#include "kdbus.h"
-+
-+void kdbus_release(struct device *dev)
-+{
-+ kfree(dev);
-+}
-+
-+
-+struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus)
-+{
-+ if (!bus)
-+ return NULL;
-+ bus->ref++;
-+ return bus;
-+}
-+
-+struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus)
-+{
-+ if (!bus)
-+ return NULL;
-+ bus->ref--;
-+ if (bus->ref > 0)
-+ return bus;
-+
-+ kdbus_bus_disconnect(bus);
-+ pr_info("clean up bus %s/%s\n",
-+ bus->ns->devpath, bus->name);
-+
-+ kfree(bus->name);
-+ kfree(bus);
-+ return NULL;
-+}
-+
-+void kdbus_bus_disconnect(struct kdbus_bus *bus)
-+{
-+ struct kdbus_ep *ep, *tmp;
-+
-+ if (bus->disconnected)
-+ return;
-+ bus->disconnected = true;
-+
-+ /* remove default endpoint */
-+ kdbus_ep_disconnect(bus->ep);
-+ kdbus_ep_unref(bus->ep);
-+
-+ /* remove any endpoints attached to this bus */
-+ list_for_each_entry_safe(ep, tmp, &bus->ep_list, bus_entry) {
-+ kdbus_ep_disconnect(ep);
-+ kdbus_ep_unref(ep);
-+ }
-+
-+ pr_info("closing bus %s/%s\n", bus->ns->devpath, bus->name);
-+}
-+
-+int kdbus_bus_new(struct kdbus_ns *ns, const char *name, umode_t mode,
-+ uid_t uid, gid_t gid, struct kdbus_bus **bus)
-+{
-+ struct kdbus_bus *b;
-+ int err;
-+
-+ b = kzalloc(sizeof(struct kdbus_bus), GFP_KERNEL);
-+ if (!b)
-+ return -ENOMEM;
-+
-+ b->ref = 1;
-+ b->ns = ns;
-+ /* connection 0 == kernel/multi-cast */
-+ b->conn_id_next = 1;
-+ mutex_init(&b->lock);
-+ idr_init(&b->conn_idr);
-+ INIT_LIST_HEAD(&b->ep_list);
-+
-+ if (uid > 0)
-+ b->name = kasprintf(GFP_KERNEL, "%u-%s", uid, name);
-+ else
-+ b->name = kstrdup(name, GFP_KERNEL);
-+ if (!b->name) {
-+ err = -ENOMEM;
-+ goto err;
-+ }
-+
-+ err = kdbus_ep_new(b, "bus", mode, uid, gid, &b->ep);
-+ if (err < 0)
-+ goto err;
-+
-+ mutex_lock(&ns->lock);
-+ b->id = ns->bus_id_next++;
-+ mutex_unlock(&ns->lock);
-+
-+ *bus = b;
-+ pr_info("created bus %llu '%s/%s'\n",
-+ (unsigned long long)b->id, ns->devpath, b->name);
-+ return 0;
-+err:
-+ kdbus_bus_unref(b);
-+ return err;
-+}
-+
-+
---- /dev/null
-+++ b/drivers/kdbus/ep.c
-@@ -0,0 +1,200 @@
-+/*
-+ * Copyright (C) 2013 Kay Sievers
-+ * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+ * Copyright (C) 2013 Linux Foundation
-+ *
-+ * kdbus is free software; you can redistribute it and/or modify it under
-+ * the terms of the GNU Lesser General Public License as published by the
-+ * Free Software Foundation; either version 2.1 of the License, or (at
-+ * your option) any later version.
-+ *
-+ */
-+
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/module.h>
-+#include <linux/device.h>
-+#include <linux/idr.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <uapi/linux/major.h>
-+#include <uapi/kdbus/kdbus.h>
-+
-+#include "kdbus.h"
-+
-+/* endpoints are by default owned by the bus owner */
-+static char *kdbus_devnode_ep(struct device *dev,
-+ umode_t *mode, uid_t *uid, gid_t *gid)
-+{
-+ struct kdbus_ep *ep = dev_get_drvdata(dev);
-+
-+ if (mode)
-+ *mode = ep->mode;
-+ if (uid)
-+ *uid = ep->uid;
-+ if (gid)
-+ *gid = ep->gid;
-+ return NULL;
-+}
-+
-+static struct device_type kdbus_devtype_ep = {
-+ .name = "ep",
-+ .release = kdbus_release,
-+ .devnode = kdbus_devnode_ep,
-+};
-+
-+struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep)
-+{
-+ if (!ep)
-+ return NULL;
-+ ep->ref++;
-+ return ep;
-+}
-+
-+void kdbus_ep_disconnect(struct kdbus_ep *ep)
-+{
-+ if (ep->disconnected)
-+ return;
-+ ep->disconnected = true;
-+
-+ if (ep->dev) {
-+ device_unregister(ep->dev);
-+ ep->dev = NULL;
-+ }
-+ if (ep->minor > 0) {
-+ idr_remove(&ep->bus->ns->idr, ep->minor);
-+ ep->minor = 0;
-+ }
-+ pr_info("closing endpoint %s/%s/%s\n",
-+ ep->bus->ns->devpath, ep->bus->name, ep->name);
-+}
-+
-+struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep)
-+{
-+ if (!ep)
-+ return NULL;
-+ ep->ref--;
-+ if (ep->ref > 0)
-+ return ep;
-+
-+ mutex_lock(&ep->bus->lock);
-+ kdbus_ep_disconnect(ep);
-+ pr_info("clean up endpoint %s/%s/%s\n",
-+ ep->bus->ns->devpath, ep->bus->name, ep->name);
-+ kdbus_bus_unref(ep->bus);
-+ mutex_unlock(&ep->bus->lock);
-+
-+ kfree(ep->name);
-+ kfree(ep);
-+ return NULL;
-+}
-+
-+/* Find the endpoint for a specific bus */
-+struct kdbus_ep *kdbus_ep_find(struct kdbus_bus *bus, const char *name)
-+{
-+ struct kdbus_ep *ep;
-+
-+ mutex_lock(&bus->lock);
-+ list_for_each_entry(ep, &bus->ep_list, bus_entry) {
-+ if (!strcmp(ep->name, name))
-+ goto exit;
-+ }
-+ /* Endpoint not found so return NULL */
-+ ep = NULL;
-+exit:
-+ mutex_unlock(&bus->lock);
-+
-+ return ep;
-+}
-+
-+int kdbus_ep_new(struct kdbus_bus *bus, const char *name, umode_t mode,
-+ uid_t uid, gid_t gid, struct kdbus_ep **ep)
-+{
-+ struct kdbus_ep *e;
-+ int err;
-+ int i;
-+
-+ e = kzalloc(sizeof(struct kdbus_ep), GFP_KERNEL);
-+ if (!e)
-+ return -ENOMEM;
-+
-+ mutex_lock(&bus->ns->lock);
-+ e->ref = 1;
-+ e->mode = mode;
-+ e->uid = uid;
-+ e->gid = gid;
-+
-+ e->name = kstrdup(name, GFP_KERNEL);
-+ if (!e->name) {
-+ err = -ENOMEM;
-+ goto err;
-+ }
-+
-+ /* register minor in our endpoint map */
-+ if (!idr_pre_get(&bus->ns->idr, GFP_KERNEL)) {
-+ err = -ENOMEM;
-+ goto err_unlock;
-+ }
-+ err = idr_get_new_above(&bus->ns->idr, e, 1, &i);
-+ if (err < 0)
-+ goto err_unlock;
-+ e->minor = i;
-+
-+ /* get id for this endpoint from bus */
-+ mutex_lock(&bus->lock);
-+ e->id = bus->ep_id_next++;
-+ mutex_unlock(&bus->lock);
-+
-+ /* register bus endpoint device */
-+ e->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
-+ if (!e->dev)
-+ goto err;
-+ dev_set_name(e->dev, "%s/%s/%s", bus->ns->devpath, bus->name, name);
-+ e->dev->bus = &kdbus_subsys;
-+ e->dev->type = &kdbus_devtype_ep;
-+ e->dev->devt = MKDEV(bus->ns->major, e->minor);
-+ dev_set_drvdata(e->dev, e);
-+ err = device_register(e->dev);
-+ if (err < 0) {
-+ put_device(e->dev);
-+ e->dev = NULL;
-+ }
-+
-+ init_waitqueue_head(&e->wait);
-+
-+ /* Link this endpoint to the bus it is on */
-+ e->bus = kdbus_bus_ref(bus);
-+ list_add_tail(&e->bus_entry, &bus->ep_list);
-+
-+ mutex_unlock(&bus->ns->lock);
-+
-+ if (ep)
-+ *ep = e;
-+ pr_info("created endpoint %llu for bus '%s/%s/%s'\n",
-+ (unsigned long long)e->id, bus->ns->devpath, bus->name, name);
-+ return 0;
-+
-+err_unlock:
-+ mutex_unlock(&bus->ns->lock);
-+err:
-+ kdbus_ep_unref(e);
-+ return err;
-+}
-+
-+int kdbus_ep_remove(struct kdbus_ep *ep)
-+{
-+ struct kdbus_bus *bus = ep->bus;
-+
-+ mutex_lock(&bus->ns->lock);
-+ device_unregister(ep->dev);
-+ list_del(&ep->bus_entry);
-+ kdbus_ep_unref(ep);
-+ mutex_unlock(&bus->ns->lock);
-+ kdbus_bus_unref(bus);
-+ return 0;
-+}
-+
-+
---- /dev/null
-+++ b/drivers/kdbus/kdbus.c
-@@ -0,0 +1,611 @@
-+/*
-+ * kdbus - interprocess message routing
-+ *
-+ * Copyright (C) 2013 Kay Sievers
-+ * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+ * Copyright (C) 2013 Linux Foundation
-+ *
-+ * kdbus is free software; you can redistribute it and/or modify it under
-+ * the terms of the GNU Lesser General Public License as published by the
-+ * Free Software Foundation; either version 2.1 of the License, or (at
-+ * your option) any later version.
-+ *
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/module.h>
-+#include <linux/device.h>
-+#include <linux/idr.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/mutex.h>
-+#include <linux/init.h>
-+#include <linux/poll.h>
-+//#include <asm/uaccess.h>
-+#include <uapi/linux/major.h>
-+#include <uapi/kdbus/kdbus.h>
-+
-+#include "kdbus.h"
-+
-+/*
-+ * TODO:
-+ * - set parent for driver-core /sys/devices/kdbus!... devices to virtual/kdbus/,
-+ * the bus subsys misses the "no parent" logic the class subsys has
-+ *
-+ * - switch to a 64bit idr for connection id <--> kdbus_conn
-+ */
-+
-+/*
-+ * Example of device nodes in /dev. For any future changes, keep in mind,
-+ * that the layout should support a possible /dev/kdbus/ filesystem for the
-+ * init namspace and one for each sub-namespace.
-+ *
-+ * /dev/kdbus/
-+ * |-- control
-+ * |-- system
-+ * | |-- bus
-+ * | |-- ep-epiphany
-+ * | `-- ep-firefox
-+ * |-- 2702-user
-+ * | `-- bus
-+ * |-- 1000-user
-+ * | `-- bus
-+ * `-- ns
-+ * |-- myfedoracontainer
-+ * | |-- control
-+ * | |-- system
-+ * | | `-- bus
-+ * | `-- 1000-user
-+ * | `-- bus
-+ * `-- mydebiancontainer
-+ * |-- control
-+ * |-- system
-+ * `-- bus
-+ */
-+
-+/* kdbus sysfs subsystem */
-+struct bus_type kdbus_subsys = {
-+ .name = "kdbus",
-+};
-+
-+/* List of all connections in the system. */
-+/* Well, really only the endpoint connections,
-+ * that's all we care about for now */
-+static LIST_HEAD(connection_list);
-+
-+/* kdbus initial namespace */
-+static struct kdbus_ns *kdbus_ns_init;
-+
-+/* map of majors to namespaces */
-+DEFINE_IDR(kdbus_ns_major_idr);
-+
-+/* namespace list lock */
-+DEFINE_MUTEX(kdbus_subsys_lock);
-+
-+static int kdbus_msg_new(struct kdbus_conn *conn, struct kdbus_msg __user *umsg,
-+ struct kdbus_msg **msg);
-+static int kdbus_msg_send(struct kdbus_conn *conn, struct kdbus_msg *msg);
-+
-+
-+static void kdbus_msg_release(struct kref *kref)
-+{
-+ struct kdbus_test_msg *msg = container_of(kref, struct kdbus_test_msg, kref);
-+ kfree(msg);
-+}
-+
-+
-+/* kdbus file operations */
-+static int kdbus_conn_open(struct inode *inode, struct file *file)
-+{
-+ struct kdbus_conn *conn;
-+ struct kdbus_ns *ns;
-+ struct kdbus_ep *ep;
-+ int i;
-+ int err;
-+
-+ conn = kzalloc(sizeof(struct kdbus_conn), GFP_KERNEL);
-+ if (!conn)
-+ return -ENOMEM;
-+
-+ /* find and reference namespace */
-+ mutex_lock(&kdbus_subsys_lock);
-+ ns = idr_find(&kdbus_ns_major_idr, MAJOR(inode->i_rdev));
-+ if (!ns || ns->disconnected) {
-+ kfree(conn);
-+ mutex_unlock(&kdbus_subsys_lock);
-+ return -ENOENT;
-+ }
-+ conn->ns = kdbus_ns_ref(ns);
-+ file->private_data = conn;
-+ mutex_unlock(&kdbus_subsys_lock);
-+
-+ /* control device node */
-+ if (MINOR(inode->i_rdev) == 0) {
-+ conn->type = KDBUS_CONN_CONTROL;
-+ file->private_data = conn;
-+ pr_info("opened control device '%s/control'\n",
-+ conn->ns->devpath);
-+ return 0;
-+ }
-+
-+ /* find endpoint for device node */
-+ mutex_lock(&conn->ns->lock);
-+ ep = idr_find(&conn->ns->idr, MINOR(inode->i_rdev));
-+ if (!ep || ep->disconnected) {
-+ err = -ENOENT;
-+ goto err_unlock;
-+ }
-+
-+ /* create endpoint connection */
-+ conn->type = KDBUS_CONN_EP;
-+ conn->ep = kdbus_ep_ref(ep);
-+
-+ /* get and register new id for this connection */
-+ conn->id = conn->ep->bus->conn_id_next++;
-+ if (!idr_pre_get(&conn->ep->bus->conn_idr, GFP_KERNEL)) {
-+ err = -ENOMEM;
-+ goto err_unlock;
-+ }
-+ /* FIXME: get 64 bit working, this will fail for the 2^31th connection */
-+ err = idr_get_new_above(&conn->ep->bus->conn_idr, conn, conn->id, &i);
-+ if (err >= 0 && conn->id != i) {
-+ idr_remove(&conn->ep->bus->conn_idr, i);
-+ err = -EEXIST;
-+ goto err_unlock;
-+ }
-+
-+ mutex_init(&conn->msg_lock);
-+ INIT_LIST_HEAD(&conn->msg_list);
-+
-+ list_add_tail(&connection_list, &conn->connection_entry);
-+
-+ file->private_data = conn;
-+ mutex_unlock(&conn->ns->lock);
-+
-+ pr_info("created endpoint bus connection %llu '%s/%s'\n",
-+ (unsigned long long)conn->id, conn->ns->devpath,
-+ conn->ep->bus->name);
-+ return 0;
-+
-+err_unlock:
-+ mutex_unlock(&conn->ns->lock);
-+ kfree(conn);
-+ return err;
-+}
-+
-+static int kdbus_conn_release(struct inode *inode, struct file *file)
-+{
-+ struct kdbus_conn *conn = file->private_data;
-+ struct kdbus_test_msg *msg;
-+ struct kdbus_msg_list_entry *msg_entry, *tmp_entry;
-+
-+ switch (conn->type) {
-+ case KDBUS_CONN_NS_OWNER:
-+ break;
-+
-+ case KDBUS_CONN_BUS_OWNER:
-+ kdbus_bus_disconnect(conn->bus_owner);
-+ kdbus_bus_unref(conn->bus_owner);
-+ break;
-+
-+ case KDBUS_CONN_EP:
-+ kdbus_ep_unref(conn->ep);
-+ list_del(&conn->connection_entry);
-+ /* clean up any messages still left on this endpoint */
-+ mutex_lock(&conn->msg_lock);
-+ list_for_each_entry_safe(msg_entry, tmp_entry, &conn->msg_list, entry) {
-+ msg = msg_entry->msg;
-+ list_del(&msg_entry->entry);
-+ kfree(msg_entry);
-+ kref_put(&msg->kref, kdbus_msg_release);
-+ }
-+ mutex_unlock(&conn->msg_lock);
-+
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ mutex_lock(&conn->ns->lock);
-+ kdbus_ns_unref(conn->ns);
-+ mutex_unlock(&conn->ns->lock);
-+ kfree(conn);
-+ return 0;
-+}
-+
-+/* kdbus control device commands */
-+static long kdbus_conn_ioctl_control(struct file *file, unsigned int cmd,
-+ void __user *argp)
-+{
-+ struct kdbus_conn *conn = file->private_data;
-+ struct kdbus_cmd_name name;
-+ struct kdbus_bus *bus = NULL;
-+ struct kdbus_ns *ns = NULL;
-+ int err;
-+
-+ switch (cmd) {
-+ case KDBUS_CMD_BUS_CREATE:
-+ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
-+ return -EFAULT;
-+
-+ err = kdbus_bus_new(conn->ns, name.name,
-+ 0660, current_fsuid(), current_fsgid(),
-+ &bus);
-+ if (err < 0)
-+ return err;
-+
-+ /* turn the control fd into a new bus owner device */
-+ conn->type = KDBUS_CONN_BUS_OWNER;
-+ conn->bus_owner = bus;
-+ break;
-+
-+#if 0 /* FIXME Don't know if we really want this... */
-+ case KDBUS_CMD_BUS_REMOVE:
-+ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
-+ return -EFAULT;
-+
-+ bus = kdbus_bus_find(name.name);
-+ if (!bus)
-+ return -EINVAL;
-+ kdbus_bus_disconnect(bus); // FIXME needed?
-+ kdbus_bus_unref(bus);
-+ break;
-+#endif
-+ case KDBUS_CMD_NS_CREATE:
-+ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
-+ return -EFAULT;
-+
-+ err = kdbus_ns_new(kdbus_ns_init, name.name, &ns);
-+ if (err < 0) {
-+ pr_err("failed to create namespace %s, err=%i\n",
-+ name.name, err);
-+ return err;
-+ }
-+ break;
-+
-+ case KDBUS_CMD_NS_REMOVE:
-+ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
-+ return -EFAULT;
-+
-+ ns = kdbus_ns_find(name.name);
-+ if (!ns)
-+ return -EINVAL;
-+
-+ /* we can not remove the "default" namespace */
-+ if (ns == kdbus_ns_init)
-+ return -EINVAL;
-+
-+ kdbus_ns_unref(ns);
-+ break;
-+
-+ default:
-+ return -ENOTTY;
-+ }
-+ return 0;
-+}
-+
-+/* kdbus bus endpoint commands */
-+static long kdbus_conn_ioctl_ep(struct file *file, unsigned int cmd,
-+ void __user *argp)
-+{
-+ struct kdbus_conn *conn = file->private_data;
-+ struct kdbus_cmd_name name;
-+ struct kdbus_msg *msg;
-+ struct kdbus_ep *ep;
-+ long err;
-+
-+ /* We need a connection before we can do anything with an ioctl */
-+ if (!conn)
-+ return -EINVAL;
-+
-+ switch (cmd) {
-+ case KDBUS_CMD_EP_CREATE:
-+ /* create a new endpoint for this bus */
-+ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
-+ return -EFAULT;
-+ return kdbus_ep_new(conn->ep->bus, name.name,
-+ 0660, current_fsuid(), current_fsgid(),
-+ NULL);
-+
-+ case KDBUS_CMD_EP_REMOVE:
-+ /* remove an endpoint from this bus */
-+ if (copy_from_user(&name, argp, sizeof(struct kdbus_cmd_name)))
-+ return -EFAULT;
-+ ep = kdbus_ep_find(conn->bus_owner, name.name);
-+ if (!ep)
-+ return -EINVAL;
-+
-+ return kdbus_ep_remove(ep);
-+
-+ case KDBUS_CMD_EP_POLICY_SET:
-+ /* upload a policy for this bus */
-+ return -ENOSYS;
-+
-+ case KDBUS_CMD_NAME_ACQUIRE:
-+ /* acquire a well-known name */
-+ return -ENOSYS;
-+
-+ case KDBUS_CMD_NAME_RELEASE:
-+ /* release a well-known name */
-+ return -ENOSYS;
-+
-+ case KDBUS_CMD_NAME_LIST:
-+ /* return all current well-known names */
-+ return -ENOSYS;
-+
-+ case KDBUS_CMD_MATCH_ADD:
-+ /* subscribe to/filter for broadcast messages */
-+ return -ENOSYS;
-+
-+ case KDBUS_CMD_MATCH_REMOVE:
-+ /* unsubscribe from broadcast messages */
-+ return -ENOSYS;
-+
-+ case KDBUS_CMD_MSG_SEND:
-+ /* send a message */
-+ err = kdbus_msg_new(conn, argp, &msg);
-+ if (err < 0)
-+ return err;
-+ return kdbus_msg_send(conn, msg);
-+
-+ case KDBUS_CMD_MSG_RECV:
-+ /* receive a message, needs to be freed */
-+ return -ENOSYS;
-+
-+ default:
-+ return -ENOTTY;
-+ }
-+}
-+
-+static long kdbus_conn_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+ struct kdbus_conn *conn = file->private_data;
-+ void __user *argp = (void __user *)arg;
-+
-+ pr_info("%s, cmd=%d\n", __func__, cmd);
-+ switch (conn->type) {
-+ case KDBUS_CONN_CONTROL:
-+ pr_info("control ioctl\n");
-+ return kdbus_conn_ioctl_control(file, cmd, argp);
-+
-+ case KDBUS_CONN_EP:
-+ pr_info("endpoint ioctl\n");
-+ return kdbus_conn_ioctl_ep(file, cmd, argp);
-+
-+ default:
-+ pr_info("bad type\n");
-+ return -EINVAL;
-+ }
-+}
-+
-+static unsigned int kdbus_conn_poll(struct file *file,
-+ struct poll_table_struct *wait)
-+{
-+ struct kdbus_conn *conn = file->private_data;
-+ unsigned int mask = 0;
-+
-+ /* Only an endpoint can read/write data */
-+ if (conn->type != KDBUS_CONN_EP)
-+ return POLLERR | POLLHUP;
-+
-+ poll_wait(file, &conn->ep->wait, wait);
-+
-+ mutex_lock(&conn->msg_lock);
-+ if (!list_empty(&conn->msg_list))
-+ mask |= POLLIN | POLLRDNORM;
-+ mutex_unlock(&conn->msg_lock);
-+
-+ return 0;
-+}
-+
-+static int kdbus_conn_mmap(struct file *file, struct vm_area_struct *vma)
-+{
-+ return -EINVAL;
-+}
-+
-+static ssize_t kdbus_conn_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos)
-+{
-+ struct kdbus_conn *conn = file->private_data;
-+ struct kdbus_conn *temp_conn;
-+ struct kdbus_test_msg *msg;
-+
-+ /* Only an endpoint can read/write data */
-+ if (conn->type != KDBUS_CONN_EP)
-+ return -EINVAL;
-+
-+ /* FIXME: Let's cap a message size at PAGE_SIZE for now */
-+ if (count > PAGE_SIZE)
-+ return -EINVAL;
-+
-+ if (count == 0)
-+ return 0;
-+
-+ msg = kmalloc((sizeof(*msg) + count), GFP_KERNEL);
-+ if (!msg)
-+ return -ENOMEM;
-+
-+ if (copy_from_user(&msg->data[0], ubuf, count))
-+ return -EFAULT;
-+
-+ kref_init(&msg->kref);
-+ msg->length = count;
-+
-+ /* Walk the list of connections,
-+ * find any endpoints that match our endpoint,
-+ * create a kdbus_msg_list_entry for it,
-+ * attach the message to the endpoint list,
-+ * wake the connection up. */
-+
-+ /* what do we lock here? FIXME */
-+
-+ list_for_each_entry(temp_conn, &connection_list, connection_entry) {
-+ if (temp_conn->type != KDBUS_CONN_EP)
-+ continue;
-+ if (temp_conn->ep == conn->ep) {
-+ /* Matching endpoints */
-+ struct kdbus_msg_list_entry *msg_list_entry;
-+
-+ msg_list_entry = kmalloc(sizeof(*msg_list_entry), GFP_KERNEL);
-+ kref_get(&msg->kref);
-+ msg_list_entry->msg = msg;
-+ mutex_lock(&temp_conn->msg_lock);
-+ list_add_tail(&temp_conn->msg_list, &msg_list_entry->entry);
-+ mutex_unlock(&temp_conn->msg_lock);
-+ /* wake up the other processes. Hopefully... */
-+ wake_up_interruptible_all(&temp_conn->ep->wait);
-+ }
-+ }
-+
-+ /* drop our reference on the message, as we are done with it */
-+ kref_put(&msg->kref, kdbus_msg_release);
-+ return count;
-+}
-+
-+static ssize_t kdbus_conn_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos)
-+{
-+ struct kdbus_conn *conn = file->private_data;
-+ struct kdbus_msg_list_entry *msg_list_entry;
-+ struct kdbus_test_msg *msg;
-+ ssize_t retval = 0;
-+
-+ /* Only an endpoint can read/write data */
-+ if (conn->type != KDBUS_CONN_EP)
-+ return -EINVAL;
-+
-+ if (count == 0)
-+ return 0;
-+
-+ if (mutex_lock_interruptible(&conn->msg_lock))
-+ return -ERESTARTSYS;
-+
-+ while (list_empty(&conn->msg_list)) {
-+ /* Nothing to read, so try again or sleep */
-+ mutex_unlock(&conn->msg_lock);
-+
-+ if (file->f_flags & O_NONBLOCK)
-+ return -EAGAIN;
-+
-+ /* sleep until we get something */
-+ if (wait_event_interruptible(conn->ep->wait, list_empty(&conn->msg_list)))
-+ return -ERESTARTSYS;
-+
-+ if (mutex_lock_interruptible(&conn->msg_lock))
-+ return -ERESTARTSYS;
-+ }
-+
-+ /* let's grab a message from our list to write out */
-+ if (!list_empty(&conn->msg_list)) {
-+ msg_list_entry = list_entry(&conn->msg_list, struct kdbus_msg_list_entry, entry);
-+ msg = msg_list_entry->msg;
-+ if (msg->length > count) {
-+ retval = -E2BIG; // FIXME wrong error code, I know, what should we use?
-+ goto exit;
-+ }
-+ if (copy_to_user(ubuf, &msg->data[0], msg->length)) {
-+ retval = -EFAULT;
-+ goto exit;
-+ }
-+ list_del(&msg_list_entry->entry);
-+ kfree(msg_list_entry);
-+ retval = msg->length;
-+ kref_put(&msg->kref, kdbus_msg_release);
-+ }
-+
-+exit:
-+ mutex_unlock(&conn->msg_lock);
-+ return retval;
-+}
-+
-+const struct file_operations kdbus_device_ops = {
-+ .owner = THIS_MODULE,
-+ .open = kdbus_conn_open,
-+ .release = kdbus_conn_release,
-+ .unlocked_ioctl = kdbus_conn_ioctl,
-+ .compat_ioctl = kdbus_conn_ioctl,
-+ .poll = kdbus_conn_poll,
-+ .mmap = kdbus_conn_mmap,
-+ .llseek = noop_llseek,
-+ .write = kdbus_conn_write,
-+ .read = kdbus_conn_read,
-+};
-+
-+static void kdbus_msg_free(struct kdbus_msg *msg)
-+{
-+ kfree(msg);
-+}
-+
-+static int kdbus_msg_new(struct kdbus_conn *conn, struct kdbus_msg __user *umsg,
-+ struct kdbus_msg **msg)
-+{
-+ struct kdbus_msg *m;
-+ int err;
-+
-+ m = kmalloc(sizeof(struct kdbus_msg), GFP_KERNEL);
-+ if (!m)
-+ return -ENOMEM;
-+ if (copy_from_user(m, umsg, sizeof(struct kdbus_msg))) {
-+ err = -EFAULT;
-+ goto out_err;
-+ }
-+
-+ m->src_id = conn->id;
-+ m->msg_id = conn->ep->bus->msg_id_next++;
-+ *msg = m;
-+ return 0;
-+out_err:
-+ kdbus_msg_free(m);
-+ return err;
-+}
-+
-+static int kdbus_msg_send(struct kdbus_conn *conn, struct kdbus_msg *msg)
-+{
-+ struct kdbus_conn *conn_dst;
-+
-+ conn_dst = idr_find(&conn->ep->bus->conn_idr, msg->dst_id);
-+ if (!conn_dst)
-+ return -ENOENT;
-+
-+ pr_info("sending message %llu from %llu to %llu\n",
-+ (unsigned long long)msg->msg_id,
-+ (unsigned long long)msg->src_id,
-+ (unsigned long long)msg->dst_id);
-+
-+ kdbus_msg_free(msg);
-+ return 0;
-+}
-+
-+static int __init kdbus_init(void)
-+{
-+ int err;
-+
-+ err = bus_register(&kdbus_subsys);
-+ if (err < 0)
-+ return err;
-+
-+ err = kdbus_ns_new(NULL, NULL, &kdbus_ns_init);
-+ if (err < 0) {
-+ bus_unregister(&kdbus_subsys);
-+ pr_err("failed to initialize err=%i\n", err);
-+ return err;
-+ }
-+
-+ pr_info("initialized\n");
-+ return 0;
-+}
-+
-+static void __exit kdbus_exit(void)
-+{
-+ kdbus_ns_unref(kdbus_ns_init);
-+ bus_unregister(&kdbus_subsys);
-+ pr_info("unloaded\n");
-+}
-+
-+module_init(kdbus_init);
-+module_exit(kdbus_exit);
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("kdbus interprocess message router");
-+MODULE_ALIAS_CHARDEV(KDBUS_CHAR_MAJOR, 0);
-+MODULE_ALIAS("devname:kdbus/control");
---- /dev/null
-+++ b/drivers/kdbus/kdbus.h
-@@ -0,0 +1,185 @@
-+/*
-+ * Copyright (C) 2013 Kay Sievers
-+ * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+ * Copyright (C) 2013 Linux Foundation
-+ *
-+ * kdbus is free software; you can redistribute it and/or modify it under
-+ * the terms of the GNU Lesser General Public License as published by the
-+ * Free Software Foundation; either version 2.1 of the License, or (at
-+ * your option) any later version.
-+ *
-+ */
-+
-+
-+#ifndef __INTERNAL_KDBUS_H
-+#define __INTERNAL_KDBUS_H
-+
-+/*
-+ * kdbus namespace
-+ * - provides a "control" node
-+ * - owns a major number
-+ * - owns all created buses
-+ * - the initial namespace is unnamed and stays around for forver
-+ * - new namespaces are created by opening the control node and
-+ * issuing KDBUS_NS_CREATE
-+ * - closing the connection destroys the created namespace
-+ */
-+struct kdbus_ns {
-+ unsigned int ref; /* reference count */
-+ const char *name; /* name of the namespace */
-+ bool disconnected; /* invalidated data */
-+ struct kdbus_ns *parent;/* parent namespace */
-+ __u64 id; /* global id of this namespace */
-+ const char *devpath; /* /dev base directory path */
-+ int major; /* device major number for all nodes */
-+ struct idr idr; /* map of endpoint minors to buses */
-+ struct device *dev; /* control device node, minor == 0 */
-+ struct mutex lock; /* ns data lock */
-+ __u64 bus_id_next; /* next bus id sequence number */
-+ struct list_head list_entry;
-+};
-+
-+/*
-+ * kdbus bus
-+ * - provides a "bus" endpoint
-+ * - owns additional endpoints
-+ * - own all bus connections
-+ * - new buses are created by opening the control node and
-+ * issuing KDBUS_BUS_CREATE
-+ * - closing the connection destroys the created bus
-+ */
-+struct kdbus_bus {
-+ unsigned int ref; /* reference count */
-+ bool disconnected; /* invalidated data */
-+ struct kdbus_ns *ns; /* namespace of this bus */
-+ const char *name; /* bus name */
-+ __u64 id; /* id of this bus in the namespace */
-+ struct mutex lock; /* bus data lock */
-+ __u64 ep_id_next; /* next endpoint id sequence number */
-+ __u64 conn_id_next; /* next connection id sequence number */
-+ __u64 msg_id_next; /* next message id sequence number */
-+ struct idr conn_idr; /* map of connection ids */
-+ struct kdbus_ep *ep; /* "bus" default endpoint */
-+ struct list_head ep_list; /* endpoints assigned to this bus */
-+};
-+
-+/*
-+ * kdbus endpoint
-+ * - offers access to a bus, the default device node name is "bus"
-+ * - additional endpoints can carry a specific policy/filters
-+ */
-+struct kdbus_ep {
-+ unsigned int ref; /* reference count */
-+ bool disconnected; /* invalidated data */
-+ struct kdbus_bus *bus; /* bus behind this endpoint */
-+ const char *name; /* name, prefixed with uid */
-+ __u64 id; /* id of this endpoint on the bus */
-+ unsigned int minor; /* minor of this endpoint in the namespace major */
-+ struct device *dev; /* device node of this endpoint */
-+ umode_t mode; /* file mode of this endpoint device node */
-+ uid_t uid; /* uid owning this endpoint */
-+ gid_t gid; /* gid owning this endpoint */
-+ struct list_head bus_entry; /* list of endpoints for this bus */
-+ struct list_head message_list; /* messages in flight for this endpoint */
-+ wait_queue_head_t wait; /* wake up this endpoint */
-+};
-+
-+/*
-+ * kdbus connection
-+ * - connection to a control node or an endpoint
-+ */
-+enum kdbus_conn_type {
-+ KDBUS_CONN_UNDEFINED,
-+ KDBUS_CONN_CONTROL,
-+ KDBUS_CONN_NS_OWNER,
-+ KDBUS_CONN_BUS_OWNER,
-+ KDBUS_CONN_EP,
-+};
-+
-+struct kdbus_conn {
-+ enum kdbus_conn_type type;
-+ struct kdbus_ns *ns;
-+ union {
-+ struct kdbus_ns *ns_owner;
-+ struct kdbus_bus *bus_owner;
-+ struct kdbus_ep *ep;
-+ };
-+ __u64 id; /* id of the connection on the bus */
-+
-+ /*
-+ * first, horrible cut at messages assigned to connections
-+ * odds are, this is going to be slow, but let's measure it first to
-+ * see what the real numbers are, and where the bottlenecks are.
-+ * Premature optimization and all...
-+ */
-+ struct mutex msg_lock;
-+ struct list_head msg_list;
-+
-+ /* Ugh a list of all connections in the system? Ugly, but we need to
-+ * be able to walk them all somehow. Maybe just have a list on the
-+ * endpoints of the connections associated with that endpoint? That's
-+ * all we really need in the end... */
-+ struct list_head connection_entry;
-+};
-+
-+/* kdbus message */
-+enum kdbus_msg_data_type {
-+ KDBUS_MSG_DATA_UNDEFINED,
-+ KDBUS_MSG_DATA_MEM,
-+};
-+
-+struct kdbus_msg_data {
-+ u64 data;
-+ u64 size;
-+ u32 type;
-+ u32 flags;
-+};
-+
-+/* To knock around with for now */
-+struct kdbus_test_msg {
-+ struct kref kref;
-+ u32 length;
-+ u8 data[0];
-+};
-+
-+struct kdbus_msg_list_entry {
-+ struct kdbus_test_msg *msg;
-+ struct list_head entry;
-+};
-+
-+/* namespace stuff */
-+
-+extern const struct file_operations kdbus_device_ops;
-+extern struct mutex kdbus_subsys_lock;
-+extern struct idr kdbus_ns_major_idr;
-+struct kdbus_ns *kdbus_ns_ref(struct kdbus_ns *ns);
-+void kdbus_ns_disconnect(struct kdbus_ns *ns);
-+struct kdbus_ns *kdbus_ns_unref(struct kdbus_ns *ns);
-+int kdbus_ns_new(struct kdbus_ns *parent, const char *name, struct kdbus_ns **ns);
-+struct kdbus_ns *kdbus_ns_find(const char *name);
-+
-+
-+/* bus stuff */
-+extern struct bus_type kdbus_subsys;
-+void kdbus_release(struct device *dev);
-+
-+struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus);
-+struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus);
-+void kdbus_bus_disconnect(struct kdbus_bus *bus);
-+int kdbus_bus_new(struct kdbus_ns *ns, const char *name, umode_t mode,
-+ uid_t uid, gid_t gid, struct kdbus_bus **bus);
-+
-+
-+/* endpoint stuff */
-+struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep);
-+struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep);
-+
-+struct kdbus_ep *kdbus_ep_find(struct kdbus_bus *bus, const char *name);
-+int kdbus_ep_new(struct kdbus_bus *bus, const char *name, umode_t mode,
-+ uid_t uid, gid_t gid, struct kdbus_ep **ep);
-+int kdbus_ep_remove(struct kdbus_ep *ep);
-+void kdbus_ep_disconnect(struct kdbus_ep *ep);
-+
-+
-+
-+#endif
---- /dev/null
-+++ b/drivers/kdbus/ns.c
-@@ -0,0 +1,217 @@
-+/*
-+ * Copyright (C) 2013 Kay Sievers
-+ * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+ * Copyright (C) 2013 Linux Foundation
-+ *
-+ * kdbus is free software; you can redistribute it and/or modify it under
-+ * the terms of the GNU Lesser General Public License as published by the
-+ * Free Software Foundation; either version 2.1 of the License, or (at
-+ * your option) any later version.
-+ *
-+ */
-+
-+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-+
-+#include <linux/module.h>
-+#include <linux/device.h>
-+#include <linux/idr.h>
-+#include <linux/fs.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+#include <linux/init.h>
-+#include <uapi/linux/major.h>
-+#include <uapi/kdbus/kdbus.h>
-+
-+#include "kdbus.h"
-+
-+/* global list of all namespaces */
-+static LIST_HEAD(namespace_list);
-+
-+/* next namespace id sequence number */
-+static __u64 kdbus_ns_id_next;
-+
-+/* control nodes are world accessible */
-+static char *kdbus_devnode_control(struct device *dev,
-+ umode_t *mode, uid_t *uid, gid_t *gid)
-+{
-+ if (mode)
-+ *mode = 0666;
-+ return NULL;
-+}
-+
-+static struct device_type kdbus_devtype_control = {
-+ .name = "control",
-+ .release = kdbus_release,
-+ .devnode = kdbus_devnode_control,
-+};
-+
-+
-+/* kdbus namespace */
-+struct kdbus_ns *kdbus_ns_ref(struct kdbus_ns *ns)
-+{
-+ if (!ns)
-+ return NULL;
-+ ns->ref++;
-+ return ns;
-+}
-+
-+void kdbus_ns_disconnect(struct kdbus_ns *ns)
-+{
-+ if (ns->disconnected)
-+ return;
-+ ns->disconnected = true;
-+
-+ if (ns->dev) {
-+ device_unregister(ns->dev);
-+ ns->dev = NULL;
-+ }
-+ if (ns->major > 0) {
-+ idr_remove(&kdbus_ns_major_idr, ns->major);
-+ unregister_chrdev(ns->major, "kdbus");
-+ ns->major = 0;
-+ }
-+ pr_info("closing namespace %s\n", ns->devpath);
-+}
-+
-+struct kdbus_ns *kdbus_ns_unref(struct kdbus_ns *ns)
-+{
-+ if (!ns)
-+ return NULL;
-+ ns->ref--;
-+ if (ns->ref > 0)
-+ return ns;
-+
-+ kdbus_ns_disconnect(ns);
-+ pr_info("clean up namespace %s\n", ns->devpath);
-+ list_del(&ns->list_entry);
-+ kfree(ns->name);
-+ kfree(ns->devpath);
-+ kfree(ns);
-+ return NULL;
-+}
-+
-+int kdbus_ns_new(struct kdbus_ns *parent, const char *name, struct kdbus_ns **ns)
-+{
-+ struct kdbus_ns *n;
-+ const char *ns_name = NULL;
-+ int i;
-+ int err;
-+
-+ pr_info("%s, %s\n", __func__, name);
-+
-+ if ((parent && !name) || (!parent && name))
-+ return -EINVAL;
-+
-+ n = kzalloc(sizeof(struct kdbus_ns), GFP_KERNEL);
-+ if (!n)
-+ return -ENOMEM;
-+
-+ if (name) {
-+ ns_name = kstrdup(name, GFP_KERNEL);
-+ if (!ns_name) {
-+ kfree(n);
-+ return -ENOMEM;
-+ }
-+ }
-+
-+ n->ref = 1;
-+ idr_init(&n->idr);
-+ mutex_init(&n->lock);
-+
-+ /* compose name and path of base directory in /dev */
-+ if (!parent) {
-+ /* initial namespace */
-+ n->devpath = kstrdup("kdbus", GFP_KERNEL);
-+ if (!n->devpath) {
-+ err = -ENOMEM;
-+ goto err;
-+ }
-+
-+ /* register static major to support module auto-loading */
-+ err = register_chrdev(KDBUS_CHAR_MAJOR, "kdbus", &kdbus_device_ops);
-+ if (err)
-+ goto err;
-+ n->major = KDBUS_CHAR_MAJOR;
-+ } else {
-+ n->parent = parent;
-+ n->devpath = kasprintf(GFP_KERNEL, "kdbus/ns/%s/%s", parent->devpath, name);
-+// n->devpath = kasprintf(GFP_KERNEL, "kdbus/ns/%s", name);
-+ if (!n->devpath) {
-+ err = -ENOMEM;
-+ goto err;
-+ }
-+
-+ /* get dynamic major */
-+ n->major = register_chrdev(0, "kdbus", &kdbus_device_ops);
-+ if (n->major < 0) {
-+ err = n->major;
-+ goto err;
-+ }
-+ n->name = ns_name;
-+ }
-+
-+ /* register major in our namespace map */
-+ mutex_lock(&kdbus_subsys_lock);
-+ if (!idr_pre_get(&kdbus_ns_major_idr, GFP_KERNEL)) {
-+ err = -ENOMEM;
-+ goto err_unlock;
-+ }
-+ err = idr_get_new_above(&kdbus_ns_major_idr, n, n->major, &i);
-+ if (err >= 0 && n->major != i) {
-+ idr_remove(&kdbus_ns_major_idr, i);
-+ err = -EEXIST;
-+ goto err_unlock;
-+ }
-+
-+ /* get id for this namespace */
-+ n->id = kdbus_ns_id_next++;
-+
-+ /* register control device for this namespace */
-+ n->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
-+ if (!n->dev)
-+ goto err_unlock;
-+ dev_set_name(n->dev, "%s/%s", n->devpath, "control");
-+ n->dev->bus = &kdbus_subsys;
-+ n->dev->type = &kdbus_devtype_control;
-+ n->dev->devt = MKDEV(n->major, 0);
-+ dev_set_drvdata(n->dev, n);
-+ err = device_register(n->dev);
-+ if (err < 0) {
-+ put_device(n->dev);
-+ n->dev = NULL;
-+ goto err_unlock;
-+ }
-+
-+ /* Add to global list of namespaces so we can find it again */
-+ list_add_tail(&n->list_entry, &namespace_list);
-+
-+ mutex_unlock(&kdbus_subsys_lock);
-+
-+ *ns = n;
-+ pr_info("created namespace %llu '%s/'\n",
-+ (unsigned long long)n->id, n->devpath);
-+ return 0;
-+
-+err_unlock:
-+ mutex_unlock(&kdbus_subsys_lock);
-+err:
-+ kdbus_ns_unref(n);
-+ return err;
-+}
-+
-+struct kdbus_ns *kdbus_ns_find(const char *name)
-+{
-+ struct kdbus_ns *ns;
-+
-+ mutex_lock(&kdbus_subsys_lock);
-+ list_for_each_entry(ns, &namespace_list, list_entry) {
-+ if (!strcmp(ns->name, name))
-+ goto exit;
-+ }
-+ /* namespace not found so return NULL */
-+ ns = NULL;
-+exit:
-+ mutex_unlock(&kdbus_subsys_lock);
-+ return ns;
-+}
-+
---- /dev/null
-+++ b/include/uapi/kdbus/kdbus.h
-@@ -0,0 +1,123 @@
-+/*
-+ * Copyright (C) 2013 Kay Sievers
-+ * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-+ * Copyright (C) 2013 Linux Foundation
-+ *
-+ * kdbus is free software; you can redistribute it and/or modify it under
-+ * the terms of the GNU Lesser General Public License as published by the
-+ * Free Software Foundation; either version 2.1 of the License, or (at
-+ * your option) any later version.
-+ *
-+ */
-+
-+#ifndef _KDBUS_H_
-+#define _KDBUS_H_
-+
-+#define KDBUS_IOC_MAGIC 0x95
-+
-+/* kdbus control device commands */
-+struct kdbus_cmd_name {
-+ uint64_t capabilities;
-+ char name[256];
-+ char reserved[256];
-+};
-+
-+struct kdbus_fake_message {
-+ char msg[256]; /* FIXME obviously... */
-+};
-+
-+/**
-+ * struct kdbus_msg
-+ *
-+ * set by userspace:
-+ * dst_id: destination id
-+ * filter: bloom filter for the kernel to use to filter messages
-+ * data_count: number of data structures for this message
-+ * data: data for the message
-+ *
-+ * set by kernel:
-+ * msg_id: message id, to allow userspace to sort messages
-+ * src_id: who sent the message
-+ * src_uid: uid of sending process
-+ * src_gid: gid of sending process
-+ * src_pid: pid of sending process
-+ * src_tid: tid of sending process
-+ * ts_nsec: timestamp when message was sent to the kernel
-+ *
-+ */
-+struct kdbus_msg {
-+ __u64 dst_id;
-+ __u64 filter;
-+
-+ __u64 msg_id;
-+ __u64 src_id;
-+ __u64 flags;
-+ __kernel_uid_t src_uid;
-+ __kernel_gid_t src_gid;
-+ __kernel_pid_t src_pid;
-+ __kernel_pid_t src_tid;
-+ __u64 ts_nsec;
-+ __u64 reserved[8];
-+ __u32 data_count;
-+ struct kdbus_msg_data *data;
-+};
-+
-+
-+
-+#if 0
-+/* Old-style dbus had the following message type: */
-+struct old_dbus_header {
-+ u8 endianness; /* 'l' for little endian, 'B' for big endian */
-+ u8 type; /* message type */
-+ u8 flags;
-+ u8 protocol_version;
-+ u32 message_length
-+ u32 cookie;
-+}
-+
-+#define DBUS_TYPE_INVALID 0
-+#define DBUS_TYPE_METHOD_CALL 1
-+#define DBUS_TYPE_METHOD_RETURN 2
-+#define DBUS_TYPE_ERROR 3
-+#define DBUS_TYPE_SIGNAL 4
-+
-+#define DBUS_FLAG_NO_REPLY_EXPECTED 0x01
-+#define DBUS_FLAG_NO_AUTO_START 0x02
-+
-+#define DBUS_FIELD_INVALID 0
-+#define DBUS_FIELD_PATH 1
-+#define DBUS_FIELD_INTERFACE 2
-+#define DBUS_FIELD_MEMBER 3
-+#define DBUS_FIELD_ERROR_NAME 4
-+#define DBUS_FIELD_REPLY_SERIAL 5
-+#define DBUS_FIELD_DESTINATION 6
-+#define DBUS_FIELD_SENDER 7
-+#define DBUS_FIELD_SIGNATURE 8
-+#define DBUS_FIELD_UNIX_FDS 9
-+
-+#endif
-+
-+enum kdbus_cmd {
-+ /* kdbus control commands */
-+ KDBUS_CMD_BUS_CREATE = _IOW(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_name),
-+ KDBUS_CMD_BUS_REMOVE = _IOW(KDBUS_IOC_MAGIC, 0x01, struct kdbus_cmd_name),
-+ KDBUS_CMD_NS_CREATE = _IOW(KDBUS_IOC_MAGIC, 0x10, struct kdbus_cmd_name),
-+ KDBUS_CMD_NS_REMOVE = _IOW(KDBUS_IOC_MAGIC, 0x11, struct kdbus_cmd_name),
-+
-+ /* kdbus endpoint commands */
-+ KDBUS_CMD_EP_CREATE = _IOWR(KDBUS_IOC_MAGIC, 0x30, struct kdbus_cmd_name),
-+ KDBUS_CMD_EP_REMOVE = _IOWR(KDBUS_IOC_MAGIC, 0x31, struct kdbus_cmd_name),
-+ KDBUS_CMD_EP_POLICY_SET = _IOWR(KDBUS_IOC_MAGIC, 0x32, int),
-+
-+ KDBUS_CMD_NAME_ACQUIRE = _IOWR(KDBUS_IOC_MAGIC, 0x50, int),
-+ KDBUS_CMD_NAME_RELEASE = _IOWR(KDBUS_IOC_MAGIC, 0x51, int),
-+ KDBUS_CMD_NAME_LIST = _IOWR(KDBUS_IOC_MAGIC, 0x52, int),
-+
-+ KDBUS_CMD_MATCH_ADD = _IOWR(KDBUS_IOC_MAGIC, 0x60, int),
-+ KDBUS_CMD_MATCH_REMOVE = _IOWR(KDBUS_IOC_MAGIC, 0x61, int),
-+
-+ KDBUS_CMD_MSG_SEND = _IOWR(KDBUS_IOC_MAGIC, 0x80, struct kdbus_fake_message),
-+ KDBUS_CMD_MSG_RECV = _IOWR(KDBUS_IOC_MAGIC, 0x81, struct kdbus_fake_message),
-+};
-+
-+#endif
---- a/include/uapi/linux/major.h
-+++ b/include/uapi/linux/major.h
-@@ -166,6 +166,8 @@
-
- #define OSST_MAJOR 206 /* OnStream-SCx0 SCSI tape */
-
-+#define KDBUS_CHAR_MAJOR 222
-+
- #define IBM_TTY3270_MAJOR 227
- #define IBM_FS3270_MAJOR 228
-
---- /dev/null
-+++ b/kdbus.c
-@@ -0,0 +1,77 @@
-+#define _GNU_SOURCE
-+#include <stdio.h>
-+#include <string.h>
-+#include <time.h>
-+#include <fcntl.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <errno.h>
-+#include <assert.h>
-+#include <sys/ioctl.h>
-+
-+#include "include/uapi/kdbus/kdbus.h"
-+
-+int main(int argc, char *argv[])
-+{
-+ int fdc;
-+ int fdb;
-+ struct kdbus_cmd_name name;
-+ char *busname;
-+ char *bus;
-+ char *ep;
-+ char *ns;
-+ uid_t uid;
-+ int err;
-+
-+ uid = getuid();
-+ if (argv[1])
-+ busname = argv[1];
-+ else if (uid > 0)
-+ busname = "system";
-+ else
-+ busname = "user";
-+ strcpy(name.name, busname);
-+
-+ printf("-- opening /dev/kdbus/control\n");
-+ fdc = open("/dev/kdbus/control", O_RDWR|O_CLOEXEC);
-+ if (fdc < 0)
-+ return EXIT_FAILURE;
-+
-+ asprintf(&ns, "mydebiancontainer");
-+ strcpy(name.name, ns);
-+ printf("-- creating namespace called %s\n", ns);
-+ err = ioctl(fdc, KDBUS_CMD_NS_CREATE, &name);
-+ if (err)
-+ printf("--- error \"%s\"\n", err, strerror(errno));
-+
-+ printf("-- creating bus '%s'\n", name.name);
-+ err = ioctl(fdc, KDBUS_CMD_BUS_CREATE, &name);
-+ if (err)
-+ printf("--- error \"%s\"\n", err, strerror(errno));
-+
-+ if (uid > 0)
-+ asprintf(&bus, "/dev/kdbus/%u-%s/bus", uid, busname);
-+ else
-+ asprintf(&bus, "/dev/kdbus/%s/bus", busname);
-+ printf("-- opening bus connection %s\n", bus);
-+ fdb = open(bus, O_RDWR|O_CLOEXEC);
-+
-+
-+ asprintf(&ep, "ep-42");
-+ strcpy(name.name, ep);
-+ printf("-- creating endpoint for bus %s called %s\n", bus, ep);
-+ err = ioctl(fdb, KDBUS_CMD_EP_CREATE, &name);
-+ if (err)
-+ printf("--- error \"%s\"\n", err, strerror(errno));
-+
-+ printf("-- sleeping 10s\n");
-+ sleep(10);
-+
-+ printf("-- closing bus connection\n");
-+ close(fdb);
-+
-+ printf("-- closing bus master\n");
-+ close(fdc);
-+ return EXIT_SUCCESS;
-+}