aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2013-04-06 12:56:00 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-04-08 11:21:48 -0400
commit3c2670e6515cf584810f417db9b00992c8b2d75a (patch)
treebc13c7babc6c8f08b6a82d0b3848778b264d9651
parentbb2b0051d7b0772ea9d0b4be900c2d965093f5d7 (diff)
driver core: add uid and gid to devtmpfs
Some drivers want to tell userspace what uid and gid should be used for their device nodes, so allow that information to percolate through the driver core to userspace in order to make this happen. This means that some systems (i.e. Android and friends) will not need to even run a udev-like daemon for their device node manager and can just rely in devtmpfs fully, reducing their footprint even more. Signed-off-by: Kay Sievers <kay@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--block/genhd.c3
-rw-r--r--drivers/base/core.c17
-rw-r--r--drivers/base/devtmpfs.c27
-rw-r--r--drivers/usb/core/usb.c3
-rw-r--r--include/linux/device.h7
5 files changed, 39 insertions, 18 deletions
diff --git a/block/genhd.c b/block/genhd.c
index 3c001fba80c7..dfcec431ceea 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1111,7 +1111,8 @@ struct class block_class = {
1111 .name = "block", 1111 .name = "block",
1112}; 1112};
1113 1113
1114static char *block_devnode(struct device *dev, umode_t *mode) 1114static char *block_devnode(struct device *dev, umode_t *mode,
1115 uid_t *uid, gid_t *gid)
1115{ 1116{
1116 struct gendisk *disk = dev_to_disk(dev); 1117 struct gendisk *disk = dev_to_disk(dev);
1117 1118
diff --git a/drivers/base/core.c b/drivers/base/core.c
index a7391a30cb29..8a428b51089d 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,
283 const char *tmp; 283 const char *tmp;
284 const char *name; 284 const char *name;
285 umode_t mode = 0; 285 umode_t mode = 0;
286 uid_t uid = 0;
287 gid_t gid = 0;
286 288
287 add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); 289 add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
288 add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); 290 add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
289 name = device_get_devnode(dev, &mode, &tmp); 291 name = device_get_devnode(dev, &mode, &uid, &gid, &tmp);
290 if (name) { 292 if (name) {
291 add_uevent_var(env, "DEVNAME=%s", name); 293 add_uevent_var(env, "DEVNAME=%s", name);
292 kfree(tmp);
293 if (mode) 294 if (mode)
294 add_uevent_var(env, "DEVMODE=%#o", mode & 0777); 295 add_uevent_var(env, "DEVMODE=%#o", mode & 0777);
296 if (uid)
297 add_uevent_var(env, "DEVUID=%u", uid);
298 if (gid)
299 add_uevent_var(env, "DEVGID=%u", gid);
300 kfree(tmp);
295 } 301 }
296 } 302 }
297 303
@@ -1281,6 +1287,8 @@ static struct device *next_device(struct klist_iter *i)
1281 * device_get_devnode - path of device node file 1287 * device_get_devnode - path of device node file
1282 * @dev: device 1288 * @dev: device
1283 * @mode: returned file access mode 1289 * @mode: returned file access mode
1290 * @uid: returned file owner
1291 * @gid: returned file group
1284 * @tmp: possibly allocated string 1292 * @tmp: possibly allocated string
1285 * 1293 *
1286 * Return the relative path of a possible device node. 1294 * Return the relative path of a possible device node.
@@ -1289,7 +1297,8 @@ static struct device *next_device(struct klist_iter *i)
1289 * freed by the caller. 1297 * freed by the caller.
1290 */ 1298 */
1291const char *device_get_devnode(struct device *dev, 1299const char *device_get_devnode(struct device *dev,
1292 umode_t *mode, const char **tmp) 1300 umode_t *mode, uid_t *uid, gid_t *gid,
1301 const char **tmp)
1293{ 1302{
1294 char *s; 1303 char *s;
1295 1304
@@ -1297,7 +1306,7 @@ const char *device_get_devnode(struct device *dev,
1297 1306
1298 /* the device type may provide a specific name */ 1307 /* the device type may provide a specific name */
1299 if (dev->type && dev->type->devnode) 1308 if (dev->type && dev->type->devnode)
1300 *tmp = dev->type->devnode(dev, mode); 1309 *tmp = dev->type->devnode(dev, mode, uid, gid);
1301 if (*tmp) 1310 if (*tmp)
1302 return *tmp; 1311 return *tmp;
1303 1312
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 01fc5b07f951..fda52563677f 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -41,6 +41,8 @@ static struct req {
41 int err; 41 int err;
42 const char *name; 42 const char *name;
43 umode_t mode; /* 0 => delete */ 43 umode_t mode; /* 0 => delete */
44 uid_t uid;
45 gid_t gid;
44 struct device *dev; 46 struct device *dev;
45} *requests; 47} *requests;
46 48
@@ -85,7 +87,9 @@ int devtmpfs_create_node(struct device *dev)
85 return 0; 87 return 0;
86 88
87 req.mode = 0; 89 req.mode = 0;
88 req.name = device_get_devnode(dev, &req.mode, &tmp); 90 req.uid = 0;
91 req.gid = 0;
92 req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp);
89 if (!req.name) 93 if (!req.name)
90 return -ENOMEM; 94 return -ENOMEM;
91 95
@@ -121,7 +125,7 @@ int devtmpfs_delete_node(struct device *dev)
121 if (!thread) 125 if (!thread)
122 return 0; 126 return 0;
123 127
124 req.name = device_get_devnode(dev, NULL, &tmp); 128 req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp);
125 if (!req.name) 129 if (!req.name)
126 return -ENOMEM; 130 return -ENOMEM;
127 131
@@ -187,7 +191,8 @@ static int create_path(const char *nodepath)
187 return err; 191 return err;
188} 192}
189 193
190static int handle_create(const char *nodename, umode_t mode, struct device *dev) 194static int handle_create(const char *nodename, umode_t mode, uid_t uid,
195 gid_t gid, struct device *dev)
191{ 196{
192 struct dentry *dentry; 197 struct dentry *dentry;
193 struct path path; 198 struct path path;
@@ -201,14 +206,14 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
201 if (IS_ERR(dentry)) 206 if (IS_ERR(dentry))
202 return PTR_ERR(dentry); 207 return PTR_ERR(dentry);
203 208
204 err = vfs_mknod(path.dentry->d_inode, 209 err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt);
205 dentry, mode, dev->devt);
206 if (!err) { 210 if (!err) {
207 struct iattr newattrs; 211 struct iattr newattrs;
208 212
209 /* fixup possibly umasked mode */
210 newattrs.ia_mode = mode; 213 newattrs.ia_mode = mode;
211 newattrs.ia_valid = ATTR_MODE; 214 newattrs.ia_uid = uid;
215 newattrs.ia_gid = gid;
216 newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
212 mutex_lock(&dentry->d_inode->i_mutex); 217 mutex_lock(&dentry->d_inode->i_mutex);
213 notify_change(dentry, &newattrs); 218 notify_change(dentry, &newattrs);
214 mutex_unlock(&dentry->d_inode->i_mutex); 219 mutex_unlock(&dentry->d_inode->i_mutex);
@@ -358,10 +363,11 @@ int devtmpfs_mount(const char *mntdir)
358 363
359static DECLARE_COMPLETION(setup_done); 364static DECLARE_COMPLETION(setup_done);
360 365
361static int handle(const char *name, umode_t mode, struct device *dev) 366static int handle(const char *name, umode_t mode, uid_t uid, gid_t gid,
367 struct device *dev)
362{ 368{
363 if (mode) 369 if (mode)
364 return handle_create(name, mode, dev); 370 return handle_create(name, mode, uid, gid, dev);
365 else 371 else
366 return handle_remove(name, dev); 372 return handle_remove(name, dev);
367} 373}
@@ -387,7 +393,8 @@ static int devtmpfsd(void *p)
387 spin_unlock(&req_lock); 393 spin_unlock(&req_lock);
388 while (req) { 394 while (req) {
389 struct req *next = req->next; 395 struct req *next = req->next;
390 req->err = handle(req->name, req->mode, req->dev); 396 req->err = handle(req->name, req->mode,
397 req->uid, req->gid, req->dev);
391 complete(&req->done); 398 complete(&req->done);
392 req = next; 399 req = next;
393 } 400 }
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index f81b92572735..17002832abd9 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -317,7 +317,8 @@ static const struct dev_pm_ops usb_device_pm_ops = {
317#endif /* CONFIG_PM */ 317#endif /* CONFIG_PM */
318 318
319 319
320static char *usb_devnode(struct device *dev, umode_t *mode) 320static char *usb_devnode(struct device *dev,
321 umode_t *mode, uid_t *uid, gid_t *gid)
321{ 322{
322 struct usb_device *usb_dev; 323 struct usb_device *usb_dev;
323 324
diff --git a/include/linux/device.h b/include/linux/device.h
index 4a7c4a84afee..851b85c7101e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -25,6 +25,7 @@
25#include <linux/pm.h> 25#include <linux/pm.h>
26#include <linux/atomic.h> 26#include <linux/atomic.h>
27#include <linux/ratelimit.h> 27#include <linux/ratelimit.h>
28#include <linux/uidgid.h>
28#include <asm/device.h> 29#include <asm/device.h>
29 30
30struct device; 31struct device;
@@ -465,7 +466,8 @@ struct device_type {
465 const char *name; 466 const char *name;
466 const struct attribute_group **groups; 467 const struct attribute_group **groups;
467 int (*uevent)(struct device *dev, struct kobj_uevent_env *env); 468 int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
468 char *(*devnode)(struct device *dev, umode_t *mode); 469 char *(*devnode)(struct device *dev, umode_t *mode,
470 uid_t *uid, gid_t *gid);
469 void (*release)(struct device *dev); 471 void (*release)(struct device *dev);
470 472
471 const struct dev_pm_ops *pm; 473 const struct dev_pm_ops *pm;
@@ -843,7 +845,8 @@ extern int device_rename(struct device *dev, const char *new_name);
843extern int device_move(struct device *dev, struct device *new_parent, 845extern int device_move(struct device *dev, struct device *new_parent,
844 enum dpm_order dpm_order); 846 enum dpm_order dpm_order);
845extern const char *device_get_devnode(struct device *dev, 847extern const char *device_get_devnode(struct device *dev,
846 umode_t *mode, const char **tmp); 848 umode_t *mode, uid_t *uid, gid_t *gid,
849 const char **tmp);
847extern void *dev_get_drvdata(const struct device *dev); 850extern void *dev_get_drvdata(const struct device *dev);
848extern int dev_set_drvdata(struct device *dev, void *data); 851extern int dev_set_drvdata(struct device *dev, void *data);
849 852