1/* 2 * devtmpfs - kernel-maintained tmpfs-based /dev 3 * 4 * Copyright (C) 2009, Kay Sievers <kay.sievers@vrfy.org> 5 * 6 * During bootup, before any driver core device is registered, 7 * devtmpfs, a tmpfs-based filesystem is created. Every driver-core 8 * device which requests a device node, will add a node in this 9 * filesystem. 10 * By default, all devices are named after the name of the device, 11 * owned by root and have a default mode of 0600. Subsystems can 12 * overwrite the default setting if needed. 13 */ 14 15#include <linux/kernel.h> 16#include <linux/syscalls.h> 17#include <linux/mount.h> 18#include <linux/device.h> 19#include <linux/genhd.h> 20#include <linux/namei.h> 21#include <linux/fs.h> 22#include <linux/shmem_fs.h> 23#include <linux/ramfs.h> 24#include <linux/sched.h> 25#include <linux/slab.h> 26#include <linux/kthread.h> 27#include "base.h" 28 29static struct task_struct *thread; 30 31#if defined CONFIG_DEVTMPFS_MOUNT 32static int mount_dev = 1; 33#else 34static int mount_dev; 35#endif 36 37static DEFINE_SPINLOCK(req_lock); 38 39static struct req { 40 struct req *next; 41 struct completion done; 42 int err; 43 const char *name; 44 umode_t mode; /* 0 => delete */ 45 kuid_t uid; 46 kgid_t gid; 47 struct device *dev; 48} *requests; 49 50static int __init mount_param(char *str) 51{ 52 mount_dev = simple_strtoul(str, NULL, 0); 53 return 1; 54} 55__setup("devtmpfs.mount=", mount_param); 56 57static struct dentry *dev_mount(struct file_system_type *fs_type, int flags, 58 const char *dev_name, void *data) 59{ 60#ifdef CONFIG_TMPFS 61 return mount_single(fs_type, flags, data, shmem_fill_super); 62#else 63 return mount_single(fs_type, flags, data, ramfs_fill_super); 64#endif 65} 66 67static struct file_system_type dev_fs_type = { 68 .name = "devtmpfs", 69 .mount = dev_mount, 70 .kill_sb = kill_litter_super, 71}; 72 73#ifdef CONFIG_BLOCK 74static inline int is_blockdev(struct device *dev) 75{ 76 return dev->class == &block_class; 77} 78#else 79static inline int is_blockdev(struct device *dev) { return 0; } 80#endif 81 82int devtmpfs_create_node(struct device *dev) 83{ 84 const char *tmp = NULL; 85 struct req req; 86 87 if (!thread) 88 return 0; 89 90 req.mode = 0; 91 req.uid = GLOBAL_ROOT_UID; 92 req.gid = GLOBAL_ROOT_GID; 93 req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp); 94 if (!req.name) 95 return -ENOMEM; 96 97 if (req.mode == 0) 98 req.mode = 0600; 99 if (is_blockdev(dev)) 100 req.mode |= S_IFBLK; 101 else 102 req.mode |= S_IFCHR; 103 104 req.dev = dev; 105 106 init_completion(&req.done); 107 108 spin_lock(&req_lock); 109 req.next = requests; 110 requests = &req; 111 spin_unlock(&req_lock); 112 113 wake_up_process(thread); 114 wait_for_completion(&req.done); 115 116 kfree(tmp); 117 118 return req.err; 119} 120 121int devtmpfs_delete_node(struct device *dev) 122{ 123 const char *tmp = NULL; 124 struct req req; 125 126 if (!thread) 127 return 0; 128 129 req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp); 130 if (!req.name) 131 return -ENOMEM; 132 133 req.mode = 0; 134 req.dev = dev; 135 136 init_completion(&req.done); 137 138 spin_lock(&req_lock); 139 req.next = requests; 140 requests = &req; 141 spin_unlock(&req_lock); 142 143 wake_up_process(thread); 144 wait_for_completion(&req.done); 145 146 kfree(tmp); 147 return req.err; 148} 149 150static int dev_mkdir(const char *name, umode_t mode) 151{ 152 struct dentry *dentry; 153 struct path path; 154 int err; 155 156 dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY); 157 if (IS_ERR(dentry)) 158 return PTR_ERR(dentry); 159 160 err = vfs_mkdir(path.dentry->d_inode, dentry, mode); 161 if (!err) 162 /* mark as kernel-created inode */ 163 dentry->d_inode->i_private = &thread; 164 done_path_create(&path, dentry); 165 return err; 166} 167 168static int create_path(const char *nodepath) 169{ 170 char *path; 171 char *s; 172 int err = 0; 173 174 /* parent directories do not exist, create them */ 175 path = kstrdup(nodepath, GFP_KERNEL); 176 if (!path) 177 return -ENOMEM; 178 179 s = path; 180 for (;;) { 181 s = strchr(s, '/'); 182 if (!s) 183 break; 184 s[0] = '\0'; 185 err = dev_mkdir(path, 0755); 186 if (err && err != -EEXIST) 187 break; 188 s[0] = '/'; 189 s++; 190 } 191 kfree(path); 192 return err; 193} 194 195static int handle_create(const char *nodename, umode_t mode, kuid_t uid, 196 kgid_t gid, struct device *dev) 197{ 198 struct dentry *dentry; 199 struct path path; 200 int err; 201 202 dentry = kern_path_create(AT_FDCWD, nodename, &path, 0); 203 if (dentry == ERR_PTR(-ENOENT)) { 204 create_path(nodename); 205 dentry = kern_path_create(AT_FDCWD, nodename, &path, 0); 206 } 207 if (IS_ERR(dentry)) 208 return PTR_ERR(dentry); 209 210 err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt); 211 if (!err) { 212 struct iattr newattrs; 213 214 newattrs.ia_mode = mode; 215 newattrs.ia_uid = uid; 216 newattrs.ia_gid = gid; 217 newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID; 218 mutex_lock(&dentry->d_inode->i_mutex); 219 notify_change(dentry, &newattrs, NULL); 220 mutex_unlock(&dentry->d_inode->i_mutex); 221 222 /* mark as kernel-created inode */ 223 dentry->d_inode->i_private = &thread; 224 } 225 done_path_create(&path, dentry); 226 return err; 227} 228 229static int dev_rmdir(const char *name) 230{ 231 struct path parent; 232 struct dentry *dentry; 233 int err; 234 235 dentry = kern_path_locked(name, &parent); 236 if (IS_ERR(dentry)) 237 return PTR_ERR(dentry); 238 if (dentry->d_inode) { 239 if (dentry->d_inode->i_private == &thread) 240 err = vfs_rmdir(parent.dentry->d_inode, dentry); 241 else 242 err = -EPERM; 243 } else { 244 err = -ENOENT; 245 } 246 dput(dentry); 247 mutex_unlock(&parent.dentry->d_inode->i_mutex); 248 path_put(&parent); 249 return err; 250} 251 252static int delete_path(const char *nodepath) 253{ 254 const char *path; 255 int err = 0; 256 257 path = kstrdup(nodepath, GFP_KERNEL); 258 if (!path) 259 return -ENOMEM; 260 261 for (;;) { 262 char *base; 263 264 base = strrchr(path, '/'); 265 if (!base) 266 break; 267 base[0] = '\0'; 268 err = dev_rmdir(path); 269 if (err) 270 break; 271 } 272 273 kfree(path); 274 return err; 275} 276 277static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *stat) 278{ 279 /* did we create it */ 280 if (inode->i_private != &thread) 281 return 0; 282 283 /* does the dev_t match */ 284 if (is_blockdev(dev)) { 285 if (!S_ISBLK(stat->mode)) 286 return 0; 287 } else { 288 if (!S_ISCHR(stat->mode)) 289 return 0; 290 } 291 if (stat->rdev != dev->devt) 292 return 0; 293 294 /* ours */ 295 return 1; 296} 297 298static int handle_remove(const char *nodename, struct device *dev) 299{ 300 struct path parent; 301 struct dentry *dentry; 302 int deleted = 0; 303 int err; 304 305 dentry = kern_path_locked(nodename, &parent); 306 if (IS_ERR(dentry)) 307 return PTR_ERR(dentry); 308 309 if (dentry->d_inode) { 310 struct kstat stat; 311 struct path p = {.mnt = parent.mnt, .dentry = dentry}; 312 err = vfs_getattr(&p, &stat); 313 if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { 314 struct iattr newattrs; 315 /* 316 * before unlinking this node, reset permissions 317 * of possible references like hardlinks 318 */ 319 newattrs.ia_uid = GLOBAL_ROOT_UID; 320 newattrs.ia_gid = GLOBAL_ROOT_GID; 321 newattrs.ia_mode = stat.mode & ~0777; 322 newattrs.ia_valid = 323 ATTR_UID|ATTR_GID|ATTR_MODE; 324 mutex_lock(&dentry->d_inode->i_mutex); 325 notify_change(dentry, &newattrs, NULL); 326 mutex_unlock(&dentry->d_inode->i_mutex); 327 err = vfs_unlink(parent.dentry->d_inode, dentry, NULL); 328 if (!err || err == -ENOENT) 329 deleted = 1; 330 } 331 } else { 332 err = -ENOENT; 333 } 334 dput(dentry); 335 mutex_unlock(&parent.dentry->d_inode->i_mutex); 336 337 path_put(&parent); 338 if (deleted && strchr(nodename, '/')) 339 delete_path(nodename); 340 return err; 341} 342 343/* 344 * If configured, or requested by the commandline, devtmpfs will be 345 * auto-mounted after the kernel mounted the root filesystem. 346 */ 347int devtmpfs_mount(const char *mntdir) 348{ 349 int err; 350 351 if (!mount_dev) 352 return 0; 353 354 if (!thread) 355 return 0; 356 357 err = sys_mount("devtmpfs", (char *)mntdir, "devtmpfs", MS_SILENT, NULL); 358 if (err) 359 printk(KERN_INFO "devtmpfs: error mounting %i\n", err); 360 else 361 printk(KERN_INFO "devtmpfs: mounted\n"); 362 return err; 363} 364 365static DECLARE_COMPLETION(setup_done); 366 367static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, 368 struct device *dev) 369{ 370 if (mode) 371 return handle_create(name, mode, uid, gid, dev); 372 else 373 return handle_remove(name, dev); 374} 375 376static int devtmpfsd(void *p) 377{ 378 char options[] = "mode=0755"; 379 int *err = p; 380 *err = sys_unshare(CLONE_NEWNS); 381 if (*err) 382 goto out; 383 *err = sys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options); 384 if (*err) 385 goto out; 386 sys_chdir("/.."); /* will traverse into overmounted root */ 387 sys_chroot("."); 388 complete(&setup_done); 389 while (1) { 390 spin_lock(&req_lock); 391 while (requests) { 392 struct req *req = requests; 393 requests = NULL; 394 spin_unlock(&req_lock); 395 while (req) { 396 struct req *next = req->next; 397 req->err = handle(req->name, req->mode, 398 req->uid, req->gid, req->dev); 399 complete(&req->done); 400 req = next; 401 } 402 spin_lock(&req_lock); 403 } 404 __set_current_state(TASK_INTERRUPTIBLE); 405 spin_unlock(&req_lock); 406 schedule(); 407 } 408 return 0; 409out: 410 complete(&setup_done); 411 return *err; 412} 413 414/* 415 * Create devtmpfs instance, driver-core devices will add their device 416 * nodes here. 417 */ 418int __init devtmpfs_init(void) 419{ 420 int err = register_filesystem(&dev_fs_type); 421 if (err) { 422 printk(KERN_ERR "devtmpfs: unable to register devtmpfs " 423 "type %i\n", err); 424 return err; 425 } 426 427 thread = kthread_run(devtmpfsd, &err, "kdevtmpfs"); 428 if (!IS_ERR(thread)) { 429 wait_for_completion(&setup_done); 430 } else { 431 err = PTR_ERR(thread); 432 thread = NULL; 433 } 434 435 if (err) { 436 printk(KERN_ERR "devtmpfs: unable to create devtmpfs %i\n", err); 437 unregister_filesystem(&dev_fs_type); 438 return err; 439 } 440 441 printk(KERN_INFO "devtmpfs: initialized\n"); 442 return 0; 443} 444