From 4c1d5a64f134b254552b6211f6f79a1da667eab7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 7 Dec 2011 18:21:57 -0500 Subject: vfs: for usbfs, etc. internal vfsmounts ->mnt_sb->s_root == ->mnt_root Signed-off-by: Al Viro --- security/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security/inode.c') diff --git a/security/inode.c b/security/inode.c index c4df2fbebe6b..a67004f9d106 100644 --- a/security/inode.c +++ b/security/inode.c @@ -159,7 +159,7 @@ static int create_by_name(const char *name, mode_t mode, * have around. */ if (!parent) - parent = mount->mnt_sb->s_root; + parent = mount->mnt_root; mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); -- cgit v1.2.3 From dba19c6064766730dd64757a010ec3aec503ecdb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Jul 2011 20:49:29 -0400 Subject: get rid of open-coded S_ISREG(), etc. Signed-off-by: Al Viro --- security/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security/inode.c') diff --git a/security/inode.c b/security/inode.c index a67004f9d106..bfe02e68f92e 100644 --- a/security/inode.c +++ b/security/inode.c @@ -164,7 +164,7 @@ static int create_by_name(const char *name, mode_t mode, mutex_lock(&parent->d_inode->i_mutex); *dentry = lookup_one_len(name, parent, strlen(name)); if (!IS_ERR(*dentry)) { - if ((mode & S_IFMT) == S_IFDIR) + if (S_ISDIR(mode)) error = mkdir(parent->d_inode, *dentry, mode); else error = create(parent->d_inode, *dentry, mode); -- cgit v1.2.3 From 52ef0c042bf06f6aef382fade175075627beebc1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 26 Jul 2011 04:30:04 -0400 Subject: switch securityfs_create_file() to umode_t Signed-off-by: Al Viro --- security/inode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'security/inode.c') diff --git a/security/inode.c b/security/inode.c index bfe02e68f92e..90a70a67d835 100644 --- a/security/inode.c +++ b/security/inode.c @@ -56,7 +56,7 @@ static const struct file_operations default_file_ops = { .llseek = noop_llseek, }; -static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev) +static struct inode *get_inode(struct super_block *sb, umode_t mode, dev_t dev) { struct inode *inode = new_inode(sb); @@ -85,7 +85,7 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev) /* SMP-safe */ static int mknod(struct inode *dir, struct dentry *dentry, - int mode, dev_t dev) + umode_t mode, dev_t dev) { struct inode *inode; int error = -ENOMEM; @@ -102,7 +102,7 @@ static int mknod(struct inode *dir, struct dentry *dentry, return error; } -static int mkdir(struct inode *dir, struct dentry *dentry, int mode) +static int mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { int res; @@ -113,7 +113,7 @@ static int mkdir(struct inode *dir, struct dentry *dentry, int mode) return res; } -static int create(struct inode *dir, struct dentry *dentry, int mode) +static int create(struct inode *dir, struct dentry *dentry, umode_t mode) { mode = (mode & S_IALLUGO) | S_IFREG; return mknod(dir, dentry, mode, 0); @@ -145,7 +145,7 @@ static struct file_system_type fs_type = { .kill_sb = kill_litter_super, }; -static int create_by_name(const char *name, mode_t mode, +static int create_by_name(const char *name, umode_t mode, struct dentry *parent, struct dentry **dentry) { @@ -205,7 +205,7 @@ static int create_by_name(const char *name, mode_t mode, * If securityfs is not enabled in the kernel, the value %-ENODEV is * returned. */ -struct dentry *securityfs_create_file(const char *name, mode_t mode, +struct dentry *securityfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops) { -- cgit v1.2.3 From 3e25eb9c4bb649acdddb333d10774b640190f727 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 10 Jan 2012 10:20:35 -0500 Subject: securityfs: fix object creation races inode needs to be fully set up before we feed it to d_instantiate(). securityfs_create_file() does *not* do so; it sets ->i_fop and ->i_private only after we'd exposed the inode. Unfortunately, that's done fairly deep in call chain, so the amount of churn is considerable. Helper functions killed by substituting into their solitary call sites, dead code removed. We finally can bury default_file_ops, now that the final value of ->i_fop is available (and assigned) at the point where inode is allocated. Reviewed-by: James Morris Signed-off-by: Al Viro --- security/inode.c | 191 +++++++++++++++---------------------------------------- 1 file changed, 50 insertions(+), 141 deletions(-) (limited to 'security/inode.c') diff --git a/security/inode.c b/security/inode.c index 90a70a67d835..43ce6e19015f 100644 --- a/security/inode.c +++ b/security/inode.c @@ -25,100 +25,6 @@ static struct vfsmount *mount; static int mount_count; -/* - * TODO: - * I think I can get rid of these default_file_ops, but not quite sure... - */ -static ssize_t default_read_file(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - return 0; -} - -static ssize_t default_write_file(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - return count; -} - -static int default_open(struct inode *inode, struct file *file) -{ - if (inode->i_private) - file->private_data = inode->i_private; - - return 0; -} - -static const struct file_operations default_file_ops = { - .read = default_read_file, - .write = default_write_file, - .open = default_open, - .llseek = noop_llseek, -}; - -static struct inode *get_inode(struct super_block *sb, umode_t mode, dev_t dev) -{ - struct inode *inode = new_inode(sb); - - if (inode) { - inode->i_ino = get_next_ino(); - inode->i_mode = mode; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - switch (mode & S_IFMT) { - default: - init_special_inode(inode, mode, dev); - break; - case S_IFREG: - inode->i_fop = &default_file_ops; - break; - case S_IFDIR: - inode->i_op = &simple_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - - /* directory inodes start off with i_nlink == 2 (for "." entry) */ - inc_nlink(inode); - break; - } - } - return inode; -} - -/* SMP-safe */ -static int mknod(struct inode *dir, struct dentry *dentry, - umode_t mode, dev_t dev) -{ - struct inode *inode; - int error = -ENOMEM; - - if (dentry->d_inode) - return -EEXIST; - - inode = get_inode(dir->i_sb, mode, dev); - if (inode) { - d_instantiate(dentry, inode); - dget(dentry); - error = 0; - } - return error; -} - -static int mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - int res; - - mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; - res = mknod(dir, dentry, mode, 0); - if (!res) - inc_nlink(dir); - return res; -} - -static int create(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - mode = (mode & S_IALLUGO) | S_IFREG; - return mknod(dir, dentry, mode, 0); -} - static inline int positive(struct dentry *dentry) { return dentry->d_inode && !d_unhashed(dentry); @@ -145,38 +51,6 @@ static struct file_system_type fs_type = { .kill_sb = kill_litter_super, }; -static int create_by_name(const char *name, umode_t mode, - struct dentry *parent, - struct dentry **dentry) -{ - int error = 0; - - *dentry = NULL; - - /* If the parent is not specified, we create it in the root. - * We need the root dentry to do this, which is in the super - * block. A pointer to that is in the struct vfsmount that we - * have around. - */ - if (!parent) - parent = mount->mnt_root; - - mutex_lock(&parent->d_inode->i_mutex); - *dentry = lookup_one_len(name, parent, strlen(name)); - if (!IS_ERR(*dentry)) { - if (S_ISDIR(mode)) - error = mkdir(parent->d_inode, *dentry, mode); - else - error = create(parent->d_inode, *dentry, mode); - if (error) - dput(*dentry); - } else - error = PTR_ERR(*dentry); - mutex_unlock(&parent->d_inode->i_mutex); - - return error; -} - /** * securityfs_create_file - create a file in the securityfs filesystem * @@ -209,31 +83,66 @@ struct dentry *securityfs_create_file(const char *name, umode_t mode, struct dentry *parent, void *data, const struct file_operations *fops) { - struct dentry *dentry = NULL; + struct dentry *dentry; + int is_dir = S_ISDIR(mode); + struct inode *dir, *inode; int error; + if (!is_dir) { + BUG_ON(!fops); + mode = (mode & S_IALLUGO) | S_IFREG; + } + pr_debug("securityfs: creating file '%s'\n",name); error = simple_pin_fs(&fs_type, &mount, &mount_count); - if (error) { - dentry = ERR_PTR(error); - goto exit; + if (error) + return ERR_PTR(error); + + if (!parent) + parent = mount->mnt_root; + + dir = parent->d_inode; + + mutex_lock(&dir->i_mutex); + dentry = lookup_one_len(name, parent, strlen(name)); + if (IS_ERR(dentry)) + goto out; + + if (dentry->d_inode) { + error = -EEXIST; + goto out1; } - error = create_by_name(name, mode, parent, &dentry); - if (error) { - dentry = ERR_PTR(error); - simple_release_fs(&mount, &mount_count); - goto exit; + inode = new_inode(dir->i_sb); + if (!inode) { + error = -ENOMEM; + goto out1; } - if (dentry->d_inode) { - if (fops) - dentry->d_inode->i_fop = fops; - if (data) - dentry->d_inode->i_private = data; + 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 = &simple_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + inc_nlink(inode); + inc_nlink(dir); + } else { + inode->i_fop = fops; } -exit: + d_instantiate(dentry, inode); + dget(dentry); + mutex_unlock(&dir->i_mutex); + return dentry; + +out1: + dput(dentry); + dentry = ERR_PTR(error); +out: + mutex_unlock(&dir->i_mutex); + simple_release_fs(&mount, &mount_count); return dentry; } EXPORT_SYMBOL_GPL(securityfs_create_file); -- cgit v1.2.3