diff options
author | Kay Sievers <kay@vrfy.org> | 2013-04-06 12:56:00 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-08 11:21:48 -0400 |
commit | 3c2670e6515cf584810f417db9b00992c8b2d75a (patch) | |
tree | bc13c7babc6c8f08b6a82d0b3848778b264d9651 /drivers/base/devtmpfs.c | |
parent | bb2b0051d7b0772ea9d0b4be900c2d965093f5d7 (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>
Diffstat (limited to 'drivers/base/devtmpfs.c')
-rw-r--r-- | drivers/base/devtmpfs.c | 27 |
1 files changed, 17 insertions, 10 deletions
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 | ||
190 | static int handle_create(const char *nodename, umode_t mode, struct device *dev) | 194 | static 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 | ||
359 | static DECLARE_COMPLETION(setup_done); | 364 | static DECLARE_COMPLETION(setup_done); |
360 | 365 | ||
361 | static int handle(const char *name, umode_t mode, struct device *dev) | 366 | static 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 | } |