diff options
| -rw-r--r-- | 0001-kdbus-interprocess-message-router.patch | 1096 | ||||
| -rw-r--r-- | dev_removal.patch | 372 | ||||
| -rw-r--r-- | devnode_gid.patch | 206 | ||||
| -rw-r--r-- | series | 2 |
4 files changed, 1675 insertions, 1 deletions
diff --git a/0001-kdbus-interprocess-message-router.patch b/0001-kdbus-interprocess-message-router.patch new file mode 100644 index 00000000000000..e671e082b6ab48 --- /dev/null +++ b/0001-kdbus-interprocess-message-router.patch @@ -0,0 +1,1096 @@ +From 8c41f3b1fb98a30664c73d61745b346d4013ced5 Mon Sep 17 00:00:00 2001 +From: Kay Sievers <kay@vrfy.org> +Date: Sat, 22 Dec 2012 18:36:55 +0100 +Subject: [PATCH] kdbus: interprocess message router + +--- + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/kdbus/Kconfig | 5 + drivers/kdbus/Makefile | 2 + drivers/kdbus/kdbus.c | 916 +++++++++++++++++++++++++++++++++++++++++++++ + include/uapi/kdbus/kdbus.h | 46 ++ + include/uapi/linux/major.h | 2 + kdbus.c | 64 +++ + 8 files changed, 1038 insertions(+) + create mode 100644 drivers/kdbus/Kconfig + create mode 100644 drivers/kdbus/Makefile + create mode 100644 drivers/kdbus/kdbus.c + create mode 100644 include/uapi/kdbus/kdbus.h + create mode 100644 kdbus.c + +--- 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,2 @@ ++obj-$(CONFIG_KDBUS) += kdbus.o ++ +--- /dev/null ++++ b/drivers/kdbus/kdbus.c +@@ -0,0 +1,916 @@ ++/* ++ * kdbus - interprocess message routing ++ * ++ * Copyright (C) 2013 ++ * ++ * 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 <linux/cred.h> ++#include <linux/security.h> ++#include <asm/uaccess.h> ++#include <uapi/linux/major.h> ++#include <uapi/kdbus/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 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 */ ++ 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 */ ++}; ++ ++/* ++ * 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 */ ++}; ++ ++/* ++ * 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 */ ++}; ++ ++/* 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; ++}; ++ ++struct kdbus_msg { ++ u64 src_id; ++ u64 dst_id; ++ u64 flags; ++ uid_t src_uid; ++ gid_t src_gid; ++ pid_t src_pid; ++ pid_t src_tid; ++ u64 ts_nsec; ++ u64 id; ++ u64 reserved[8]; ++ u32 data_count; ++ struct kdbus_msg_data *data; ++}; ++ ++static void kdbus_release(struct device *dev) ++{ ++ kfree(dev); ++} ++ ++/* kdbus sysfs subsystem */ ++static struct bus_type kdbus_subsys = { ++ .name = "kdbus", ++}; ++ ++/* 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, ++}; ++ ++/* 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, ++}; ++ ++/* kdbus initial namespace */ ++static struct kdbus_ns *kdbus_ns_init; ++ ++/* map of majors to namespaces */ ++static DEFINE_IDR(kdbus_ns_major_idr); ++ ++/* namespace list lock */ ++static DEFINE_MUTEX(kdbus_subsys_lock); ++ ++/* next namespace id sequence number */ ++static __u64 kdbus_ns_id_next; ++ ++extern const struct file_operations kdbus_device_ops; ++static void kdbus_ep_disconnect(struct kdbus_ep *ep); ++static struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep); ++static int kdbus_ep_new(struct kdbus_bus *bus, const char *name, ++ umode_t mode, uid_t uid, gid_t gid, ++ struct kdbus_ep **ep); ++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 struct kdbus_ep *endpoint_find(struct kdbus_bus *bus, const char *name); ++static int endpoint_remove(struct kdbus_ep *ep); ++ ++/* kdbus namespace */ ++static struct kdbus_ns *kdbus_ns_ref(struct kdbus_ns *ns) ++{ ++ if (!ns) ++ return NULL; ++ ns->ref++; ++ return ns; ++} ++ ++static 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); ++} ++ ++static 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); ++ kfree(ns->devpath); ++ kfree(ns); ++ return NULL; ++} ++ ++static int kdbus_ns_new(struct kdbus_ns *parent, const char *name, ++ struct kdbus_ns **ns) ++{ ++ struct kdbus_ns *n; ++ int i; ++ int err; ++ ++ if ((parent && !name) || (!parent && name)) ++ return -EINVAL; ++ ++ n = kzalloc(sizeof(struct kdbus_ns), GFP_KERNEL); ++ if (!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); ++ 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; ++ } ++ } ++ ++ /* 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; ++ } ++ 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; ++} ++ ++/* kdbus bus */ ++static struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus) ++{ ++ if (!bus) ++ return NULL; ++ bus->ref++; ++ return bus; ++} ++ ++static void kdbus_bus_disconnect(struct kdbus_bus *bus) ++{ ++ if (bus->disconnected) ++ return; ++ bus->disconnected = true; ++ ++ /* remove default endpoint */ ++ kdbus_ep_disconnect(bus->ep); ++ kdbus_ep_unref(bus->ep); ++ ++ pr_info("closing bus %s/%s\n", ++ bus->ns->devpath, bus->name); ++} ++ ++static 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; ++} ++ ++static 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; ++} ++ ++/* kdbus endpoint */ ++static struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep) ++{ ++ if (!ep) ++ return NULL; ++ ep->ref++; ++ return ep; ++} ++ ++static 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); ++} ++ ++static 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 */ ++static struct kdbus_ep *endpoint_find(struct kdbus_bus *bus, const char *name) ++{ ++ struct kdbus_ep *ep = NULL; ++ ++ mutex_lock(&bus->lock); ++ list_for_each_entry(ep, &bus->ep_list, bus); ++ ++ mutex_unlock(&bus->lock); ++ ++ return NULL; ++} ++ ++static 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->bus = kdbus_bus_ref(bus); ++ ++ 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; ++ } ++ 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; ++} ++ ++static int endpoint_remove(struct kdbus_ep *ep) ++{ ++ return 0; ++} ++ ++/* 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; ++ } ++ ++ 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; ++ ++ 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); ++ 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; ++ int err; ++ ++ switch (cmd) { ++ case KDBUS_CMD_BUS_CREATE: { ++ struct kdbus_bus *bus = NULL; ++ ++ 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; ++ return 0; ++ } ++ ++ case KDBUS_CMD_NS_CREATE: ++ return -ENOSYS; ++ ++ default: ++ return -ENOTTY; ++ } ++} ++ ++/* 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 = endpoint_find(conn->bus_owner, name.name); ++ if (!ep) ++ return -EINVAL; ++ ++ return endpoint_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; ++ ++ switch (conn->type) { ++ case KDBUS_CONN_CONTROL: ++ return kdbus_conn_ioctl_control(file, cmd, argp); ++ ++ case KDBUS_CONN_EP: ++ return kdbus_conn_ioctl_ep(file, cmd, argp); ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++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, ++ .llseek = noop_llseek, ++}; ++ ++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(GFP_KERNEL, sizeof(struct kdbus_msg)); ++ 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->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->id, (unsigned long long)msg->src_id, ++ (unsigned long long)msg->dst_id); ++ ++ kdbus_msg_free(msg); ++ return 0; ++} ++ ++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("kdbus: failed to initialize err=%i\n", err); ++ return err; ++ } ++ ++ pr_info("kdbus: initialized\n"); ++ return 0; ++} ++ ++void __exit kdbus_exit(void) ++{ ++ kdbus_ns_unref(kdbus_ns_init); ++ bus_unregister(&kdbus_subsys); ++ pr_info("kdbus: 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/include/uapi/kdbus/kdbus.h +@@ -0,0 +1,46 @@ ++/* ++ * kdbus - interprocess message routing ++ * ++ * Copyright (C) 2013 ++ * ++ * 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]; ++}; ++ ++enum kdbus_cmd { ++ /* kdbus control commands */ ++ KDBUS_CMD_BUS_CREATE = _IOW(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_name), ++ KDBUS_CMD_NS_CREATE = _IOW(KDBUS_IOC_MAGIC, 0x10, 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, int), ++ 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, int), ++ KDBUS_CMD_MSG_RECV = _IOWR(KDBUS_IOC_MAGIC, 0x81, int), ++}; ++ ++#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,64 @@ ++#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; ++ uid_t uid; ++ ++ 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; ++ ++ printf("-- creating bus '%s'\n", name.name); ++ ioctl(fdc, KDBUS_CMD_BUS_CREATE, &name); ++ ++ 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); ++ ioctl(fdb, KDBUS_CMD_EP_CREATE, &name); ++ ++ printf("-- sleeping 10s\n"); ++ sleep(10); ++ ++ printf("-- closing bus connection\n"); ++ close(fdb); ++ ++ printf("-- closing bus master\n"); ++ close(fdc); ++ return EXIT_SUCCESS; ++} diff --git a/dev_removal.patch b/dev_removal.patch index 5aa627d8f859c0..26888827a32d85 100644 --- a/dev_removal.patch +++ b/dev_removal.patch @@ -61,11 +61,21 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> drivers/iio/magnetometer/hid-sensor-magn-3d.c | 4 +- drivers/memory/tegra20-mc.c | 4 +- drivers/memory/tegra30-mc.c | 4 +- + drivers/scsi/NCR_Q720.c | 2 - drivers/scsi/a100u2w.c | 8 ++-- drivers/scsi/aacraid/linit.c | 15 ++------- drivers/scsi/aic94xx/aic94xx_init.c | 23 ++++++-------- drivers/scsi/arm/cumana_2.c | 8 ++-- - 57 files changed, 248 insertions(+), 262 deletions(-) + drivers/scsi/bvme6000_scsi.c | 6 +-- + drivers/scsi/ips.c | 10 +++--- + drivers/scsi/jazz_esp.c | 6 +-- + drivers/scsi/lasi700.c | 2 - + drivers/scsi/mac_esp.c | 6 +-- + drivers/scsi/sni_53c710.c | 4 +- + drivers/scsi/stex.c | 5 +-- + drivers/scsi/sun_esp.c | 30 ++++++++---------- + drivers/scsi/zorro7xx.c | 12 +++---- + 67 files changed, 288 insertions(+), 305 deletions(-) --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -2096,6 +2106,17 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> { struct resource *irq; struct tegra30_mc *mc; +--- a/drivers/scsi/NCR_Q720.c ++++ b/drivers/scsi/NCR_Q720.c +@@ -351,7 +351,7 @@ static struct mca_driver NCR_Q720_driver + .name = "NCR_Q720", + .bus = &mca_bus_type, + .probe = NCR_Q720_probe, +- .remove = __devexit_p(NCR_Q720_remove), ++ .remove = NCR_Q720_remove, + }, + }; + --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -1082,8 +1082,8 @@ static struct scsi_host_template inia100 @@ -2305,3 +2326,352 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> .id_table = cumanascsi2_cids, .drv = { .name = "cumanascsi2", +--- a/drivers/scsi/bvme6000_scsi.c ++++ b/drivers/scsi/bvme6000_scsi.c +@@ -34,7 +34,7 @@ static struct scsi_host_template bvme600 + + static struct platform_device *bvme6000_scsi_device; + +-static __devinit int ++static int + bvme6000_probe(struct platform_device *dev) + { + struct Scsi_Host *host; +@@ -88,7 +88,7 @@ bvme6000_probe(struct platform_device *d + return -ENODEV; + } + +-static __devexit int ++static int + bvme6000_device_remove(struct platform_device *dev) + { + struct Scsi_Host *host = platform_get_drvdata(dev); +@@ -108,7 +108,7 @@ static struct platform_driver bvme6000_s + .owner = THIS_MODULE, + }, + .probe = bvme6000_probe, +- .remove = __devexit_p(bvme6000_device_remove), ++ .remove = bvme6000_device_remove, + }; + + static int __init bvme6000_scsi_init(void) +--- a/drivers/scsi/ips.c ++++ b/drivers/scsi/ips.c +@@ -389,14 +389,14 @@ MODULE_DEVICE_TABLE( pci, ips_pci_table + + static char ips_hot_plug_name[] = "ips"; + +-static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent); +-static void __devexit ips_remove_device(struct pci_dev *pci_dev); ++static int ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent); ++static void ips_remove_device(struct pci_dev *pci_dev); + + static struct pci_driver ips_pci_driver = { + .name = ips_hot_plug_name, + .id_table = ips_pci_table, + .probe = ips_insert_device, +- .remove = __devexit_p(ips_remove_device), ++ .remove = ips_remove_device, + }; + + +@@ -6837,7 +6837,7 @@ err_out_sh: + /* Routine Description: */ + /* Remove one Adapter ( Hot Plugging ) */ + /*---------------------------------------------------------------------------*/ +-static void __devexit ++static void + ips_remove_device(struct pci_dev *pci_dev) + { + struct Scsi_Host *sh = pci_get_drvdata(pci_dev); +@@ -6898,7 +6898,7 @@ module_exit(ips_module_exit); + /* Return Value: */ + /* 0 if Successful, else non-zero */ + /*---------------------------------------------------------------------------*/ +-static int __devinit ++static int + ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent) + { + int index = -1; +--- a/drivers/scsi/jazz_esp.c ++++ b/drivers/scsi/jazz_esp.c +@@ -129,7 +129,7 @@ static const struct esp_driver_ops jazz_ + .dma_error = jazz_esp_dma_error, + }; + +-static int __devinit esp_jazz_probe(struct platform_device *dev) ++static int esp_jazz_probe(struct platform_device *dev) + { + struct scsi_host_template *tpnt = &scsi_esp_template; + struct Scsi_Host *host; +@@ -201,7 +201,7 @@ fail: + return err; + } + +-static int __devexit esp_jazz_remove(struct platform_device *dev) ++static int esp_jazz_remove(struct platform_device *dev) + { + struct esp *esp = dev_get_drvdata(&dev->dev); + unsigned int irq = esp->host->irq; +@@ -223,7 +223,7 @@ MODULE_ALIAS("platform:jazz_esp"); + + static struct platform_driver esp_jazz_driver = { + .probe = esp_jazz_probe, +- .remove = __devexit_p(esp_jazz_remove), ++ .remove = esp_jazz_remove, + .driver = { + .name = "jazz_esp", + .owner = THIS_MODULE, +--- a/drivers/scsi/lasi700.c ++++ b/drivers/scsi/lasi700.c +@@ -168,7 +168,7 @@ static struct parisc_driver lasi700_driv + .name = "lasi_scsi", + .id_table = lasi700_ids, + .probe = lasi700_probe, +- .remove = __devexit_p(lasi700_driver_remove), ++ .remove = lasi700_driver_remove, + }; + + static int __init +--- a/drivers/scsi/mac_esp.c ++++ b/drivers/scsi/mac_esp.c +@@ -481,7 +481,7 @@ static struct esp_driver_ops mac_esp_ops + .dma_error = mac_esp_dma_error, + }; + +-static int __devinit esp_mac_probe(struct platform_device *dev) ++static int esp_mac_probe(struct platform_device *dev) + { + struct scsi_host_template *tpnt = &scsi_esp_template; + struct Scsi_Host *host; +@@ -591,7 +591,7 @@ fail: + return err; + } + +-static int __devexit esp_mac_remove(struct platform_device *dev) ++static int esp_mac_remove(struct platform_device *dev) + { + struct mac_esp_priv *mep = platform_get_drvdata(dev); + struct esp *esp = mep->esp; +@@ -614,7 +614,7 @@ static int __devexit esp_mac_remove(stru + + static struct platform_driver esp_mac_driver = { + .probe = esp_mac_probe, +- .remove = __devexit_p(esp_mac_remove), ++ .remove = esp_mac_remove, + .driver = { + .name = DRV_MODULE_NAME, + .owner = THIS_MODULE, +--- a/drivers/scsi/sni_53c710.c ++++ b/drivers/scsi/sni_53c710.c +@@ -65,7 +65,7 @@ static struct scsi_host_template snirm71 + .module = THIS_MODULE, + }; + +-static int __devinit snirm710_probe(struct platform_device *dev) ++static int snirm710_probe(struct platform_device *dev) + { + unsigned long base; + struct NCR_700_Host_Parameters *hostdata; +@@ -134,7 +134,7 @@ static int __exit snirm710_driver_remove + + static struct platform_driver snirm710_driver = { + .probe = snirm710_probe, +- .remove = __devexit_p(snirm710_driver_remove), ++ .remove = snirm710_driver_remove, + .driver = { + .name = "snirm_53c710", + .owner = THIS_MODULE, +--- a/drivers/scsi/stex.c ++++ b/drivers/scsi/stex.c +@@ -1540,8 +1540,7 @@ static void stex_free_irq(struct st_hba + pci_disable_msi(pdev); + } + +-static int __devinit +-stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) ++static int stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { + struct st_hba *hba; + struct Scsi_Host *host; +@@ -1815,7 +1814,7 @@ static struct pci_driver stex_pci_driver + .name = DRV_NAME, + .id_table = stex_pci_tbl, + .probe = stex_probe, +- .remove = __devexit_p(stex_remove), ++ .remove = stex_remove, + .shutdown = stex_shutdown, + }; + +--- a/drivers/scsi/sun_esp.c ++++ b/drivers/scsi/sun_esp.c +@@ -43,8 +43,7 @@ enum dvma_rev { + dvmahme + }; + +-static int __devinit esp_sbus_setup_dma(struct esp *esp, +- struct platform_device *dma_of) ++static int esp_sbus_setup_dma(struct esp *esp, struct platform_device *dma_of) + { + esp->dma = dma_of; + +@@ -79,7 +78,7 @@ static int __devinit esp_sbus_setup_dma( + + } + +-static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) ++static int esp_sbus_map_regs(struct esp *esp, int hme) + { + struct platform_device *op = esp->dev; + struct resource *res; +@@ -99,7 +98,7 @@ static int __devinit esp_sbus_map_regs(s + return 0; + } + +-static int __devinit esp_sbus_map_command_block(struct esp *esp) ++static int esp_sbus_map_command_block(struct esp *esp) + { + struct platform_device *op = esp->dev; + +@@ -111,7 +110,7 @@ static int __devinit esp_sbus_map_comman + return 0; + } + +-static int __devinit esp_sbus_register_irq(struct esp *esp) ++static int esp_sbus_register_irq(struct esp *esp) + { + struct Scsi_Host *host = esp->host; + struct platform_device *op = esp->dev; +@@ -120,7 +119,7 @@ static int __devinit esp_sbus_register_i + return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); + } + +-static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma) ++static void esp_get_scsi_id(struct esp *esp, struct platform_device *espdma) + { + struct platform_device *op = esp->dev; + struct device_node *dp; +@@ -142,7 +141,7 @@ done: + esp->scsi_id_mask = (1 << esp->scsi_id); + } + +-static void __devinit esp_get_differential(struct esp *esp) ++static void esp_get_differential(struct esp *esp) + { + struct platform_device *op = esp->dev; + struct device_node *dp; +@@ -154,7 +153,7 @@ static void __devinit esp_get_differenti + esp->flags &= ~ESP_FLAG_DIFFERENTIAL; + } + +-static void __devinit esp_get_clock_params(struct esp *esp) ++static void esp_get_clock_params(struct esp *esp) + { + struct platform_device *op = esp->dev; + struct device_node *bus_dp, *dp; +@@ -170,7 +169,7 @@ static void __devinit esp_get_clock_para + esp->cfreq = fmhz; + } + +-static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of) ++static void esp_get_bursts(struct esp *esp, struct platform_device *dma_of) + { + struct device_node *dma_dp = dma_of->dev.of_node; + struct platform_device *op = esp->dev; +@@ -195,7 +194,7 @@ static void __devinit esp_get_bursts(str + esp->bursts = bursts; + } + +-static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma) ++static void esp_sbus_get_props(struct esp *esp, struct platform_device *espdma) + { + esp_get_scsi_id(esp, espdma); + esp_get_differential(esp); +@@ -487,9 +486,8 @@ static const struct esp_driver_ops sbus_ + .dma_error = sbus_esp_dma_error, + }; + +-static int __devinit esp_sbus_probe_one(struct platform_device *op, +- struct platform_device *espdma, +- int hme) ++static int esp_sbus_probe_one(struct platform_device *op, ++ struct platform_device *espdma, int hme) + { + struct scsi_host_template *tpnt = &scsi_esp_template; + struct Scsi_Host *host; +@@ -562,7 +560,7 @@ fail: + return err; + } + +-static int __devinit esp_sbus_probe(struct platform_device *op) ++static int esp_sbus_probe(struct platform_device *op) + { + struct device_node *dma_node = NULL; + struct device_node *dp = op->dev.of_node; +@@ -585,7 +583,7 @@ static int __devinit esp_sbus_probe(stru + return esp_sbus_probe_one(op, dma_of, hme); + } + +-static int __devexit esp_sbus_remove(struct platform_device *op) ++static int esp_sbus_remove(struct platform_device *op) + { + struct esp *esp = dev_get_drvdata(&op->dev); + struct platform_device *dma_of = esp->dma; +@@ -639,7 +637,7 @@ static struct platform_driver esp_sbus_d + .of_match_table = esp_match, + }, + .probe = esp_sbus_probe, +- .remove = __devexit_p(esp_sbus_remove), ++ .remove = esp_sbus_remove, + }; + + static int __init sunesp_init(void) +--- a/drivers/scsi/zorro7xx.c ++++ b/drivers/scsi/zorro7xx.c +@@ -38,7 +38,7 @@ static struct zorro_driver_data { + const char *name; + unsigned long offset; + int absolute; /* offset is absolute address */ +-} zorro7xx_driver_data[] __devinitdata = { ++} zorro7xx_driver_data[] = { + { .name = "PowerUP 603e+", .offset = 0xf40000, .absolute = 1 }, + { .name = "WarpEngine 40xx", .offset = 0x40000 }, + { .name = "A4091", .offset = 0x800000 }, +@@ -46,7 +46,7 @@ static struct zorro_driver_data { + { 0 } + }; + +-static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = { ++static struct zorro_device_id zorro7xx_zorro_tbl[] = { + { + .id = ZORRO_PROD_PHASE5_BLIZZARD_603E_PLUS, + .driver_data = (unsigned long)&zorro7xx_driver_data[0], +@@ -71,8 +71,8 @@ static struct zorro_device_id zorro7xx_z + }; + MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl); + +-static int __devinit zorro7xx_init_one(struct zorro_dev *z, +- const struct zorro_device_id *ent) ++static int zorro7xx_init_one(struct zorro_dev *z, ++ const struct zorro_device_id *ent) + { + struct Scsi_Host *host; + struct NCR_700_Host_Parameters *hostdata; +@@ -150,7 +150,7 @@ static int __devinit zorro7xx_init_one(s + return -ENODEV; + } + +-static __devexit void zorro7xx_remove_one(struct zorro_dev *z) ++static void zorro7xx_remove_one(struct zorro_dev *z) + { + struct Scsi_Host *host = zorro_get_drvdata(z); + struct NCR_700_Host_Parameters *hostdata = shost_priv(host); +@@ -167,7 +167,7 @@ static struct zorro_driver zorro7xx_driv + .name = "zorro7xx-scsi", + .id_table = zorro7xx_zorro_tbl, + .probe = zorro7xx_init_one, +- .remove = __devexit_p(zorro7xx_remove_one), ++ .remove = zorro7xx_remove_one, + }; + + static int __init zorro7xx_scsi_init(void) diff --git a/devnode_gid.patch b/devnode_gid.patch new file mode 100644 index 00000000000000..f6ca7f9d7f2e0b --- /dev/null +++ b/devnode_gid.patch @@ -0,0 +1,206 @@ +From 8c41f3b1fb98a30664c73d61745b346d4013ced5 Mon Sep 17 00:00:00 2001 +From: Kay Sievers <kay@vrfy.org> +Date: Sat, 22 Dec 2012 18:36:55 +0100 +Subject: [PATCH] driver core: add uid and gid to devtmpfs + + +--- + block/genhd.c | 3 ++- + drivers/base/core.c | 17 +++++++++++++---- + drivers/base/devtmpfs.c | 27 +++++++++++++++++---------- + drivers/usb/core/usb.c | 3 ++- + include/linux/device.h | 7 +++++-- + 5 files changed, 39 insertions(+), 18 deletions(-) + +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -1107,7 +1107,8 @@ struct class block_class = { + .name = "block", + }; + +-static char *block_devnode(struct device *dev, umode_t *mode) ++static char *block_devnode(struct device *dev, umode_t *mode, ++ uid_t *uid, gid_t *gid) + { + struct gendisk *disk = dev_to_disk(dev); + +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -283,15 +283,21 @@ static int dev_uevent(struct kset *kset, + const char *tmp; + const char *name; + umode_t mode = 0; ++ uid_t uid = 0; ++ gid_t gid = 0; + + add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); + add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); +- name = device_get_devnode(dev, &mode, &tmp); ++ name = device_get_devnode(dev, &mode, &uid, &gid, &tmp); + if (name) { + add_uevent_var(env, "DEVNAME=%s", name); +- kfree(tmp); + if (mode) + add_uevent_var(env, "DEVMODE=%#o", mode & 0777); ++ if (uid) ++ add_uevent_var(env, "DEVUID=%u", uid); ++ if (gid) ++ add_uevent_var(env, "DEVGID=%u", gid); ++ kfree(tmp); + } + } + +@@ -1274,6 +1280,8 @@ static struct device *next_device(struct + * device_get_devnode - path of device node file + * @dev: device + * @mode: returned file access mode ++ * @uid: returned file owner ++ * @gid: returned file group + * @tmp: possibly allocated string + * + * Return the relative path of a possible device node. +@@ -1282,7 +1290,8 @@ static struct device *next_device(struct + * freed by the caller. + */ + const char *device_get_devnode(struct device *dev, +- umode_t *mode, const char **tmp) ++ umode_t *mode, uid_t *uid, gid_t *gid, ++ const char **tmp) + { + char *s; + +@@ -1290,7 +1299,7 @@ const char *device_get_devnode(struct de + + /* the device type may provide a specific name */ + if (dev->type && dev->type->devnode) +- *tmp = dev->type->devnode(dev, mode); ++ *tmp = dev->type->devnode(dev, mode, uid, gid); + if (*tmp) + return *tmp; + +--- a/drivers/base/devtmpfs.c ++++ b/drivers/base/devtmpfs.c +@@ -41,6 +41,8 @@ static struct req { + int err; + const char *name; + umode_t mode; /* 0 => delete */ ++ uid_t uid; ++ gid_t gid; + struct device *dev; + } *requests; + +@@ -85,7 +87,9 @@ int devtmpfs_create_node(struct device * + return 0; + + req.mode = 0; +- req.name = device_get_devnode(dev, &req.mode, &tmp); ++ req.uid = 0; ++ req.gid = 0; ++ req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp); + if (!req.name) + return -ENOMEM; + +@@ -121,7 +125,7 @@ int devtmpfs_delete_node(struct device * + if (!thread) + return 0; + +- req.name = device_get_devnode(dev, NULL, &tmp); ++ req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp); + if (!req.name) + return -ENOMEM; + +@@ -187,7 +191,8 @@ static int create_path(const char *nodep + return err; + } + +-static int handle_create(const char *nodename, umode_t mode, struct device *dev) ++static int handle_create(const char *nodename, umode_t mode, uid_t uid, ++ gid_t gid, struct device *dev) + { + struct dentry *dentry; + struct path path; +@@ -201,14 +206,14 @@ static int handle_create(const char *nod + if (IS_ERR(dentry)) + return PTR_ERR(dentry); + +- err = vfs_mknod(path.dentry->d_inode, +- dentry, mode, dev->devt); ++ err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt); + if (!err) { + struct iattr newattrs; + +- /* fixup possibly umasked mode */ + newattrs.ia_mode = mode; +- newattrs.ia_valid = ATTR_MODE; ++ newattrs.ia_uid = uid; ++ newattrs.ia_gid = gid; ++ newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID; + mutex_lock(&dentry->d_inode->i_mutex); + notify_change(dentry, &newattrs); + mutex_unlock(&dentry->d_inode->i_mutex); +@@ -357,10 +362,11 @@ int devtmpfs_mount(const char *mntdir) + + static DECLARE_COMPLETION(setup_done); + +-static int handle(const char *name, umode_t mode, struct device *dev) ++static int handle(const char *name, umode_t mode, uid_t uid, gid_t gid, ++ struct device *dev) + { + if (mode) +- return handle_create(name, mode, dev); ++ return handle_create(name, mode, uid, gid, dev); + else + return handle_remove(name, dev); + } +@@ -386,7 +392,8 @@ static int devtmpfsd(void *p) + spin_unlock(&req_lock); + while (req) { + struct req *next = req->next; +- req->err = handle(req->name, req->mode, req->dev); ++ req->err = handle(req->name, req->mode, ++ req->uid, req->gid, req->dev); + complete(&req->done); + req = next; + } +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -317,7 +317,8 @@ static const struct dev_pm_ops usb_devic + #endif /* CONFIG_PM */ + + +-static char *usb_devnode(struct device *dev, umode_t *mode) ++static char *usb_devnode(struct device *dev, ++ umode_t *mode, uid_t *uid, gid_t *gid) + { + struct usb_device *usb_dev; + +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -24,6 +24,7 @@ + #include <linux/pm.h> + #include <linux/atomic.h> + #include <linux/ratelimit.h> ++#include <linux/uidgid.h> + #include <asm/device.h> + + struct device; +@@ -470,7 +471,8 @@ struct device_type { + const char *name; + const struct attribute_group **groups; + int (*uevent)(struct device *dev, struct kobj_uevent_env *env); +- char *(*devnode)(struct device *dev, umode_t *mode); ++ char *(*devnode)(struct device *dev, umode_t *mode, ++ uid_t *uid, gid_t *gid); + void (*release)(struct device *dev); + + const struct dev_pm_ops *pm; +@@ -841,7 +843,8 @@ extern int device_rename(struct device * + extern int device_move(struct device *dev, struct device *new_parent, + enum dpm_order dpm_order); + extern const char *device_get_devnode(struct device *dev, +- umode_t *mode, const char **tmp); ++ umode_t *mode, uid_t *uid, gid_t *gid, ++ const char **tmp); + extern void *dev_get_drvdata(const struct device *dev); + extern int dev_set_drvdata(struct device *dev, void *data); + @@ -1,4 +1,6 @@ # My specific stuff, at the top to make it easier to work stuff below. +devnode_gid.patch +0001-kdbus-interprocess-message-router.patch dbus.patch dev_removal.patch |
