1b67dbf9dSGreg KH /* 2b67dbf9dSGreg KH * inode.c - securityfs 3b67dbf9dSGreg KH * 4b67dbf9dSGreg KH * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de> 5b67dbf9dSGreg KH * 6b67dbf9dSGreg KH * This program is free software; you can redistribute it and/or 7b67dbf9dSGreg KH * modify it under the terms of the GNU General Public License version 8b67dbf9dSGreg KH * 2 as published by the Free Software Foundation. 9b67dbf9dSGreg KH * 10b67dbf9dSGreg KH * Based on fs/debugfs/inode.c which had the following copyright notice: 11b67dbf9dSGreg KH * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> 12b67dbf9dSGreg KH * Copyright (C) 2004 IBM Inc. 13b67dbf9dSGreg KH */ 14b67dbf9dSGreg KH 15b67dbf9dSGreg KH /* #define DEBUG */ 16b67dbf9dSGreg KH #include <linux/module.h> 17b67dbf9dSGreg KH #include <linux/fs.h> 18b67dbf9dSGreg KH #include <linux/mount.h> 19b67dbf9dSGreg KH #include <linux/pagemap.h> 20b67dbf9dSGreg KH #include <linux/init.h> 21b67dbf9dSGreg KH #include <linux/namei.h> 22b67dbf9dSGreg KH #include <linux/security.h> 2392562927SMimi Zohar #include <linux/magic.h> 24b67dbf9dSGreg KH 25b67dbf9dSGreg KH static struct vfsmount *mount; 26b67dbf9dSGreg KH static int mount_count; 27b67dbf9dSGreg KH 28b67dbf9dSGreg KH /* 29b67dbf9dSGreg KH * TODO: 30b67dbf9dSGreg KH * I think I can get rid of these default_file_ops, but not quite sure... 31b67dbf9dSGreg KH */ 32b67dbf9dSGreg KH static ssize_t default_read_file(struct file *file, char __user *buf, 33b67dbf9dSGreg KH size_t count, loff_t *ppos) 34b67dbf9dSGreg KH { 35b67dbf9dSGreg KH return 0; 36b67dbf9dSGreg KH } 37b67dbf9dSGreg KH 38b67dbf9dSGreg KH static ssize_t default_write_file(struct file *file, const char __user *buf, 39b67dbf9dSGreg KH size_t count, loff_t *ppos) 40b67dbf9dSGreg KH { 41b67dbf9dSGreg KH return count; 42b67dbf9dSGreg KH } 43b67dbf9dSGreg KH 44b67dbf9dSGreg KH static int default_open(struct inode *inode, struct file *file) 45b67dbf9dSGreg KH { 468e18e294STheodore Ts'o if (inode->i_private) 478e18e294STheodore Ts'o file->private_data = inode->i_private; 48b67dbf9dSGreg KH 49b67dbf9dSGreg KH return 0; 50b67dbf9dSGreg KH } 51b67dbf9dSGreg KH 529c2e08c5SArjan van de Ven static const struct file_operations default_file_ops = { 53b67dbf9dSGreg KH .read = default_read_file, 54b67dbf9dSGreg KH .write = default_write_file, 55b67dbf9dSGreg KH .open = default_open, 56b67dbf9dSGreg KH }; 57b67dbf9dSGreg KH 58b67dbf9dSGreg KH static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev) 59b67dbf9dSGreg KH { 60b67dbf9dSGreg KH struct inode *inode = new_inode(sb); 61b67dbf9dSGreg KH 62b67dbf9dSGreg KH if (inode) { 63b67dbf9dSGreg KH inode->i_mode = mode; 64b67dbf9dSGreg KH inode->i_uid = 0; 65b67dbf9dSGreg KH inode->i_gid = 0; 66b67dbf9dSGreg KH inode->i_blocks = 0; 67b67dbf9dSGreg KH inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 68b67dbf9dSGreg KH switch (mode & S_IFMT) { 69b67dbf9dSGreg KH default: 70b67dbf9dSGreg KH init_special_inode(inode, mode, dev); 71b67dbf9dSGreg KH break; 72b67dbf9dSGreg KH case S_IFREG: 73b67dbf9dSGreg KH inode->i_fop = &default_file_ops; 74b67dbf9dSGreg KH break; 75b67dbf9dSGreg KH case S_IFDIR: 76b67dbf9dSGreg KH inode->i_op = &simple_dir_inode_operations; 77b67dbf9dSGreg KH inode->i_fop = &simple_dir_operations; 78b67dbf9dSGreg KH 79b67dbf9dSGreg KH /* directory inodes start off with i_nlink == 2 (for "." entry) */ 80d8c76e6fSDave Hansen inc_nlink(inode); 81b67dbf9dSGreg KH break; 82b67dbf9dSGreg KH } 83b67dbf9dSGreg KH } 84b67dbf9dSGreg KH return inode; 85b67dbf9dSGreg KH } 86b67dbf9dSGreg KH 87b67dbf9dSGreg KH /* SMP-safe */ 88b67dbf9dSGreg KH static int mknod(struct inode *dir, struct dentry *dentry, 89b67dbf9dSGreg KH int mode, dev_t dev) 90b67dbf9dSGreg KH { 91b67dbf9dSGreg KH struct inode *inode; 92b67dbf9dSGreg KH int error = -EPERM; 93b67dbf9dSGreg KH 94b67dbf9dSGreg KH if (dentry->d_inode) 95b67dbf9dSGreg KH return -EEXIST; 96b67dbf9dSGreg KH 97b67dbf9dSGreg KH inode = get_inode(dir->i_sb, mode, dev); 98b67dbf9dSGreg KH if (inode) { 99b67dbf9dSGreg KH d_instantiate(dentry, inode); 100b67dbf9dSGreg KH dget(dentry); 101b67dbf9dSGreg KH error = 0; 102b67dbf9dSGreg KH } 103b67dbf9dSGreg KH return error; 104b67dbf9dSGreg KH } 105b67dbf9dSGreg KH 106b67dbf9dSGreg KH static int mkdir(struct inode *dir, struct dentry *dentry, int mode) 107b67dbf9dSGreg KH { 108b67dbf9dSGreg KH int res; 109b67dbf9dSGreg KH 110b67dbf9dSGreg KH mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; 111b67dbf9dSGreg KH res = mknod(dir, dentry, mode, 0); 112b67dbf9dSGreg KH if (!res) 113d8c76e6fSDave Hansen inc_nlink(dir); 114b67dbf9dSGreg KH return res; 115b67dbf9dSGreg KH } 116b67dbf9dSGreg KH 117b67dbf9dSGreg KH static int create(struct inode *dir, struct dentry *dentry, int mode) 118b67dbf9dSGreg KH { 119b67dbf9dSGreg KH mode = (mode & S_IALLUGO) | S_IFREG; 120b67dbf9dSGreg KH return mknod(dir, dentry, mode, 0); 121b67dbf9dSGreg KH } 122b67dbf9dSGreg KH 123b67dbf9dSGreg KH static inline int positive(struct dentry *dentry) 124b67dbf9dSGreg KH { 125b67dbf9dSGreg KH return dentry->d_inode && !d_unhashed(dentry); 126b67dbf9dSGreg KH } 127b67dbf9dSGreg KH 128b67dbf9dSGreg KH static int fill_super(struct super_block *sb, void *data, int silent) 129b67dbf9dSGreg KH { 130b67dbf9dSGreg KH static struct tree_descr files[] = {{""}}; 131b67dbf9dSGreg KH 132b67dbf9dSGreg KH return simple_fill_super(sb, SECURITYFS_MAGIC, files); 133b67dbf9dSGreg KH } 134b67dbf9dSGreg KH 135454e2398SDavid Howells static int get_sb(struct file_system_type *fs_type, 136b67dbf9dSGreg KH int flags, const char *dev_name, 137454e2398SDavid Howells void *data, struct vfsmount *mnt) 138b67dbf9dSGreg KH { 139454e2398SDavid Howells return get_sb_single(fs_type, flags, data, fill_super, mnt); 140b67dbf9dSGreg KH } 141b67dbf9dSGreg KH 142b67dbf9dSGreg KH static struct file_system_type fs_type = { 143b67dbf9dSGreg KH .owner = THIS_MODULE, 144b67dbf9dSGreg KH .name = "securityfs", 145b67dbf9dSGreg KH .get_sb = get_sb, 146b67dbf9dSGreg KH .kill_sb = kill_litter_super, 147b67dbf9dSGreg KH }; 148b67dbf9dSGreg KH 149b67dbf9dSGreg KH static int create_by_name(const char *name, mode_t mode, 150b67dbf9dSGreg KH struct dentry *parent, 151b67dbf9dSGreg KH struct dentry **dentry) 152b67dbf9dSGreg KH { 153b67dbf9dSGreg KH int error = 0; 154b67dbf9dSGreg KH 155b67dbf9dSGreg KH *dentry = NULL; 156b67dbf9dSGreg KH 157b67dbf9dSGreg KH /* If the parent is not specified, we create it in the root. 158b67dbf9dSGreg KH * We need the root dentry to do this, which is in the super 159b67dbf9dSGreg KH * block. A pointer to that is in the struct vfsmount that we 160b67dbf9dSGreg KH * have around. 161b67dbf9dSGreg KH */ 162b67dbf9dSGreg KH if (!parent ) { 163b67dbf9dSGreg KH if (mount && mount->mnt_sb) { 164b67dbf9dSGreg KH parent = mount->mnt_sb->s_root; 165b67dbf9dSGreg KH } 166b67dbf9dSGreg KH } 167b67dbf9dSGreg KH if (!parent) { 168b67dbf9dSGreg KH pr_debug("securityfs: Ah! can not find a parent!\n"); 169b67dbf9dSGreg KH return -EFAULT; 170b67dbf9dSGreg KH } 171b67dbf9dSGreg KH 1721b1dcc1bSJes Sorensen mutex_lock(&parent->d_inode->i_mutex); 173b67dbf9dSGreg KH *dentry = lookup_one_len(name, parent, strlen(name)); 174b67dbf9dSGreg KH if (!IS_ERR(dentry)) { 175b67dbf9dSGreg KH if ((mode & S_IFMT) == S_IFDIR) 176b67dbf9dSGreg KH error = mkdir(parent->d_inode, *dentry, mode); 177b67dbf9dSGreg KH else 178b67dbf9dSGreg KH error = create(parent->d_inode, *dentry, mode); 179b67dbf9dSGreg KH } else 180b67dbf9dSGreg KH error = PTR_ERR(dentry); 1811b1dcc1bSJes Sorensen mutex_unlock(&parent->d_inode->i_mutex); 182b67dbf9dSGreg KH 183b67dbf9dSGreg KH return error; 184b67dbf9dSGreg KH } 185b67dbf9dSGreg KH 186b67dbf9dSGreg KH /** 187b67dbf9dSGreg KH * securityfs_create_file - create a file in the securityfs filesystem 188b67dbf9dSGreg KH * 189b67dbf9dSGreg KH * @name: a pointer to a string containing the name of the file to create. 190b67dbf9dSGreg KH * @mode: the permission that the file should have 191b67dbf9dSGreg KH * @parent: a pointer to the parent dentry for this file. This should be a 1923f23d815SRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 193b67dbf9dSGreg KH * file will be created in the root of the securityfs filesystem. 194b67dbf9dSGreg KH * @data: a pointer to something that the caller will want to get to later 1958e18e294STheodore Ts'o * on. The inode.i_private pointer will point to this value on 196b67dbf9dSGreg KH * the open() call. 197b67dbf9dSGreg KH * @fops: a pointer to a struct file_operations that should be used for 198b67dbf9dSGreg KH * this file. 199b67dbf9dSGreg KH * 200b67dbf9dSGreg KH * This is the basic "create a file" function for securityfs. It allows for a 2013f23d815SRandy Dunlap * wide range of flexibility in creating a file, or a directory (if you 202b67dbf9dSGreg KH * want to create a directory, the securityfs_create_dir() function is 2033f23d815SRandy Dunlap * recommended to be used instead). 204b67dbf9dSGreg KH * 2053f23d815SRandy Dunlap * This function returns a pointer to a dentry if it succeeds. This 206b67dbf9dSGreg KH * pointer must be passed to the securityfs_remove() function when the file is 207b67dbf9dSGreg KH * to be removed (no automatic cleanup happens if your module is unloaded, 208faa3aad7SSerge E. Hallyn * you are responsible here). If an error occurs, the function will return 209faa3aad7SSerge E. Hallyn * the erorr value (via ERR_PTR). 210b67dbf9dSGreg KH * 2113f23d815SRandy Dunlap * If securityfs is not enabled in the kernel, the value %-ENODEV is 212faa3aad7SSerge E. Hallyn * returned. 213b67dbf9dSGreg KH */ 214b67dbf9dSGreg KH struct dentry *securityfs_create_file(const char *name, mode_t mode, 215b67dbf9dSGreg KH struct dentry *parent, void *data, 2169c2e08c5SArjan van de Ven const struct file_operations *fops) 217b67dbf9dSGreg KH { 218b67dbf9dSGreg KH struct dentry *dentry = NULL; 219b67dbf9dSGreg KH int error; 220b67dbf9dSGreg KH 221b67dbf9dSGreg KH pr_debug("securityfs: creating file '%s'\n",name); 222b67dbf9dSGreg KH 2231f5ce9e9STrond Myklebust error = simple_pin_fs(&fs_type, &mount, &mount_count); 224b67dbf9dSGreg KH if (error) { 225b67dbf9dSGreg KH dentry = ERR_PTR(error); 226b67dbf9dSGreg KH goto exit; 227b67dbf9dSGreg KH } 228b67dbf9dSGreg KH 229b67dbf9dSGreg KH error = create_by_name(name, mode, parent, &dentry); 230b67dbf9dSGreg KH if (error) { 231b67dbf9dSGreg KH dentry = ERR_PTR(error); 232b67dbf9dSGreg KH simple_release_fs(&mount, &mount_count); 233b67dbf9dSGreg KH goto exit; 234b67dbf9dSGreg KH } 235b67dbf9dSGreg KH 236b67dbf9dSGreg KH if (dentry->d_inode) { 237b67dbf9dSGreg KH if (fops) 238b67dbf9dSGreg KH dentry->d_inode->i_fop = fops; 239b67dbf9dSGreg KH if (data) 2408e18e294STheodore Ts'o dentry->d_inode->i_private = data; 241b67dbf9dSGreg KH } 242b67dbf9dSGreg KH exit: 243b67dbf9dSGreg KH return dentry; 244b67dbf9dSGreg KH } 245b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_create_file); 246b67dbf9dSGreg KH 247b67dbf9dSGreg KH /** 248b67dbf9dSGreg KH * securityfs_create_dir - create a directory in the securityfs filesystem 249b67dbf9dSGreg KH * 250b67dbf9dSGreg KH * @name: a pointer to a string containing the name of the directory to 251b67dbf9dSGreg KH * create. 252b67dbf9dSGreg KH * @parent: a pointer to the parent dentry for this file. This should be a 2533f23d815SRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 254b67dbf9dSGreg KH * directory will be created in the root of the securityfs filesystem. 255b67dbf9dSGreg KH * 2563f23d815SRandy Dunlap * This function creates a directory in securityfs with the given @name. 257b67dbf9dSGreg KH * 2583f23d815SRandy Dunlap * This function returns a pointer to a dentry if it succeeds. This 259b67dbf9dSGreg KH * pointer must be passed to the securityfs_remove() function when the file is 260b67dbf9dSGreg KH * to be removed (no automatic cleanup happens if your module is unloaded, 2613f23d815SRandy Dunlap * you are responsible here). If an error occurs, %NULL will be returned. 262b67dbf9dSGreg KH * 2633f23d815SRandy Dunlap * If securityfs is not enabled in the kernel, the value %-ENODEV is 264b67dbf9dSGreg KH * returned. It is not wise to check for this value, but rather, check for 2653f23d815SRandy Dunlap * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling 266b67dbf9dSGreg KH * code. 267b67dbf9dSGreg KH */ 268b67dbf9dSGreg KH struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) 269b67dbf9dSGreg KH { 270b67dbf9dSGreg KH return securityfs_create_file(name, 271b67dbf9dSGreg KH S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 272b67dbf9dSGreg KH parent, NULL, NULL); 273b67dbf9dSGreg KH } 274b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_create_dir); 275b67dbf9dSGreg KH 276b67dbf9dSGreg KH /** 277b67dbf9dSGreg KH * securityfs_remove - removes a file or directory from the securityfs filesystem 278b67dbf9dSGreg KH * 2793f23d815SRandy Dunlap * @dentry: a pointer to a the dentry of the file or directory to be removed. 280b67dbf9dSGreg KH * 281b67dbf9dSGreg KH * This function removes a file or directory in securityfs that was previously 282b67dbf9dSGreg KH * created with a call to another securityfs function (like 283b67dbf9dSGreg KH * securityfs_create_file() or variants thereof.) 284b67dbf9dSGreg KH * 285b67dbf9dSGreg KH * This function is required to be called in order for the file to be 2863f23d815SRandy Dunlap * removed. No automatic cleanup of files will happen when a module is 2873f23d815SRandy Dunlap * removed; you are responsible here. 288b67dbf9dSGreg KH */ 289b67dbf9dSGreg KH void securityfs_remove(struct dentry *dentry) 290b67dbf9dSGreg KH { 291b67dbf9dSGreg KH struct dentry *parent; 292b67dbf9dSGreg KH 293b67dbf9dSGreg KH if (!dentry) 294b67dbf9dSGreg KH return; 295b67dbf9dSGreg KH 296b67dbf9dSGreg KH parent = dentry->d_parent; 297b67dbf9dSGreg KH if (!parent || !parent->d_inode) 298b67dbf9dSGreg KH return; 299b67dbf9dSGreg KH 3001b1dcc1bSJes Sorensen mutex_lock(&parent->d_inode->i_mutex); 301b67dbf9dSGreg KH if (positive(dentry)) { 302b67dbf9dSGreg KH if (dentry->d_inode) { 303b67dbf9dSGreg KH if (S_ISDIR(dentry->d_inode->i_mode)) 304b67dbf9dSGreg KH simple_rmdir(parent->d_inode, dentry); 305b67dbf9dSGreg KH else 306b67dbf9dSGreg KH simple_unlink(parent->d_inode, dentry); 307b67dbf9dSGreg KH dput(dentry); 308b67dbf9dSGreg KH } 309b67dbf9dSGreg KH } 3101b1dcc1bSJes Sorensen mutex_unlock(&parent->d_inode->i_mutex); 311b67dbf9dSGreg KH simple_release_fs(&mount, &mount_count); 312b67dbf9dSGreg KH } 313b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_remove); 314b67dbf9dSGreg KH 31569d8e138SGreg Kroah-Hartman static struct kobject *security_kobj; 316b67dbf9dSGreg KH 317b67dbf9dSGreg KH static int __init securityfs_init(void) 318b67dbf9dSGreg KH { 319b67dbf9dSGreg KH int retval; 320b67dbf9dSGreg KH 3210ff21e46SGreg Kroah-Hartman security_kobj = kobject_create_and_add("security", kernel_kobj); 32269d8e138SGreg Kroah-Hartman if (!security_kobj) 32369d8e138SGreg Kroah-Hartman return -EINVAL; 324b67dbf9dSGreg KH 325b67dbf9dSGreg KH retval = register_filesystem(&fs_type); 326b67dbf9dSGreg KH if (retval) 32778a2d906SGreg Kroah-Hartman kobject_put(security_kobj); 328b67dbf9dSGreg KH return retval; 329b67dbf9dSGreg KH } 330b67dbf9dSGreg KH 331b67dbf9dSGreg KH core_initcall(securityfs_init); 332b67dbf9dSGreg KH MODULE_LICENSE("GPL"); 333b67dbf9dSGreg KH 334