summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-29 11:31:50 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-29 11:31:50 -0700
commit2794b5d408c625e104de813d3de7ac0ec34d46d9 (patch)
treea99e067475ed4e1de27c86a544347be97e7458fb /drivers/base
parent4f567cbc957a7cffd1a428a000d93bd903f42349 (diff)
parent0d1d392f011b284bb4af0411b2d36e5d04e0f058 (diff)
downloadlinux-2794b5d408c625e104de813d3de7ac0ec34d46d9.tar.gz
linux-2794b5d408c625e104de813d3de7ac0ec34d46d9.tar.bz2
linux-2794b5d408c625e104de813d3de7ac0ec34d46d9.zip
Merge tag 'driver-core-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core update from Greg Kroah-Hartman: "Here's the merge request for the driver core tree for 3.10-rc1 It's pretty small, just a number of driver core and sysfs updates and fixes, all of which have been in linux-next for a while now. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed conflict in kernel/rtmutex-tester.c, the locking tree had a better fix for the same sysfs file mode problem. * tag 'driver-core-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: PM / Runtime: Idle devices asynchronously after probe|release driver core: handle user namespaces properly with the uid/gid devtmpfs change driver core: devtmpfs: fix compile failure with CONFIG_UIDGID_STRICT_TYPE_CHECKS devtmpfs: add base.h include driver core: add uid and gid to devtmpfs sysfs: check if one entry has been removed before freeing sysfs: fix crash_notes_size build warning sysfs: fix use after free in case of concurrent read/write and readdir rtmutex-tester: fix mode of sysfs files Documentation: Add ABI entry for crash_notes and crash_notes_size sysfs: Add crash_notes_size to export percpu note size driver core: platform_device.h: fix checkpatch errors and warnings driver core: platform.c: fix checkpatch errors and warnings driver core: warn that platform_driver_probe can not use deferred probing sysfs: use atomic_inc_unless_negative in sysfs_get_active base: core: WARN() about bogus permissions on device attributes device: separate all subsys mutexes
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/bus.c8
-rw-r--r--drivers/base/core.c26
-rw-r--r--drivers/base/cpu.c14
-rw-r--r--drivers/base/dd.c6
-rw-r--r--drivers/base/devtmpfs.c28
-rw-r--r--drivers/base/platform.c24
6 files changed, 73 insertions, 33 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 519865b53f76..8a00dec574d6 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -898,18 +898,18 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
/**
- * __bus_register - register a driver-core subsystem
+ * bus_register - register a driver-core subsystem
* @bus: bus to register
- * @key: lockdep class key
*
* Once we have that, we register the bus with the kobject
* infrastructure, then register the children subsystems it has:
* the devices and drivers that belong to the subsystem.
*/
-int __bus_register(struct bus_type *bus, struct lock_class_key *key)
+int bus_register(struct bus_type *bus)
{
int retval;
struct subsys_private *priv;
+ struct lock_class_key *key = &bus->lock_key;
priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
if (!priv)
@@ -981,7 +981,7 @@ out:
bus->p = NULL;
return retval;
}
-EXPORT_SYMBOL_GPL(__bus_register);
+EXPORT_SYMBOL_GPL(bus_register);
/**
* bus_unregister - remove a bus from the system
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 56536f4b0f6b..f88d9e259a32 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -283,15 +283,21 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
const char *tmp;
const char *name;
umode_t mode = 0;
+ kuid_t uid = GLOBAL_ROOT_UID;
+ kgid_t gid = GLOBAL_ROOT_GID;
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_eq(uid, GLOBAL_ROOT_UID))
+ add_uevent_var(env, "DEVUID=%u", from_kuid(&init_user_ns, uid));
+ if (!gid_eq(gid, GLOBAL_ROOT_GID))
+ add_uevent_var(env, "DEVGID=%u", from_kgid(&init_user_ns, gid));
+ kfree(tmp);
}
}
@@ -563,8 +569,15 @@ int device_create_file(struct device *dev,
const struct device_attribute *attr)
{
int error = 0;
- if (dev)
+
+ if (dev) {
+ WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
+ "Write permission without 'store'\n");
+ WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
+ "Read permission without 'show'\n");
error = sysfs_create_file(&dev->kobj, &attr->attr);
+ }
+
return error;
}
@@ -1274,6 +1287,8 @@ static struct device *next_device(struct klist_iter *i)
* 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 +1297,8 @@ static struct device *next_device(struct klist_iter *i)
* freed by the caller.
*/
const char *device_get_devnode(struct device *dev,
- umode_t *mode, const char **tmp)
+ umode_t *mode, kuid_t *uid, kgid_t *gid,
+ const char **tmp)
{
char *s;
@@ -1290,7 +1306,7 @@ const char *device_get_devnode(struct device *dev,
/* 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;
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index fb10728f6372..d8c7f3ee6e19 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -132,6 +132,17 @@ static ssize_t show_crash_notes(struct device *dev, struct device_attribute *att
return rc;
}
static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
+
+static ssize_t show_crash_notes_size(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t rc;
+
+ rc = sprintf(buf, "%zu\n", sizeof(note_buf_t));
+ return rc;
+}
+static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL);
#endif
/*
@@ -259,6 +270,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
#ifdef CONFIG_KEXEC
if (!error)
error = device_create_file(&cpu->dev, &dev_attr_crash_notes);
+ if (!error)
+ error = device_create_file(&cpu->dev,
+ &dev_attr_crash_notes_size);
#endif
return error;
}
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index bb5645ea0282..35fa36898916 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -380,7 +380,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
- pm_runtime_idle(dev);
+ pm_request_idle(dev);
return ret;
}
@@ -428,7 +428,7 @@ int device_attach(struct device *dev)
}
} else {
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
- pm_runtime_idle(dev);
+ pm_request_idle(dev);
}
out_unlock:
device_unlock(dev);
@@ -499,7 +499,7 @@ static void __device_release_driver(struct device *dev)
BUS_NOTIFY_UNBIND_DRIVER,
dev);
- pm_runtime_put_sync(dev);
+ pm_runtime_put(dev);
if (dev->bus && dev->bus->remove)
dev->bus->remove(dev);
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 01fc5b07f951..7413d065906b 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -24,6 +24,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/kthread.h>
+#include "base.h"
static struct task_struct *thread;
@@ -41,6 +42,8 @@ static struct req {
int err;
const char *name;
umode_t mode; /* 0 => delete */
+ kuid_t uid;
+ kgid_t gid;
struct device *dev;
} *requests;
@@ -85,7 +88,9 @@ int devtmpfs_create_node(struct device *dev)
return 0;
req.mode = 0;
- req.name = device_get_devnode(dev, &req.mode, &tmp);
+ req.uid = GLOBAL_ROOT_UID;
+ req.gid = GLOBAL_ROOT_GID;
+ req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp);
if (!req.name)
return -ENOMEM;
@@ -121,7 +126,7 @@ int devtmpfs_delete_node(struct device *dev)
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 +192,8 @@ static int create_path(const char *nodepath)
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, kuid_t uid,
+ kgid_t gid, struct device *dev)
{
struct dentry *dentry;
struct path path;
@@ -201,14 +207,14 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
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);
@@ -358,10 +364,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, kuid_t uid, kgid_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);
}
@@ -387,7 +394,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;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index c0b8df38402b..9eda84246ffd 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -46,8 +46,8 @@ EXPORT_SYMBOL_GPL(platform_bus);
* manipulate any relevant information in the pdev_archdata they can do:
*
* platform_device_alloc()
- * ... manipulate ...
- * platform_device_add()
+ * ... manipulate ...
+ * platform_device_add()
*
* And if they don't care they can just call platform_device_register() and
* everything will just work out.
@@ -326,9 +326,7 @@ int platform_device_add(struct platform_device *pdev)
}
if (p && insert_resource(p, r)) {
- printk(KERN_ERR
- "%s: failed to claim resource %d\n",
- dev_name(&pdev->dev), i);
+ dev_err(&pdev->dev, "failed to claim resource %d\n", i);
ret = -EBUSY;
goto failed;
}
@@ -555,7 +553,8 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
/**
* platform_driver_probe - register driver for non-hotpluggable device
* @drv: platform driver structure
- * @probe: the driver probe routine, probably from an __init section
+ * @probe: the driver probe routine, probably from an __init section,
+ * must not return -EPROBE_DEFER.
*
* Use this instead of platform_driver_register() when you know the device
* is not hotpluggable and has already been registered, and you want to
@@ -566,6 +565,9 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
* into system-on-chip processors, where the controller devices have been
* configured as part of board setup.
*
+ * This is incompatible with deferred probing so probe() must not
+ * return -EPROBE_DEFER.
+ *
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
*/
@@ -682,7 +684,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
int rc;
/* Some devices have extra OF data and an OF-style MODALIAS */
- rc = of_device_uevent_modalias(dev,env);
+ rc = of_device_uevent_modalias(dev, env);
if (rc != -ENODEV)
return rc;
@@ -1126,8 +1128,8 @@ static int __init early_platform_driver_probe_id(char *class_str,
switch (match_id) {
case EARLY_PLATFORM_ID_ERROR:
- pr_warning("%s: unable to parse %s parameter\n",
- class_str, epdrv->pdrv->driver.name);
+ pr_warn("%s: unable to parse %s parameter\n",
+ class_str, epdrv->pdrv->driver.name);
/* fall-through */
case EARLY_PLATFORM_ID_UNSET:
match = NULL;
@@ -1158,8 +1160,8 @@ static int __init early_platform_driver_probe_id(char *class_str,
}
if (epdrv->pdrv->probe(match))
- pr_warning("%s: unable to probe %s early.\n",
- class_str, match->name);
+ pr_warn("%s: unable to probe %s early.\n",
+ class_str, match->name);
else
n++;
}