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/config.h> 17b67dbf9dSGreg KH #include <linux/module.h> 18b67dbf9dSGreg KH #include <linux/fs.h> 19b67dbf9dSGreg KH #include <linux/mount.h> 20b67dbf9dSGreg KH #include <linux/pagemap.h> 21b67dbf9dSGreg KH #include <linux/init.h> 22b67dbf9dSGreg KH #include <linux/namei.h> 23b67dbf9dSGreg KH #include <linux/security.h> 24b67dbf9dSGreg KH 25b67dbf9dSGreg KH #define SECURITYFS_MAGIC 0x73636673 26b67dbf9dSGreg KH 27b67dbf9dSGreg KH static struct vfsmount *mount; 28b67dbf9dSGreg KH static int mount_count; 29b67dbf9dSGreg KH 30b67dbf9dSGreg KH /* 31b67dbf9dSGreg KH * TODO: 32b67dbf9dSGreg KH * I think I can get rid of these default_file_ops, but not quite sure... 33b67dbf9dSGreg KH */ 34b67dbf9dSGreg KH static ssize_t default_read_file(struct file *file, char __user *buf, 35b67dbf9dSGreg KH size_t count, loff_t *ppos) 36b67dbf9dSGreg KH { 37b67dbf9dSGreg KH return 0; 38b67dbf9dSGreg KH } 39b67dbf9dSGreg KH 40b67dbf9dSGreg KH static ssize_t default_write_file(struct file *file, const char __user *buf, 41b67dbf9dSGreg KH size_t count, loff_t *ppos) 42b67dbf9dSGreg KH { 43b67dbf9dSGreg KH return count; 44b67dbf9dSGreg KH } 45b67dbf9dSGreg KH 46b67dbf9dSGreg KH static int default_open(struct inode *inode, struct file *file) 47b67dbf9dSGreg KH { 48b67dbf9dSGreg KH if (inode->u.generic_ip) 49b67dbf9dSGreg KH file->private_data = inode->u.generic_ip; 50b67dbf9dSGreg KH 51b67dbf9dSGreg KH return 0; 52b67dbf9dSGreg KH } 53b67dbf9dSGreg KH 54b67dbf9dSGreg KH static struct file_operations default_file_ops = { 55b67dbf9dSGreg KH .read = default_read_file, 56b67dbf9dSGreg KH .write = default_write_file, 57b67dbf9dSGreg KH .open = default_open, 58b67dbf9dSGreg KH }; 59b67dbf9dSGreg KH 60b67dbf9dSGreg KH static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev) 61b67dbf9dSGreg KH { 62b67dbf9dSGreg KH struct inode *inode = new_inode(sb); 63b67dbf9dSGreg KH 64b67dbf9dSGreg KH if (inode) { 65b67dbf9dSGreg KH inode->i_mode = mode; 66b67dbf9dSGreg KH inode->i_uid = 0; 67b67dbf9dSGreg KH inode->i_gid = 0; 68b67dbf9dSGreg KH inode->i_blksize = PAGE_CACHE_SIZE; 69b67dbf9dSGreg KH inode->i_blocks = 0; 70b67dbf9dSGreg KH inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 71b67dbf9dSGreg KH switch (mode & S_IFMT) { 72b67dbf9dSGreg KH default: 73b67dbf9dSGreg KH init_special_inode(inode, mode, dev); 74b67dbf9dSGreg KH break; 75b67dbf9dSGreg KH case S_IFREG: 76b67dbf9dSGreg KH inode->i_fop = &default_file_ops; 77b67dbf9dSGreg KH break; 78b67dbf9dSGreg KH case S_IFDIR: 79b67dbf9dSGreg KH inode->i_op = &simple_dir_inode_operations; 80b67dbf9dSGreg KH inode->i_fop = &simple_dir_operations; 81b67dbf9dSGreg KH 82b67dbf9dSGreg KH /* directory inodes start off with i_nlink == 2 (for "." entry) */ 83b67dbf9dSGreg KH inode->i_nlink++; 84b67dbf9dSGreg KH break; 85b67dbf9dSGreg KH } 86b67dbf9dSGreg KH } 87b67dbf9dSGreg KH return inode; 88b67dbf9dSGreg KH } 89b67dbf9dSGreg KH 90b67dbf9dSGreg KH /* SMP-safe */ 91b67dbf9dSGreg KH static int mknod(struct inode *dir, struct dentry *dentry, 92b67dbf9dSGreg KH int mode, dev_t dev) 93b67dbf9dSGreg KH { 94b67dbf9dSGreg KH struct inode *inode; 95b67dbf9dSGreg KH int error = -EPERM; 96b67dbf9dSGreg KH 97b67dbf9dSGreg KH if (dentry->d_inode) 98b67dbf9dSGreg KH return -EEXIST; 99b67dbf9dSGreg KH 100b67dbf9dSGreg KH inode = get_inode(dir->i_sb, mode, dev); 101b67dbf9dSGreg KH if (inode) { 102b67dbf9dSGreg KH d_instantiate(dentry, inode); 103b67dbf9dSGreg KH dget(dentry); 104b67dbf9dSGreg KH error = 0; 105b67dbf9dSGreg KH } 106b67dbf9dSGreg KH return error; 107b67dbf9dSGreg KH } 108b67dbf9dSGreg KH 109b67dbf9dSGreg KH static int mkdir(struct inode *dir, struct dentry *dentry, int mode) 110b67dbf9dSGreg KH { 111b67dbf9dSGreg KH int res; 112b67dbf9dSGreg KH 113b67dbf9dSGreg KH mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; 114b67dbf9dSGreg KH res = mknod(dir, dentry, mode, 0); 115b67dbf9dSGreg KH if (!res) 116b67dbf9dSGreg KH dir->i_nlink++; 117b67dbf9dSGreg KH return res; 118b67dbf9dSGreg KH } 119b67dbf9dSGreg KH 120b67dbf9dSGreg KH static int create(struct inode *dir, struct dentry *dentry, int mode) 121b67dbf9dSGreg KH { 122b67dbf9dSGreg KH mode = (mode & S_IALLUGO) | S_IFREG; 123b67dbf9dSGreg KH return mknod(dir, dentry, mode, 0); 124b67dbf9dSGreg KH } 125b67dbf9dSGreg KH 126b67dbf9dSGreg KH static inline int positive(struct dentry *dentry) 127b67dbf9dSGreg KH { 128b67dbf9dSGreg KH return dentry->d_inode && !d_unhashed(dentry); 129b67dbf9dSGreg KH } 130b67dbf9dSGreg KH 131b67dbf9dSGreg KH static int fill_super(struct super_block *sb, void *data, int silent) 132b67dbf9dSGreg KH { 133b67dbf9dSGreg KH static struct tree_descr files[] = {{""}}; 134b67dbf9dSGreg KH 135b67dbf9dSGreg KH return simple_fill_super(sb, SECURITYFS_MAGIC, files); 136b67dbf9dSGreg KH } 137b67dbf9dSGreg KH 138b67dbf9dSGreg KH static struct super_block *get_sb(struct file_system_type *fs_type, 139b67dbf9dSGreg KH int flags, const char *dev_name, 140b67dbf9dSGreg KH void *data) 141b67dbf9dSGreg KH { 142b67dbf9dSGreg KH return get_sb_single(fs_type, flags, data, fill_super); 143b67dbf9dSGreg KH } 144b67dbf9dSGreg KH 145b67dbf9dSGreg KH static struct file_system_type fs_type = { 146b67dbf9dSGreg KH .owner = THIS_MODULE, 147b67dbf9dSGreg KH .name = "securityfs", 148b67dbf9dSGreg KH .get_sb = get_sb, 149b67dbf9dSGreg KH .kill_sb = kill_litter_super, 150b67dbf9dSGreg KH }; 151b67dbf9dSGreg KH 152b67dbf9dSGreg KH static int create_by_name(const char *name, mode_t mode, 153b67dbf9dSGreg KH struct dentry *parent, 154b67dbf9dSGreg KH struct dentry **dentry) 155b67dbf9dSGreg KH { 156b67dbf9dSGreg KH int error = 0; 157b67dbf9dSGreg KH 158b67dbf9dSGreg KH *dentry = NULL; 159b67dbf9dSGreg KH 160b67dbf9dSGreg KH /* If the parent is not specified, we create it in the root. 161b67dbf9dSGreg KH * We need the root dentry to do this, which is in the super 162b67dbf9dSGreg KH * block. A pointer to that is in the struct vfsmount that we 163b67dbf9dSGreg KH * have around. 164b67dbf9dSGreg KH */ 165b67dbf9dSGreg KH if (!parent ) { 166b67dbf9dSGreg KH if (mount && mount->mnt_sb) { 167b67dbf9dSGreg KH parent = mount->mnt_sb->s_root; 168b67dbf9dSGreg KH } 169b67dbf9dSGreg KH } 170b67dbf9dSGreg KH if (!parent) { 171b67dbf9dSGreg KH pr_debug("securityfs: Ah! can not find a parent!\n"); 172b67dbf9dSGreg KH return -EFAULT; 173b67dbf9dSGreg KH } 174b67dbf9dSGreg KH 1751b1dcc1bSJes Sorensen mutex_lock(&parent->d_inode->i_mutex); 176b67dbf9dSGreg KH *dentry = lookup_one_len(name, parent, strlen(name)); 177b67dbf9dSGreg KH if (!IS_ERR(dentry)) { 178b67dbf9dSGreg KH if ((mode & S_IFMT) == S_IFDIR) 179b67dbf9dSGreg KH error = mkdir(parent->d_inode, *dentry, mode); 180b67dbf9dSGreg KH else 181b67dbf9dSGreg KH error = create(parent->d_inode, *dentry, mode); 182b67dbf9dSGreg KH } else 183b67dbf9dSGreg KH error = PTR_ERR(dentry); 1841b1dcc1bSJes Sorensen mutex_unlock(&parent->d_inode->i_mutex); 185b67dbf9dSGreg KH 186b67dbf9dSGreg KH return error; 187b67dbf9dSGreg KH } 188b67dbf9dSGreg KH 189b67dbf9dSGreg KH /** 190b67dbf9dSGreg KH * securityfs_create_file - create a file in the securityfs filesystem 191b67dbf9dSGreg KH * 192b67dbf9dSGreg KH * @name: a pointer to a string containing the name of the file to create. 193b67dbf9dSGreg KH * @mode: the permission that the file should have 194b67dbf9dSGreg KH * @parent: a pointer to the parent dentry for this file. This should be a 195b67dbf9dSGreg KH * directory dentry if set. If this paramater is NULL, then the 196b67dbf9dSGreg KH * file will be created in the root of the securityfs filesystem. 197b67dbf9dSGreg KH * @data: a pointer to something that the caller will want to get to later 198b67dbf9dSGreg KH * on. The inode.u.generic_ip pointer will point to this value on 199b67dbf9dSGreg KH * the open() call. 200b67dbf9dSGreg KH * @fops: a pointer to a struct file_operations that should be used for 201b67dbf9dSGreg KH * this file. 202b67dbf9dSGreg KH * 203b67dbf9dSGreg KH * This is the basic "create a file" function for securityfs. It allows for a 204b67dbf9dSGreg KH * wide range of flexibility in createing a file, or a directory (if you 205b67dbf9dSGreg KH * want to create a directory, the securityfs_create_dir() function is 206b67dbf9dSGreg KH * recommended to be used instead.) 207b67dbf9dSGreg KH * 208b67dbf9dSGreg KH * This function will return a pointer to a dentry if it succeeds. This 209b67dbf9dSGreg KH * pointer must be passed to the securityfs_remove() function when the file is 210b67dbf9dSGreg KH * to be removed (no automatic cleanup happens if your module is unloaded, 211b67dbf9dSGreg KH * you are responsible here.) If an error occurs, NULL will be returned. 212b67dbf9dSGreg KH * 213b67dbf9dSGreg KH * If securityfs is not enabled in the kernel, the value -ENODEV will be 214b67dbf9dSGreg KH * returned. It is not wise to check for this value, but rather, check for 215b67dbf9dSGreg KH * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 216b67dbf9dSGreg KH * code. 217b67dbf9dSGreg KH */ 218b67dbf9dSGreg KH struct dentry *securityfs_create_file(const char *name, mode_t mode, 219b67dbf9dSGreg KH struct dentry *parent, void *data, 220b67dbf9dSGreg KH struct file_operations *fops) 221b67dbf9dSGreg KH { 222b67dbf9dSGreg KH struct dentry *dentry = NULL; 223b67dbf9dSGreg KH int error; 224b67dbf9dSGreg KH 225b67dbf9dSGreg KH pr_debug("securityfs: creating file '%s'\n",name); 226b67dbf9dSGreg KH 2271f5ce9e9STrond Myklebust error = simple_pin_fs(&fs_type, &mount, &mount_count); 228b67dbf9dSGreg KH if (error) { 229b67dbf9dSGreg KH dentry = ERR_PTR(error); 230b67dbf9dSGreg KH goto exit; 231b67dbf9dSGreg KH } 232b67dbf9dSGreg KH 233b67dbf9dSGreg KH error = create_by_name(name, mode, parent, &dentry); 234b67dbf9dSGreg KH if (error) { 235b67dbf9dSGreg KH dentry = ERR_PTR(error); 236b67dbf9dSGreg KH simple_release_fs(&mount, &mount_count); 237b67dbf9dSGreg KH goto exit; 238b67dbf9dSGreg KH } 239b67dbf9dSGreg KH 240b67dbf9dSGreg KH if (dentry->d_inode) { 241b67dbf9dSGreg KH if (fops) 242b67dbf9dSGreg KH dentry->d_inode->i_fop = fops; 243b67dbf9dSGreg KH if (data) 244b67dbf9dSGreg KH dentry->d_inode->u.generic_ip = data; 245b67dbf9dSGreg KH } 246b67dbf9dSGreg KH exit: 247b67dbf9dSGreg KH return dentry; 248b67dbf9dSGreg KH } 249b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_create_file); 250b67dbf9dSGreg KH 251b67dbf9dSGreg KH /** 252b67dbf9dSGreg KH * securityfs_create_dir - create a directory in the securityfs filesystem 253b67dbf9dSGreg KH * 254b67dbf9dSGreg KH * @name: a pointer to a string containing the name of the directory to 255b67dbf9dSGreg KH * create. 256b67dbf9dSGreg KH * @parent: a pointer to the parent dentry for this file. This should be a 257b67dbf9dSGreg KH * directory dentry if set. If this paramater is NULL, then the 258b67dbf9dSGreg KH * directory will be created in the root of the securityfs filesystem. 259b67dbf9dSGreg KH * 260b67dbf9dSGreg KH * This function creates a directory in securityfs with the given name. 261b67dbf9dSGreg KH * 262b67dbf9dSGreg KH * This function will return a pointer to a dentry if it succeeds. This 263b67dbf9dSGreg KH * pointer must be passed to the securityfs_remove() function when the file is 264b67dbf9dSGreg KH * to be removed (no automatic cleanup happens if your module is unloaded, 265b67dbf9dSGreg KH * you are responsible here.) If an error occurs, NULL will be returned. 266b67dbf9dSGreg KH * 267b67dbf9dSGreg KH * If securityfs is not enabled in the kernel, the value -ENODEV will be 268b67dbf9dSGreg KH * returned. It is not wise to check for this value, but rather, check for 269b67dbf9dSGreg KH * NULL or !NULL instead as to eliminate the need for #ifdef in the calling 270b67dbf9dSGreg KH * code. 271b67dbf9dSGreg KH */ 272b67dbf9dSGreg KH struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) 273b67dbf9dSGreg KH { 274b67dbf9dSGreg KH return securityfs_create_file(name, 275b67dbf9dSGreg KH S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, 276b67dbf9dSGreg KH parent, NULL, NULL); 277b67dbf9dSGreg KH } 278b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_create_dir); 279b67dbf9dSGreg KH 280b67dbf9dSGreg KH /** 281b67dbf9dSGreg KH * securityfs_remove - removes a file or directory from the securityfs filesystem 282b67dbf9dSGreg KH * 283b67dbf9dSGreg KH * @dentry: a pointer to a the dentry of the file or directory to be 284b67dbf9dSGreg KH * removed. 285b67dbf9dSGreg KH * 286b67dbf9dSGreg KH * This function removes a file or directory in securityfs that was previously 287b67dbf9dSGreg KH * created with a call to another securityfs function (like 288b67dbf9dSGreg KH * securityfs_create_file() or variants thereof.) 289b67dbf9dSGreg KH * 290b67dbf9dSGreg KH * This function is required to be called in order for the file to be 291b67dbf9dSGreg KH * removed, no automatic cleanup of files will happen when a module is 292b67dbf9dSGreg KH * removed, you are responsible here. 293b67dbf9dSGreg KH */ 294b67dbf9dSGreg KH void securityfs_remove(struct dentry *dentry) 295b67dbf9dSGreg KH { 296b67dbf9dSGreg KH struct dentry *parent; 297b67dbf9dSGreg KH 298b67dbf9dSGreg KH if (!dentry) 299b67dbf9dSGreg KH return; 300b67dbf9dSGreg KH 301b67dbf9dSGreg KH parent = dentry->d_parent; 302b67dbf9dSGreg KH if (!parent || !parent->d_inode) 303b67dbf9dSGreg KH return; 304b67dbf9dSGreg KH 3051b1dcc1bSJes Sorensen mutex_lock(&parent->d_inode->i_mutex); 306b67dbf9dSGreg KH if (positive(dentry)) { 307b67dbf9dSGreg KH if (dentry->d_inode) { 308b67dbf9dSGreg KH if (S_ISDIR(dentry->d_inode->i_mode)) 309b67dbf9dSGreg KH simple_rmdir(parent->d_inode, dentry); 310b67dbf9dSGreg KH else 311b67dbf9dSGreg KH simple_unlink(parent->d_inode, dentry); 312b67dbf9dSGreg KH dput(dentry); 313b67dbf9dSGreg KH } 314b67dbf9dSGreg KH } 3151b1dcc1bSJes Sorensen mutex_unlock(&parent->d_inode->i_mutex); 316b67dbf9dSGreg KH simple_release_fs(&mount, &mount_count); 317b67dbf9dSGreg KH } 318b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_remove); 319b67dbf9dSGreg KH 320b67dbf9dSGreg KH static decl_subsys(security, NULL, NULL); 321b67dbf9dSGreg KH 322b67dbf9dSGreg KH static int __init securityfs_init(void) 323b67dbf9dSGreg KH { 324b67dbf9dSGreg KH int retval; 325b67dbf9dSGreg KH 326b67dbf9dSGreg KH kset_set_kset_s(&security_subsys, kernel_subsys); 327b67dbf9dSGreg KH retval = subsystem_register(&security_subsys); 328b67dbf9dSGreg KH if (retval) 329b67dbf9dSGreg KH return retval; 330b67dbf9dSGreg KH 331b67dbf9dSGreg KH retval = register_filesystem(&fs_type); 332b67dbf9dSGreg KH if (retval) 333b67dbf9dSGreg KH subsystem_unregister(&security_subsys); 334b67dbf9dSGreg KH return retval; 335b67dbf9dSGreg KH } 336b67dbf9dSGreg KH 337b67dbf9dSGreg KH static void __exit securityfs_exit(void) 338b67dbf9dSGreg KH { 339b67dbf9dSGreg KH simple_release_fs(&mount, &mount_count); 340b67dbf9dSGreg KH unregister_filesystem(&fs_type); 341b67dbf9dSGreg KH subsystem_unregister(&security_subsys); 342b67dbf9dSGreg KH } 343b67dbf9dSGreg KH 344b67dbf9dSGreg KH core_initcall(securityfs_init); 345b67dbf9dSGreg KH module_exit(securityfs_exit); 346b67dbf9dSGreg KH MODULE_LICENSE("GPL"); 347b67dbf9dSGreg KH 348