diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-02-23 04:53:53 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-03-19 06:42:18 -0400 |
commit | f382d6e631fe424200ee0d8bb16539f5b7bef7be (patch) | |
tree | 03692bc57fa9cce5d12ace0b57fc03c11b6fa72f /fs | |
parent | 1dd0dd111f1b7591f2848fffdb06044053f66c40 (diff) | |
download | op-kernel-dev-f382d6e631fe424200ee0d8bb16539f5b7bef7be.zip op-kernel-dev-f382d6e631fe424200ee0d8bb16539f5b7bef7be.tar.gz |
[PATCH] sanitize hppfs
* hppfs_iget() and its users are racy; there's no need to pollute icache
anyway, new_inode() works fine and is safe, unlike the current kludges
(these relied on overwriting ->i_ino before another iget_locked() gets
to that one - and did it after unlocking).
* merge hppfs_iget()/init_inode()/hppfs_read_inode(), while we are
at it.
* to pass proper vfsmount to dentry_open() store the reference
in hppfs superblock.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
--
Diffstat (limited to 'fs')
-rw-r--r-- | fs/hppfs/hppfs_kern.c | 113 |
1 files changed, 34 insertions, 79 deletions
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index 0c0f62f..8601d8e 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -18,8 +18,7 @@ #include <asm/uaccess.h> #include "os.h" -static int init_inode(struct inode *inode, struct dentry *dentry, - struct vfsmount *mnt); +static struct inode *get_inode(struct super_block *, struct dentry *); struct hppfs_data { struct list_head list; @@ -35,7 +34,6 @@ struct hppfs_private { struct hppfs_inode_info { struct dentry *proc_dentry; - struct vfsmount *proc_mnt; struct inode vfs_inode; }; @@ -137,40 +135,6 @@ static int file_removed(struct dentry *dentry, const char *file) return 0; } -static void hppfs_read_inode(struct inode *ino) -{ - struct inode *proc_ino; - - if (HPPFS_I(ino)->proc_dentry == NULL) - return; - - proc_ino = HPPFS_I(ino)->proc_dentry->d_inode; - ino->i_uid = proc_ino->i_uid; - ino->i_gid = proc_ino->i_gid; - ino->i_atime = proc_ino->i_atime; - ino->i_mtime = proc_ino->i_mtime; - ino->i_ctime = proc_ino->i_ctime; - ino->i_ino = proc_ino->i_ino; - ino->i_mode = proc_ino->i_mode; - ino->i_nlink = proc_ino->i_nlink; - ino->i_size = proc_ino->i_size; - ino->i_blocks = proc_ino->i_blocks; -} - -static struct inode *hppfs_iget(struct super_block *sb) -{ - struct inode *inode; - - inode = iget_locked(sb, 0); - if (!inode) - return ERR_PTR(-ENOMEM); - if (inode->i_state & I_NEW) { - hppfs_read_inode(inode); - unlock_new_inode(inode); - } - return inode; -} - static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, struct nameidata *nd) { @@ -206,23 +170,14 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, if (IS_ERR(proc_dentry)) return proc_dentry; - inode = hppfs_iget(ino->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); + err = -ENOMEM; + inode = get_inode(ino->i_sb, proc_dentry); + if (!inode) goto out_dput; - } - - err = init_inode(inode, proc_dentry, HPPFS_I(ino)->proc_mnt); - if (err) - goto out_put; - - hppfs_read_inode(inode); d_add(dentry, inode); return NULL; - out_put: - iput(inode); out_dput: dput(proc_dentry); out: @@ -489,7 +444,7 @@ static int hppfs_open(struct inode *inode, struct file *file) goto out_free2; proc_dentry = HPPFS_I(inode)->proc_dentry; - proc_mnt = HPPFS_I(inode)->proc_mnt; + proc_mnt = inode->i_sb->s_fs_info; /* XXX This isn't closed anywhere */ data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), @@ -547,7 +502,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file) goto out; proc_dentry = HPPFS_I(inode)->proc_dentry; - proc_mnt = HPPFS_I(inode)->proc_mnt; + proc_mnt = inode->i_sb->s_fs_info; data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), file_mode(file->f_mode)); err = PTR_ERR(data->proc_file); @@ -659,7 +614,6 @@ static struct inode *hppfs_alloc_inode(struct super_block *sb) return NULL; hi->proc_dentry = NULL; - hi->proc_mnt = NULL; inode_init_once(&hi->vfs_inode); return &hi->vfs_inode; } @@ -676,7 +630,7 @@ static void hppfs_destroy_inode(struct inode *inode) static void hppfs_put_super(struct super_block *sb) { - mntput(HPPFS_I(sb->s_root->d_inode)->proc_mnt); + mntput(sb->s_fs_info); } static const struct super_operations hppfs_sbops = { @@ -696,7 +650,7 @@ static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - proc_mnt = HPPFS_I(dentry->d_inode)->proc_mnt; + proc_mnt = dentry->d_sb->s_fs_info; proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); if (IS_ERR(proc_file)) @@ -717,7 +671,7 @@ static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) void *ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - proc_mnt = HPPFS_I(dentry->d_inode)->proc_mnt; + proc_mnt = dentry->d_sb->s_fs_info; proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); if (IS_ERR(proc_file)) @@ -739,9 +693,14 @@ static const struct inode_operations hppfs_link_iops = { .follow_link = hppfs_follow_link, }; -static int init_inode(struct inode *inode, struct dentry *dentry, - struct vfsmount *mnt) +static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) { + struct inode *proc_ino = dentry->d_inode; + struct inode *inode = new_inode(sb); + + if (!inode) + return ERR_PTR(-ENOMEM); + if (S_ISDIR(dentry->d_inode->i_mode)) { inode->i_op = &hppfs_dir_iops; inode->i_fop = &hppfs_dir_fops; @@ -754,7 +713,17 @@ static int init_inode(struct inode *inode, struct dentry *dentry, } HPPFS_I(inode)->proc_dentry = dentry; - HPPFS_I(inode)->proc_mnt = mnt; + + inode->i_uid = proc_ino->i_uid; + inode->i_gid = proc_ino->i_gid; + inode->i_atime = proc_ino->i_atime; + inode->i_mtime = proc_ino->i_mtime; + inode->i_ctime = proc_ino->i_ctime; + inode->i_ino = proc_ino->i_ino; + inode->i_mode = proc_ino->i_mode; + inode->i_nlink = proc_ino->i_nlink; + inode->i_size = proc_ino->i_size; + inode->i_blocks = proc_ino->i_blocks; return 0; } @@ -762,17 +731,10 @@ static int init_inode(struct inode *inode, struct dentry *dentry, static int hppfs_fill_super(struct super_block *sb, void *d, int silent) { struct inode *root_inode; - struct file_system_type *procfs; struct vfsmount *proc_mnt; - int err; + int err = -ENOENT; - err = -ENOENT; - procfs = get_fs_type("proc"); - if (!procfs) - goto out; - - proc_mnt = vfs_kern_mount(procfs, 0, procfs->name, NULL); - put_filesystem(procfs); + proc_mnt = do_kern_mount("proc", 0, "proc", NULL); if (IS_ERR(proc_mnt)) goto out; @@ -780,24 +742,17 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) sb->s_blocksize_bits = 10; sb->s_magic = HPPFS_SUPER_MAGIC; sb->s_op = &hppfs_sbops; - - root_inode = hppfs_iget(sb); - if (IS_ERR(root_inode)) { - err = PTR_ERR(root_inode); - goto out; - } - - err = init_inode(root_inode, proc_mnt->mnt_sb->s_root, proc_mnt); - if (err) - goto out_iput; + sb->s_fs_info = proc_mnt; err = -ENOMEM; + root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root); + if (!root_inode) + goto out_mntput; + sb->s_root = d_alloc_root(root_inode); if (!sb->s_root) goto out_iput; - hppfs_read_inode(root_inode); - return 0; out_iput: |