diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2009-09-18 17:01:12 -0400 |
---|---|---|
committer | Live-CD User <linux@linux.site> | 2009-09-19 15:50:38 -0400 |
commit | e454cea20bdcff10ee698d11b8882662a0153a47 (patch) | |
tree | f44581fe57787aef0a4f4dc00993a90ea8e688f6 /drivers/base | |
parent | 78f28b7c555359c67c2a0d23f7436e915329421e (diff) |
Driver-Core: extend devnode callbacks to provide permissions
This allows subsytems to provide devtmpfs with non-default permissions
for the device node. Instead of the default mode of 0600, null, zero,
random, urandom, full, tty, ptmx now have a mode of 0666, which allows
non-privileged processes to access standard device nodes in case no
other userspace process applies the expected permissions.
This also fixes a wrong assignment in pktcdvd and a checkpatch.pl complain.
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 19 | ||||
-rw-r--r-- | drivers/base/devtmpfs.c | 24 |
2 files changed, 28 insertions, 15 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 390e664ec1c7..6bee6af8d8e1 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -166,13 +166,16 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, | |||
166 | if (MAJOR(dev->devt)) { | 166 | if (MAJOR(dev->devt)) { |
167 | const char *tmp; | 167 | const char *tmp; |
168 | const char *name; | 168 | const char *name; |
169 | mode_t mode = 0; | ||
169 | 170 | ||
170 | add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); | 171 | add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); |
171 | add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); | 172 | add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); |
172 | name = device_get_nodename(dev, &tmp); | 173 | name = device_get_devnode(dev, &mode, &tmp); |
173 | if (name) { | 174 | if (name) { |
174 | add_uevent_var(env, "DEVNAME=%s", name); | 175 | add_uevent_var(env, "DEVNAME=%s", name); |
175 | kfree(tmp); | 176 | kfree(tmp); |
177 | if (mode) | ||
178 | add_uevent_var(env, "DEVMODE=%#o", mode & 0777); | ||
176 | } | 179 | } |
177 | } | 180 | } |
178 | 181 | ||
@@ -1148,8 +1151,9 @@ static struct device *next_device(struct klist_iter *i) | |||
1148 | } | 1151 | } |
1149 | 1152 | ||
1150 | /** | 1153 | /** |
1151 | * device_get_nodename - path of device node file | 1154 | * device_get_devnode - path of device node file |
1152 | * @dev: device | 1155 | * @dev: device |
1156 | * @mode: returned file access mode | ||
1153 | * @tmp: possibly allocated string | 1157 | * @tmp: possibly allocated string |
1154 | * | 1158 | * |
1155 | * Return the relative path of a possible device node. | 1159 | * Return the relative path of a possible device node. |
@@ -1157,21 +1161,22 @@ static struct device *next_device(struct klist_iter *i) | |||
1157 | * a name. This memory is returned in tmp and needs to be | 1161 | * a name. This memory is returned in tmp and needs to be |
1158 | * freed by the caller. | 1162 | * freed by the caller. |
1159 | */ | 1163 | */ |
1160 | const char *device_get_nodename(struct device *dev, const char **tmp) | 1164 | const char *device_get_devnode(struct device *dev, |
1165 | mode_t *mode, const char **tmp) | ||
1161 | { | 1166 | { |
1162 | char *s; | 1167 | char *s; |
1163 | 1168 | ||
1164 | *tmp = NULL; | 1169 | *tmp = NULL; |
1165 | 1170 | ||
1166 | /* the device type may provide a specific name */ | 1171 | /* the device type may provide a specific name */ |
1167 | if (dev->type && dev->type->nodename) | 1172 | if (dev->type && dev->type->devnode) |
1168 | *tmp = dev->type->nodename(dev); | 1173 | *tmp = dev->type->devnode(dev, mode); |
1169 | if (*tmp) | 1174 | if (*tmp) |
1170 | return *tmp; | 1175 | return *tmp; |
1171 | 1176 | ||
1172 | /* the class may provide a specific name */ | 1177 | /* the class may provide a specific name */ |
1173 | if (dev->class && dev->class->nodename) | 1178 | if (dev->class && dev->class->devnode) |
1174 | *tmp = dev->class->nodename(dev); | 1179 | *tmp = dev->class->devnode(dev, mode); |
1175 | if (*tmp) | 1180 | if (*tmp) |
1176 | return *tmp; | 1181 | return *tmp; |
1177 | 1182 | ||
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index fd488ad4263a..a1cb5afe6801 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
@@ -6,9 +6,10 @@ | |||
6 | * During bootup, before any driver core device is registered, | 6 | * During bootup, before any driver core device is registered, |
7 | * devtmpfs, a tmpfs-based filesystem is created. Every driver-core | 7 | * devtmpfs, a tmpfs-based filesystem is created. Every driver-core |
8 | * device which requests a device node, will add a node in this | 8 | * device which requests a device node, will add a node in this |
9 | * filesystem. The node is named after the the name of the device, | 9 | * filesystem. |
10 | * or the susbsytem can provide a custom name. All devices are | 10 | * By default, all devices are named after the the name of the |
11 | * owned by root and have a mode of 0600. | 11 | * device, owned by root and have a default mode of 0600. Subsystems |
12 | * can overwrite the default setting if needed. | ||
12 | */ | 13 | */ |
13 | 14 | ||
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
@@ -20,6 +21,7 @@ | |||
20 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
21 | #include <linux/shmem_fs.h> | 22 | #include <linux/shmem_fs.h> |
22 | #include <linux/cred.h> | 23 | #include <linux/cred.h> |
24 | #include <linux/sched.h> | ||
23 | #include <linux/init_task.h> | 25 | #include <linux/init_task.h> |
24 | 26 | ||
25 | static struct vfsmount *dev_mnt; | 27 | static struct vfsmount *dev_mnt; |
@@ -134,7 +136,7 @@ int devtmpfs_create_node(struct device *dev) | |||
134 | const char *tmp = NULL; | 136 | const char *tmp = NULL; |
135 | const char *nodename; | 137 | const char *nodename; |
136 | const struct cred *curr_cred; | 138 | const struct cred *curr_cred; |
137 | mode_t mode; | 139 | mode_t mode = 0; |
138 | struct nameidata nd; | 140 | struct nameidata nd; |
139 | struct dentry *dentry; | 141 | struct dentry *dentry; |
140 | int err; | 142 | int err; |
@@ -142,14 +144,16 @@ int devtmpfs_create_node(struct device *dev) | |||
142 | if (!dev_mnt) | 144 | if (!dev_mnt) |
143 | return 0; | 145 | return 0; |
144 | 146 | ||
145 | nodename = device_get_nodename(dev, &tmp); | 147 | nodename = device_get_devnode(dev, &mode, &tmp); |
146 | if (!nodename) | 148 | if (!nodename) |
147 | return -ENOMEM; | 149 | return -ENOMEM; |
148 | 150 | ||
151 | if (mode == 0) | ||
152 | mode = 0600; | ||
149 | if (is_blockdev(dev)) | 153 | if (is_blockdev(dev)) |
150 | mode = S_IFBLK|0600; | 154 | mode |= S_IFBLK; |
151 | else | 155 | else |
152 | mode = S_IFCHR|0600; | 156 | mode |= S_IFCHR; |
153 | 157 | ||
154 | curr_cred = override_creds(&init_cred); | 158 | curr_cred = override_creds(&init_cred); |
155 | err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, | 159 | err = vfs_path_lookup(dev_mnt->mnt_root, dev_mnt, |
@@ -165,8 +169,12 @@ int devtmpfs_create_node(struct device *dev) | |||
165 | 169 | ||
166 | dentry = lookup_create(&nd, 0); | 170 | dentry = lookup_create(&nd, 0); |
167 | if (!IS_ERR(dentry)) { | 171 | if (!IS_ERR(dentry)) { |
172 | int umask; | ||
173 | |||
174 | umask = sys_umask(0000); | ||
168 | err = vfs_mknod(nd.path.dentry->d_inode, | 175 | err = vfs_mknod(nd.path.dentry->d_inode, |
169 | dentry, mode, dev->devt); | 176 | dentry, mode, dev->devt); |
177 | sys_umask(umask); | ||
170 | /* mark as kernel created inode */ | 178 | /* mark as kernel created inode */ |
171 | if (!err) | 179 | if (!err) |
172 | dentry->d_inode->i_private = &dev_mnt; | 180 | dentry->d_inode->i_private = &dev_mnt; |
@@ -271,7 +279,7 @@ int devtmpfs_delete_node(struct device *dev) | |||
271 | if (!dev_mnt) | 279 | if (!dev_mnt) |
272 | return 0; | 280 | return 0; |
273 | 281 | ||
274 | nodename = device_get_nodename(dev, &tmp); | 282 | nodename = device_get_devnode(dev, NULL, &tmp); |
275 | if (!nodename) | 283 | if (!nodename) |
276 | return -ENOMEM; | 284 | return -ENOMEM; |
277 | 285 | ||