From 8e8739b67cd97de0a6e76c39e7576fc1a37c0167 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Sun, 24 Jul 2016 16:06:14 -0700 Subject: [PATCH] securityfs: update interface to allow inode_ops, and setup from vfs fns BugLink: http://bugs.launchpad.net/bugs/1611078 Signed-off-by: John Johansen Signed-off-by: Tim Gardner --- include/linux/security.h | 32 +++++++++++- security/inode.c | 103 +++++++++++++++++++++++++++++---------- 2 files changed, 109 insertions(+), 26 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index c2125e9093e8..f257e7269d20 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1633,7 +1633,15 @@ static inline void security_audit_rule_free(void *lsmrule) #endif /* CONFIG_AUDIT */ #ifdef CONFIG_SECURITYFS - +extern int securityfs_pin_fs(void); +extern int __securityfs_setup_d_inode(struct inode *dir, struct dentry *dentry, + umode_t mode, void *data, + const struct file_operations *fops, + const struct inode_operations *iops); +extern struct dentry *securityfs_create_dentry(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + const struct inode_operations *iops); extern struct dentry *securityfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops); @@ -1641,6 +1649,28 @@ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *par extern void securityfs_remove(struct dentry *dentry); #else /* CONFIG_SECURITYFS */ +static inline int securityfs_pin_fs(void) +{ + return -ENODEV; +} + +static inline int __securityfs_setup_d_inode(struct inode *dir, + struct dentry *dentry, + umode_t mode, void *data, + const struct file_operations *fops, + const struct inode_operations *iops)) +{ + return -ENODEV; +} + +static inline struct dentry *securityfs_create_dentry(const char *name, + umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + const struct inode_operations *iops) +{ + return ERR_PTR(-ENODEV); +} static inline struct dentry *securityfs_create_dir(const char *name, struct dentry *parent) diff --git a/security/inode.c b/security/inode.c index c83db05c15ab..7a8793d9efd8 100644 --- a/security/inode.c +++ b/security/inode.c @@ -46,8 +46,42 @@ static struct file_system_type fs_type = { .kill_sb = kill_litter_super, }; +int securityfs_pin_fs(void) +{ + return simple_pin_fs(&fs_type, &mount, &mount_count); +} + +int __securityfs_setup_d_inode(struct inode *dir, struct dentry *dentry, + umode_t mode, void *data, + const struct file_operations *fops, + const struct inode_operations *iops) +{ + bool is_dir = S_ISDIR(mode); + struct inode *inode = new_inode(dir->i_sb); + if (!inode) + return -ENOMEM; + + inode->i_ino = get_next_ino(); + inode->i_mode = mode; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_private = data; + if (is_dir) { + inode->i_op = iops ? iops : &simple_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + inc_nlink(inode); + inc_nlink(dir); + } else { + inode->i_fop = fops; + } + d_instantiate(dentry, inode); + dget(dentry); + + return 0; +} +EXPORT_SYMBOL_GPL(__securityfs_setup_d_inode); + /** - * securityfs_create_file - create a file in the securityfs filesystem + * securityfs_create_dentry - create a file/dir in the securityfs filesystem * * @name: a pointer to a string containing the name of the file to create. * @mode: the permission that the file should have @@ -59,8 +93,10 @@ static struct file_system_type fs_type = { * the open() call. * @fops: a pointer to a struct file_operations that should be used for * this file. + * @iops: a point to a struct of inode_operations that should be used for + * this file/dir * - * This is the basic "create a file" function for securityfs. It allows for a + * This is the basic "create a xxx" function for securityfs. It allows for a * wide range of flexibility in creating a file, or a directory (if you * want to create a directory, the securityfs_create_dir() function is * recommended to be used instead). @@ -74,13 +110,14 @@ static struct file_system_type fs_type = { * If securityfs is not enabled in the kernel, the value %-ENODEV is * returned. */ -struct dentry *securityfs_create_file(const char *name, umode_t mode, - struct dentry *parent, void *data, - const struct file_operations *fops) +struct dentry *securityfs_create_dentry(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops, + const struct inode_operations *iops) { struct dentry *dentry; int is_dir = S_ISDIR(mode); - struct inode *dir, *inode; + struct inode *dir; int error; if (!is_dir) { @@ -109,26 +146,9 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode, goto out1; } - inode = new_inode(dir->i_sb); - if (!inode) { - error = -ENOMEM; + error = __securityfs_setup_d_inode(dir, dentry, mode, data, fops, iops); + if (error) goto out1; - } - - inode->i_ino = get_next_ino(); - inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); - inode->i_private = data; - if (is_dir) { - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - inc_nlink(inode); - inc_nlink(dir); - } else { - inode->i_fop = fops; - } - d_instantiate(dentry, inode); - dget(dentry); inode_unlock(dir); return dentry; @@ -140,6 +160,39 @@ out: simple_release_fs(&mount, &mount_count); return dentry; } +EXPORT_SYMBOL_GPL(securityfs_create_dentry); + +/** + * securityfs_create_file - create a file in the securityfs filesystem + * + * @name: a pointer to a string containing the name of the file to create. + * @mode: the permission that the file should have + * @parent: a pointer to the parent dentry for this file. This should be a + * directory dentry if set. If this parameter is %NULL, then the + * file will be created in the root of the securityfs filesystem. + * @data: a pointer to something that the caller will want to get to later + * on. The inode.i_private pointer will point to this value on + * the open() call. + * @fops: a pointer to a struct file_operations that should be used for + * this file. + * + * This function creates a file in securityfs with the given @name. + * + * This function returns a pointer to a dentry if it succeeds. This + * pointer must be passed to the securityfs_remove() function when the file is + * to be removed (no automatic cleanup happens if your module is unloaded, + * you are responsible here). If an error occurs, the function will return + * the error value (via ERR_PTR). + * + * If securityfs is not enabled in the kernel, the value %-ENODEV is + * returned. + */ +struct dentry *securityfs_create_file(const char *name, umode_t mode, + struct dentry *parent, void *data, + const struct file_operations *fops) +{ + return securityfs_create_dentry(name, mode, parent, data, fops, NULL); +} EXPORT_SYMBOL_GPL(securityfs_create_file); /** -- 2.39.2