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 */ 161072bd67SPaul Gortmaker #include <linux/sysfs.h> 171072bd67SPaul Gortmaker #include <linux/kobject.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> 24d69dece5SCasey Schaufler #include <linux/lsm_hooks.h> 2592562927SMimi Zohar #include <linux/magic.h> 26b67dbf9dSGreg KH 27b67dbf9dSGreg KH static struct vfsmount *mount; 28b67dbf9dSGreg KH static int mount_count; 29b67dbf9dSGreg KH 30f614ee1eSAl Viro static void securityfs_free_inode(struct inode *inode) 316623ec7cSJohn Johansen { 326623ec7cSJohn Johansen if (S_ISLNK(inode->i_mode)) 336623ec7cSJohn Johansen kfree(inode->i_link); 3446c87441SAl Viro free_inode_nonrcu(inode); 3546c87441SAl Viro } 3646c87441SAl Viro 376623ec7cSJohn Johansen static const struct super_operations securityfs_super_operations = { 386623ec7cSJohn Johansen .statfs = simple_statfs, 39f614ee1eSAl Viro .free_inode = securityfs_free_inode, 406623ec7cSJohn Johansen }; 416623ec7cSJohn Johansen 42b67dbf9dSGreg KH static int fill_super(struct super_block *sb, void *data, int silent) 43b67dbf9dSGreg KH { 44cda37124SEric Biggers static const struct tree_descr files[] = {{""}}; 456623ec7cSJohn Johansen int error; 46b67dbf9dSGreg KH 476623ec7cSJohn Johansen error = simple_fill_super(sb, SECURITYFS_MAGIC, files); 486623ec7cSJohn Johansen if (error) 496623ec7cSJohn Johansen return error; 506623ec7cSJohn Johansen 516623ec7cSJohn Johansen sb->s_op = &securityfs_super_operations; 526623ec7cSJohn Johansen 536623ec7cSJohn Johansen return 0; 54b67dbf9dSGreg KH } 55b67dbf9dSGreg KH 56fc14f2feSAl Viro static struct dentry *get_sb(struct file_system_type *fs_type, 57b67dbf9dSGreg KH int flags, const char *dev_name, 58fc14f2feSAl Viro void *data) 59b67dbf9dSGreg KH { 60fc14f2feSAl Viro return mount_single(fs_type, flags, data, fill_super); 61b67dbf9dSGreg KH } 62b67dbf9dSGreg KH 63b67dbf9dSGreg KH static struct file_system_type fs_type = { 64b67dbf9dSGreg KH .owner = THIS_MODULE, 65b67dbf9dSGreg KH .name = "securityfs", 66fc14f2feSAl Viro .mount = get_sb, 67b67dbf9dSGreg KH .kill_sb = kill_litter_super, 68b67dbf9dSGreg KH }; 69b67dbf9dSGreg KH 70b67dbf9dSGreg KH /** 716623ec7cSJohn Johansen * securityfs_create_dentry - create a dentry in the securityfs filesystem 72b67dbf9dSGreg KH * 73b67dbf9dSGreg KH * @name: a pointer to a string containing the name of the file to create. 74b67dbf9dSGreg KH * @mode: the permission that the file should have 75b67dbf9dSGreg KH * @parent: a pointer to the parent dentry for this file. This should be a 763f23d815SRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 77b67dbf9dSGreg KH * file will be created in the root of the securityfs filesystem. 78b67dbf9dSGreg KH * @data: a pointer to something that the caller will want to get to later 798e18e294STheodore Ts'o * on. The inode.i_private pointer will point to this value on 80b67dbf9dSGreg KH * the open() call. 81b67dbf9dSGreg KH * @fops: a pointer to a struct file_operations that should be used for 82b67dbf9dSGreg KH * this file. 836623ec7cSJohn Johansen * @iops: a point to a struct of inode_operations that should be used for 846623ec7cSJohn Johansen * this file/dir 85b67dbf9dSGreg KH * 866623ec7cSJohn Johansen * This is the basic "create a file/dir/symlink" function for 876623ec7cSJohn Johansen * securityfs. It allows for a wide range of flexibility in creating 886623ec7cSJohn Johansen * a file, or a directory (if you want to create a directory, the 896623ec7cSJohn Johansen * securityfs_create_dir() function is recommended to be used 906623ec7cSJohn Johansen * instead). 91b67dbf9dSGreg KH * 923f23d815SRandy Dunlap * This function returns a pointer to a dentry if it succeeds. This 936623ec7cSJohn Johansen * pointer must be passed to the securityfs_remove() function when the 946623ec7cSJohn Johansen * file is to be removed (no automatic cleanup happens if your module 956623ec7cSJohn Johansen * is unloaded, you are responsible here). If an error occurs, the 966623ec7cSJohn Johansen * function will return the error value (via ERR_PTR). 97b67dbf9dSGreg KH * 983f23d815SRandy Dunlap * If securityfs is not enabled in the kernel, the value %-ENODEV is 99faa3aad7SSerge E. Hallyn * returned. 100b67dbf9dSGreg KH */ 1016623ec7cSJohn Johansen static struct dentry *securityfs_create_dentry(const char *name, umode_t mode, 102b67dbf9dSGreg KH struct dentry *parent, void *data, 1036623ec7cSJohn Johansen const struct file_operations *fops, 1046623ec7cSJohn Johansen const struct inode_operations *iops) 105b67dbf9dSGreg KH { 1063e25eb9cSAl Viro struct dentry *dentry; 1073e25eb9cSAl Viro struct inode *dir, *inode; 108b67dbf9dSGreg KH int error; 109b67dbf9dSGreg KH 1106623ec7cSJohn Johansen if (!(mode & S_IFMT)) 1113e25eb9cSAl Viro mode = (mode & S_IALLUGO) | S_IFREG; 1123e25eb9cSAl Viro 113b67dbf9dSGreg KH pr_debug("securityfs: creating file '%s'\n",name); 114b67dbf9dSGreg KH 1151f5ce9e9STrond Myklebust error = simple_pin_fs(&fs_type, &mount, &mount_count); 1163e25eb9cSAl Viro if (error) 1173e25eb9cSAl Viro return ERR_PTR(error); 118b67dbf9dSGreg KH 1193e25eb9cSAl Viro if (!parent) 1203e25eb9cSAl Viro parent = mount->mnt_root; 1213e25eb9cSAl Viro 122ce0b16ddSDavid Howells dir = d_inode(parent); 1233e25eb9cSAl Viro 1245955102cSAl Viro inode_lock(dir); 1253e25eb9cSAl Viro dentry = lookup_one_len(name, parent, strlen(name)); 1263e25eb9cSAl Viro if (IS_ERR(dentry)) 1273e25eb9cSAl Viro goto out; 128b67dbf9dSGreg KH 129ce0b16ddSDavid Howells if (d_really_is_positive(dentry)) { 1303e25eb9cSAl Viro error = -EEXIST; 1313e25eb9cSAl Viro goto out1; 132b67dbf9dSGreg KH } 1333e25eb9cSAl Viro 1343e25eb9cSAl Viro inode = new_inode(dir->i_sb); 1353e25eb9cSAl Viro if (!inode) { 1363e25eb9cSAl Viro error = -ENOMEM; 1373e25eb9cSAl Viro goto out1; 1383e25eb9cSAl Viro } 1393e25eb9cSAl Viro 1403e25eb9cSAl Viro inode->i_ino = get_next_ino(); 1413e25eb9cSAl Viro inode->i_mode = mode; 142078cd827SDeepa Dinamani inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); 1433e25eb9cSAl Viro inode->i_private = data; 1446623ec7cSJohn Johansen if (S_ISDIR(mode)) { 1453e25eb9cSAl Viro inode->i_op = &simple_dir_inode_operations; 1463e25eb9cSAl Viro inode->i_fop = &simple_dir_operations; 1473e25eb9cSAl Viro inc_nlink(inode); 1483e25eb9cSAl Viro inc_nlink(dir); 1496623ec7cSJohn Johansen } else if (S_ISLNK(mode)) { 1506623ec7cSJohn Johansen inode->i_op = iops ? iops : &simple_symlink_inode_operations; 1516623ec7cSJohn Johansen inode->i_link = data; 1523e25eb9cSAl Viro } else { 1533e25eb9cSAl Viro inode->i_fop = fops; 1543e25eb9cSAl Viro } 1553e25eb9cSAl Viro d_instantiate(dentry, inode); 1563e25eb9cSAl Viro dget(dentry); 1575955102cSAl Viro inode_unlock(dir); 1583e25eb9cSAl Viro return dentry; 1593e25eb9cSAl Viro 1603e25eb9cSAl Viro out1: 1613e25eb9cSAl Viro dput(dentry); 1623e25eb9cSAl Viro dentry = ERR_PTR(error); 1633e25eb9cSAl Viro out: 1645955102cSAl Viro inode_unlock(dir); 1653e25eb9cSAl Viro simple_release_fs(&mount, &mount_count); 166b67dbf9dSGreg KH return dentry; 167b67dbf9dSGreg KH } 1686623ec7cSJohn Johansen 1696623ec7cSJohn Johansen /** 1706623ec7cSJohn Johansen * securityfs_create_file - create a file in the securityfs filesystem 1716623ec7cSJohn Johansen * 1726623ec7cSJohn Johansen * @name: a pointer to a string containing the name of the file to create. 1736623ec7cSJohn Johansen * @mode: the permission that the file should have 1746623ec7cSJohn Johansen * @parent: a pointer to the parent dentry for this file. This should be a 1756623ec7cSJohn Johansen * directory dentry if set. If this parameter is %NULL, then the 1766623ec7cSJohn Johansen * file will be created in the root of the securityfs filesystem. 1776623ec7cSJohn Johansen * @data: a pointer to something that the caller will want to get to later 1786623ec7cSJohn Johansen * on. The inode.i_private pointer will point to this value on 1796623ec7cSJohn Johansen * the open() call. 1806623ec7cSJohn Johansen * @fops: a pointer to a struct file_operations that should be used for 1816623ec7cSJohn Johansen * this file. 1826623ec7cSJohn Johansen * 1836623ec7cSJohn Johansen * This function creates a file in securityfs with the given @name. 1846623ec7cSJohn Johansen * 1856623ec7cSJohn Johansen * This function returns a pointer to a dentry if it succeeds. This 1866623ec7cSJohn Johansen * pointer must be passed to the securityfs_remove() function when the file is 1876623ec7cSJohn Johansen * to be removed (no automatic cleanup happens if your module is unloaded, 1886623ec7cSJohn Johansen * you are responsible here). If an error occurs, the function will return 1896623ec7cSJohn Johansen * the error value (via ERR_PTR). 1906623ec7cSJohn Johansen * 1916623ec7cSJohn Johansen * If securityfs is not enabled in the kernel, the value %-ENODEV is 1926623ec7cSJohn Johansen * returned. 1936623ec7cSJohn Johansen */ 1946623ec7cSJohn Johansen struct dentry *securityfs_create_file(const char *name, umode_t mode, 1956623ec7cSJohn Johansen struct dentry *parent, void *data, 1966623ec7cSJohn Johansen const struct file_operations *fops) 1976623ec7cSJohn Johansen { 1986623ec7cSJohn Johansen return securityfs_create_dentry(name, mode, parent, data, fops, NULL); 1996623ec7cSJohn Johansen } 200b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_create_file); 201b67dbf9dSGreg KH 202b67dbf9dSGreg KH /** 203b67dbf9dSGreg KH * securityfs_create_dir - create a directory in the securityfs filesystem 204b67dbf9dSGreg KH * 205b67dbf9dSGreg KH * @name: a pointer to a string containing the name of the directory to 206b67dbf9dSGreg KH * create. 207b67dbf9dSGreg KH * @parent: a pointer to the parent dentry for this file. This should be a 2083f23d815SRandy Dunlap * directory dentry if set. If this parameter is %NULL, then the 209b67dbf9dSGreg KH * directory will be created in the root of the securityfs filesystem. 210b67dbf9dSGreg KH * 2113f23d815SRandy Dunlap * This function creates a directory in securityfs with the given @name. 212b67dbf9dSGreg KH * 2133f23d815SRandy Dunlap * This function returns a pointer to a dentry if it succeeds. This 214b67dbf9dSGreg KH * pointer must be passed to the securityfs_remove() function when the file is 215b67dbf9dSGreg KH * to be removed (no automatic cleanup happens if your module is unloaded, 2161b460651SLaurent Georget * you are responsible here). If an error occurs, the function will return 2171b460651SLaurent Georget * the error value (via ERR_PTR). 218b67dbf9dSGreg KH * 2193f23d815SRandy Dunlap * If securityfs is not enabled in the kernel, the value %-ENODEV is 2201b460651SLaurent Georget * returned. 221b67dbf9dSGreg KH */ 222b67dbf9dSGreg KH struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) 223b67dbf9dSGreg KH { 2246623ec7cSJohn Johansen return securityfs_create_file(name, S_IFDIR | 0755, parent, NULL, NULL); 225b67dbf9dSGreg KH } 226b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_create_dir); 227b67dbf9dSGreg KH 228b67dbf9dSGreg KH /** 2296623ec7cSJohn Johansen * securityfs_create_symlink - create a symlink in the securityfs filesystem 2306623ec7cSJohn Johansen * 2316623ec7cSJohn Johansen * @name: a pointer to a string containing the name of the symlink to 2326623ec7cSJohn Johansen * create. 2336623ec7cSJohn Johansen * @parent: a pointer to the parent dentry for the symlink. This should be a 2346623ec7cSJohn Johansen * directory dentry if set. If this parameter is %NULL, then the 2356623ec7cSJohn Johansen * directory will be created in the root of the securityfs filesystem. 2366623ec7cSJohn Johansen * @target: a pointer to a string containing the name of the symlink's target. 2376623ec7cSJohn Johansen * If this parameter is %NULL, then the @iops parameter needs to be 2386623ec7cSJohn Johansen * setup to handle .readlink and .get_link inode_operations. 2396623ec7cSJohn Johansen * @iops: a pointer to the struct inode_operations to use for the symlink. If 2406623ec7cSJohn Johansen * this parameter is %NULL, then the default simple_symlink_inode 2416623ec7cSJohn Johansen * operations will be used. 2426623ec7cSJohn Johansen * 2436623ec7cSJohn Johansen * This function creates a symlink in securityfs with the given @name. 2446623ec7cSJohn Johansen * 2456623ec7cSJohn Johansen * This function returns a pointer to a dentry if it succeeds. This 2466623ec7cSJohn Johansen * pointer must be passed to the securityfs_remove() function when the file is 2476623ec7cSJohn Johansen * to be removed (no automatic cleanup happens if your module is unloaded, 2486623ec7cSJohn Johansen * you are responsible here). If an error occurs, the function will return 2496623ec7cSJohn Johansen * the error value (via ERR_PTR). 2506623ec7cSJohn Johansen * 2516623ec7cSJohn Johansen * If securityfs is not enabled in the kernel, the value %-ENODEV is 2526623ec7cSJohn Johansen * returned. 2536623ec7cSJohn Johansen */ 2546623ec7cSJohn Johansen struct dentry *securityfs_create_symlink(const char *name, 2556623ec7cSJohn Johansen struct dentry *parent, 2566623ec7cSJohn Johansen const char *target, 2576623ec7cSJohn Johansen const struct inode_operations *iops) 2586623ec7cSJohn Johansen { 2596623ec7cSJohn Johansen struct dentry *dent; 2606623ec7cSJohn Johansen char *link = NULL; 2616623ec7cSJohn Johansen 2626623ec7cSJohn Johansen if (target) { 2636623ec7cSJohn Johansen link = kstrdup(target, GFP_KERNEL); 2646623ec7cSJohn Johansen if (!link) 2656623ec7cSJohn Johansen return ERR_PTR(-ENOMEM); 2666623ec7cSJohn Johansen } 2676623ec7cSJohn Johansen dent = securityfs_create_dentry(name, S_IFLNK | 0444, parent, 2686623ec7cSJohn Johansen link, NULL, iops); 2696623ec7cSJohn Johansen if (IS_ERR(dent)) 2706623ec7cSJohn Johansen kfree(link); 2716623ec7cSJohn Johansen 2726623ec7cSJohn Johansen return dent; 2736623ec7cSJohn Johansen } 2746623ec7cSJohn Johansen EXPORT_SYMBOL_GPL(securityfs_create_symlink); 2756623ec7cSJohn Johansen 2766623ec7cSJohn Johansen /** 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 { 2914093d306SAl Viro struct inode *dir; 292b67dbf9dSGreg KH 293d93e4c94SEric Paris if (!dentry || IS_ERR(dentry)) 294b67dbf9dSGreg KH return; 295b67dbf9dSGreg KH 2964093d306SAl Viro dir = d_inode(dentry->d_parent); 2974093d306SAl Viro inode_lock(dir); 298dc3f4198SAl Viro if (simple_positive(dentry)) { 299e36cb0b8SDavid Howells if (d_is_dir(dentry)) 3004093d306SAl Viro simple_rmdir(dir, dentry); 301b67dbf9dSGreg KH else 3024093d306SAl Viro simple_unlink(dir, dentry); 303b67dbf9dSGreg KH dput(dentry); 304b67dbf9dSGreg KH } 3054093d306SAl Viro inode_unlock(dir); 306b67dbf9dSGreg KH simple_release_fs(&mount, &mount_count); 307b67dbf9dSGreg KH } 308b67dbf9dSGreg KH EXPORT_SYMBOL_GPL(securityfs_remove); 309b67dbf9dSGreg KH 310d69dece5SCasey Schaufler #ifdef CONFIG_SECURITY 311d69dece5SCasey Schaufler static struct dentry *lsm_dentry; 312d69dece5SCasey Schaufler static ssize_t lsm_read(struct file *filp, char __user *buf, size_t count, 313d69dece5SCasey Schaufler loff_t *ppos) 314d69dece5SCasey Schaufler { 315d69dece5SCasey Schaufler return simple_read_from_buffer(buf, count, ppos, lsm_names, 316d69dece5SCasey Schaufler strlen(lsm_names)); 317d69dece5SCasey Schaufler } 318d69dece5SCasey Schaufler 319d69dece5SCasey Schaufler static const struct file_operations lsm_ops = { 320d69dece5SCasey Schaufler .read = lsm_read, 321d69dece5SCasey Schaufler .llseek = generic_file_llseek, 322d69dece5SCasey Schaufler }; 323d69dece5SCasey Schaufler #endif 324d69dece5SCasey Schaufler 325b67dbf9dSGreg KH static int __init securityfs_init(void) 326b67dbf9dSGreg KH { 327b67dbf9dSGreg KH int retval; 328b67dbf9dSGreg KH 329f9bb4882SEric W. Biederman retval = sysfs_create_mount_point(kernel_kobj, "security"); 330f9bb4882SEric W. Biederman if (retval) 331f9bb4882SEric W. Biederman return retval; 332b67dbf9dSGreg KH 333b67dbf9dSGreg KH retval = register_filesystem(&fs_type); 334d69dece5SCasey Schaufler if (retval) { 335f9bb4882SEric W. Biederman sysfs_remove_mount_point(kernel_kobj, "security"); 336b67dbf9dSGreg KH return retval; 337b67dbf9dSGreg KH } 338d69dece5SCasey Schaufler #ifdef CONFIG_SECURITY 339d69dece5SCasey Schaufler lsm_dentry = securityfs_create_file("lsm", 0444, NULL, NULL, 340d69dece5SCasey Schaufler &lsm_ops); 341d69dece5SCasey Schaufler #endif 342d69dece5SCasey Schaufler return 0; 343d69dece5SCasey Schaufler } 344b67dbf9dSGreg KH core_initcall(securityfs_init); 345