From 3c2670e6515cf584810f417db9b00992c8b2d75a Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 6 Apr 2013 09:56:00 -0700 Subject: 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 Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers/base/devtmpfs.c') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 01fc5b07f95..fda52563677 100644 --- 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 *dev) 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 *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 +191,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, 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 *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 +363,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); } @@ -387,7 +393,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; } -- cgit v1.2.3-70-g09d2 From c3a30420902de10bcc4c8474766cb5f97f4c4dfc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 10 Apr 2013 09:00:15 -0700 Subject: devtmpfs: add base.h include This fixes a sparse warning, and is a good idea given that the devtmpfs_init() prototype is in this file. Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/base/devtmpfs.c') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index fda52563677..aadf6472428 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -24,6 +24,7 @@ #include #include #include +#include "base.h" static struct task_struct *thread; -- cgit v1.2.3-70-g09d2 From d81c8d19da8fb6514c75d5c19334f4236856c561 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 11 Apr 2013 00:12:56 +0800 Subject: driver core: devtmpfs: fix compile failure with CONFIG_UIDGID_STRICT_TYPE_CHECKS If CONFIG_UIDGID_STRICT_TYPE_CHECKS is enalbed, the below compile failure will be triggered: drivers/base/devtmpfs.c: In function 'handle_create': drivers/base/devtmpfs.c:214:19: error: incompatible types when assigning to type 'kuid_t' from type 'uid_t' drivers/base/devtmpfs.c:215:19: error: incompatible types when assigning to type 'kgid_t' from type 'gid_t' make[2]: *** [drivers/base/devtmpfs.o] Error 1 This patch fixes the compile failure. Signed-off-by: Ming Lei Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/base/devtmpfs.c') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index aadf6472428..abd4eee61d2 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -212,8 +212,8 @@ static int handle_create(const char *nodename, umode_t mode, uid_t uid, struct iattr newattrs; newattrs.ia_mode = mode; - newattrs.ia_uid = uid; - newattrs.ia_gid = gid; + newattrs.ia_uid = KUIDT_INIT(uid); + newattrs.ia_gid = KGIDT_INIT(gid); newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs); -- cgit v1.2.3-70-g09d2 From 4e4098a3e08783cfd75f9fcdab276dc1d46931da Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Apr 2013 11:43:29 -0700 Subject: driver core: handle user namespaces properly with the uid/gid devtmpfs change Now that devtmpfs is caring about uid/gid, we need to use the correct internal types so users who have USER_NS enabled will have things work properly for them. Thanks to Eric for pointing this out, and the patch review. Reported-by: Eric W. Biederman Cc: Kay Sievers Cc: Ming Lei Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 2 +- drivers/base/core.c | 14 +++++++------- drivers/base/devtmpfs.c | 18 +++++++++--------- drivers/usb/core/usb.c | 2 +- include/linux/device.h | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers/base/devtmpfs.c') diff --git a/block/genhd.c b/block/genhd.c index dfcec431cee..20625eed551 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -1112,7 +1112,7 @@ struct class block_class = { }; static char *block_devnode(struct device *dev, umode_t *mode, - uid_t *uid, gid_t *gid) + kuid_t *uid, kgid_t *gid) { struct gendisk *disk = dev_to_disk(dev); diff --git a/drivers/base/core.c b/drivers/base/core.c index 8a428b51089..f88d9e259a3 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -283,8 +283,8 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, const char *tmp; const char *name; umode_t mode = 0; - uid_t uid = 0; - gid_t gid = 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)); @@ -293,10 +293,10 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, add_uevent_var(env, "DEVNAME=%s", name); 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); + 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); } } @@ -1297,7 +1297,7 @@ static struct device *next_device(struct klist_iter *i) * freed by the caller. */ const char *device_get_devnode(struct device *dev, - umode_t *mode, uid_t *uid, gid_t *gid, + umode_t *mode, kuid_t *uid, kgid_t *gid, const char **tmp) { char *s; diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index abd4eee61d2..7413d065906 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -42,8 +42,8 @@ static struct req { int err; const char *name; umode_t mode; /* 0 => delete */ - uid_t uid; - gid_t gid; + kuid_t uid; + kgid_t gid; struct device *dev; } *requests; @@ -88,8 +88,8 @@ int devtmpfs_create_node(struct device *dev) return 0; req.mode = 0; - req.uid = 0; - req.gid = 0; + 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; @@ -192,8 +192,8 @@ static int create_path(const char *nodepath) return err; } -static int handle_create(const char *nodename, umode_t mode, uid_t uid, - gid_t gid, 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; @@ -212,8 +212,8 @@ static int handle_create(const char *nodename, umode_t mode, uid_t uid, struct iattr newattrs; newattrs.ia_mode = mode; - newattrs.ia_uid = KUIDT_INIT(uid); - newattrs.ia_gid = KGIDT_INIT(gid); + 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); @@ -364,7 +364,7 @@ int devtmpfs_mount(const char *mntdir) static DECLARE_COMPLETION(setup_done); -static int handle(const char *name, umode_t mode, uid_t uid, gid_t gid, +static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, struct device *dev) { if (mode) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 17002832abd..e092b414dc5 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -318,7 +318,7 @@ static const struct dev_pm_ops usb_device_pm_ops = { static char *usb_devnode(struct device *dev, - umode_t *mode, uid_t *uid, gid_t *gid) + umode_t *mode, kuid_t *uid, kgid_t *gid) { struct usb_device *usb_dev; diff --git a/include/linux/device.h b/include/linux/device.h index 851b85c7101..88615ccaf23 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -467,7 +467,7 @@ struct device_type { const struct attribute_group **groups; int (*uevent)(struct device *dev, struct kobj_uevent_env *env); char *(*devnode)(struct device *dev, umode_t *mode, - uid_t *uid, gid_t *gid); + kuid_t *uid, kgid_t *gid); void (*release)(struct device *dev); const struct dev_pm_ops *pm; @@ -845,7 +845,7 @@ extern int device_rename(struct device *dev, const char *new_name); 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, uid_t *uid, gid_t *gid, + umode_t *mode, kuid_t *uid, kgid_t *gid, const char **tmp); extern void *dev_get_drvdata(const struct device *dev); extern int dev_set_drvdata(struct device *dev, void *data); -- cgit v1.2.3-70-g09d2