aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-02-23 04:53:53 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2008-03-19 06:42:18 -0400
commitf382d6e631fe424200ee0d8bb16539f5b7bef7be (patch)
tree03692bc57fa9cce5d12ace0b57fc03c11b6fa72f
parent1dd0dd111f1b7591f2848fffdb06044053f66c40 (diff)
[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> --
-rw-r--r--fs/hppfs/hppfs_kern.c113
1 files changed, 34 insertions, 79 deletions
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index 0c0f62f5164f..8601d8ef3b55 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -18,8 +18,7 @@
18#include <asm/uaccess.h> 18#include <asm/uaccess.h>
19#include "os.h" 19#include "os.h"
20 20
21static int init_inode(struct inode *inode, struct dentry *dentry, 21static struct inode *get_inode(struct super_block *, struct dentry *);
22 struct vfsmount *mnt);
23 22
24struct hppfs_data { 23struct hppfs_data {
25 struct list_head list; 24 struct list_head list;
@@ -35,7 +34,6 @@ struct hppfs_private {
35 34
36struct hppfs_inode_info { 35struct hppfs_inode_info {
37 struct dentry *proc_dentry; 36 struct dentry *proc_dentry;
38 struct vfsmount *proc_mnt;
39 struct inode vfs_inode; 37 struct inode vfs_inode;
40}; 38};
41 39
@@ -137,40 +135,6 @@ static int file_removed(struct dentry *dentry, const char *file)
137 return 0; 135 return 0;
138} 136}
139 137
140static void hppfs_read_inode(struct inode *ino)
141{
142 struct inode *proc_ino;
143
144 if (HPPFS_I(ino)->proc_dentry == NULL)
145 return;
146
147 proc_ino = HPPFS_I(ino)->proc_dentry->d_inode;
148 ino->i_uid = proc_ino->i_uid;
149 ino->i_gid = proc_ino->i_gid;
150 ino->i_atime = proc_ino->i_atime;
151 ino->i_mtime = proc_ino->i_mtime;
152 ino->i_ctime = proc_ino->i_ctime;
153 ino->i_ino = proc_ino->i_ino;
154 ino->i_mode = proc_ino->i_mode;
155 ino->i_nlink = proc_ino->i_nlink;
156 ino->i_size = proc_ino->i_size;
157 ino->i_blocks = proc_ino->i_blocks;
158}
159
160static struct inode *hppfs_iget(struct super_block *sb)
161{
162 struct inode *inode;
163
164 inode = iget_locked(sb, 0);
165 if (!inode)
166 return ERR_PTR(-ENOMEM);
167 if (inode->i_state & I_NEW) {
168 hppfs_read_inode(inode);
169 unlock_new_inode(inode);
170 }
171 return inode;
172}
173
174static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, 138static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
175 struct nameidata *nd) 139 struct nameidata *nd)
176{ 140{
@@ -206,23 +170,14 @@ static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
206 if (IS_ERR(proc_dentry)) 170 if (IS_ERR(proc_dentry))
207 return proc_dentry; 171 return proc_dentry;
208 172
209 inode = hppfs_iget(ino->i_sb); 173 err = -ENOMEM;
210 if (IS_ERR(inode)) { 174 inode = get_inode(ino->i_sb, proc_dentry);
211 err = PTR_ERR(inode); 175 if (!inode)
212 goto out_dput; 176 goto out_dput;
213 }
214
215 err = init_inode(inode, proc_dentry, HPPFS_I(ino)->proc_mnt);
216 if (err)
217 goto out_put;
218
219 hppfs_read_inode(inode);
220 177
221 d_add(dentry, inode); 178 d_add(dentry, inode);
222 return NULL; 179 return NULL;
223 180
224 out_put:
225 iput(inode);
226 out_dput: 181 out_dput:
227 dput(proc_dentry); 182 dput(proc_dentry);
228 out: 183 out:
@@ -489,7 +444,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
489 goto out_free2; 444 goto out_free2;
490 445
491 proc_dentry = HPPFS_I(inode)->proc_dentry; 446 proc_dentry = HPPFS_I(inode)->proc_dentry;
492 proc_mnt = HPPFS_I(inode)->proc_mnt; 447 proc_mnt = inode->i_sb->s_fs_info;
493 448
494 /* XXX This isn't closed anywhere */ 449 /* XXX This isn't closed anywhere */
495 data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), 450 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)
547 goto out; 502 goto out;
548 503
549 proc_dentry = HPPFS_I(inode)->proc_dentry; 504 proc_dentry = HPPFS_I(inode)->proc_dentry;
550 proc_mnt = HPPFS_I(inode)->proc_mnt; 505 proc_mnt = inode->i_sb->s_fs_info;
551 data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), 506 data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
552 file_mode(file->f_mode)); 507 file_mode(file->f_mode));
553 err = PTR_ERR(data->proc_file); 508 err = PTR_ERR(data->proc_file);
@@ -659,7 +614,6 @@ static struct inode *hppfs_alloc_inode(struct super_block *sb)
659 return NULL; 614 return NULL;
660 615
661 hi->proc_dentry = NULL; 616 hi->proc_dentry = NULL;
662 hi->proc_mnt = NULL;
663 inode_init_once(&hi->vfs_inode); 617 inode_init_once(&hi->vfs_inode);
664 return &hi->vfs_inode; 618 return &hi->vfs_inode;
665} 619}
@@ -676,7 +630,7 @@ static void hppfs_destroy_inode(struct inode *inode)
676 630
677static void hppfs_put_super(struct super_block *sb) 631static void hppfs_put_super(struct super_block *sb)
678{ 632{
679 mntput(HPPFS_I(sb->s_root->d_inode)->proc_mnt); 633 mntput(sb->s_fs_info);
680} 634}
681 635
682static const struct super_operations hppfs_sbops = { 636static const struct super_operations hppfs_sbops = {
@@ -696,7 +650,7 @@ static int hppfs_readlink(struct dentry *dentry, char __user *buffer,
696 int ret; 650 int ret;
697 651
698 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 652 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
699 proc_mnt = HPPFS_I(dentry->d_inode)->proc_mnt; 653 proc_mnt = dentry->d_sb->s_fs_info;
700 654
701 proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); 655 proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY);
702 if (IS_ERR(proc_file)) 656 if (IS_ERR(proc_file))
@@ -717,7 +671,7 @@ static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd)
717 void *ret; 671 void *ret;
718 672
719 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; 673 proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
720 proc_mnt = HPPFS_I(dentry->d_inode)->proc_mnt; 674 proc_mnt = dentry->d_sb->s_fs_info;
721 675
722 proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); 676 proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY);
723 if (IS_ERR(proc_file)) 677 if (IS_ERR(proc_file))
@@ -739,9 +693,14 @@ static const struct inode_operations hppfs_link_iops = {
739 .follow_link = hppfs_follow_link, 693 .follow_link = hppfs_follow_link,
740}; 694};
741 695
742static int init_inode(struct inode *inode, struct dentry *dentry, 696static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
743 struct vfsmount *mnt)
744{ 697{
698 struct inode *proc_ino = dentry->d_inode;
699 struct inode *inode = new_inode(sb);
700
701 if (!inode)
702 return ERR_PTR(-ENOMEM);
703
745 if (S_ISDIR(dentry->d_inode->i_mode)) { 704 if (S_ISDIR(dentry->d_inode->i_mode)) {
746 inode->i_op = &hppfs_dir_iops; 705 inode->i_op = &hppfs_dir_iops;
747 inode->i_fop = &hppfs_dir_fops; 706 inode->i_fop = &hppfs_dir_fops;
@@ -754,7 +713,17 @@ static int init_inode(struct inode *inode, struct dentry *dentry,
754 } 713 }
755 714
756 HPPFS_I(inode)->proc_dentry = dentry; 715 HPPFS_I(inode)->proc_dentry = dentry;
757 HPPFS_I(inode)->proc_mnt = mnt; 716
717 inode->i_uid = proc_ino->i_uid;
718 inode->i_gid = proc_ino->i_gid;
719 inode->i_atime = proc_ino->i_atime;
720 inode->i_mtime = proc_ino->i_mtime;
721 inode->i_ctime = proc_ino->i_ctime;
722 inode->i_ino = proc_ino->i_ino;
723 inode->i_mode = proc_ino->i_mode;
724 inode->i_nlink = proc_ino->i_nlink;
725 inode->i_size = proc_ino->i_size;
726 inode->i_blocks = proc_ino->i_blocks;
758 727
759 return 0; 728 return 0;
760} 729}
@@ -762,17 +731,10 @@ static int init_inode(struct inode *inode, struct dentry *dentry,
762static int hppfs_fill_super(struct super_block *sb, void *d, int silent) 731static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
763{ 732{
764 struct inode *root_inode; 733 struct inode *root_inode;
765 struct file_system_type *procfs;
766 struct vfsmount *proc_mnt; 734 struct vfsmount *proc_mnt;
767 int err; 735 int err = -ENOENT;
768 736
769 err = -ENOENT; 737 proc_mnt = do_kern_mount("proc", 0, "proc", NULL);
770 procfs = get_fs_type("proc");
771 if (!procfs)
772 goto out;
773
774 proc_mnt = vfs_kern_mount(procfs, 0, procfs->name, NULL);
775 put_filesystem(procfs);
776 if (IS_ERR(proc_mnt)) 738 if (IS_ERR(proc_mnt))
777 goto out; 739 goto out;
778 740
@@ -780,24 +742,17 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
780 sb->s_blocksize_bits = 10; 742 sb->s_blocksize_bits = 10;
781 sb->s_magic = HPPFS_SUPER_MAGIC; 743 sb->s_magic = HPPFS_SUPER_MAGIC;
782 sb->s_op = &hppfs_sbops; 744 sb->s_op = &hppfs_sbops;
783 745 sb->s_fs_info = proc_mnt;
784 root_inode = hppfs_iget(sb);
785 if (IS_ERR(root_inode)) {
786 err = PTR_ERR(root_inode);
787 goto out;
788 }
789
790 err = init_inode(root_inode, proc_mnt->mnt_sb->s_root, proc_mnt);
791 if (err)
792 goto out_iput;
793 746
794 err = -ENOMEM; 747 err = -ENOMEM;
748 root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root);
749 if (!root_inode)
750 goto out_mntput;
751
795 sb->s_root = d_alloc_root(root_inode); 752 sb->s_root = d_alloc_root(root_inode);
796 if (!sb->s_root) 753 if (!sb->s_root)
797 goto out_iput; 754 goto out_iput;
798 755
799 hppfs_read_inode(root_inode);
800
801 return 0; 756 return 0;
802 757
803 out_iput: 758 out_iput: