Have ext2 reject file handles with bad inode numbers early.
authorNeil Brown <neilb@suse.de>
Fri, 4 Aug 2006 00:53:40 +0000 (10:53 +1000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 8 Sep 2006 21:51:37 +0000 (14:51 -0700)
This prevents bad inode numbers from triggering errors in
ext2_get_inode.

Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
fs/ext2/super.c

index 7e30bae174edce379a67c212953a90c5912b1a20..e51d1a8f50fb935edc4adda400cf720d44eb1a5f 100644 (file)
@@ -252,6 +252,46 @@ static struct super_operations ext2_sops = {
 #endif
 };
 
+static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp)
+{
+       __u32 *objp = vobjp;
+       unsigned long ino = objp[0];
+       __u32 generation = objp[1];
+       struct inode *inode;
+       struct dentry *result;
+
+       if (ino != EXT2_ROOT_INO && ino < EXT2_FIRST_INO(sb))
+               return ERR_PTR(-ESTALE);
+       if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count))
+               return ERR_PTR(-ESTALE);
+
+       /* iget isn't really right if the inode is currently unallocated!!
+        * ext2_read_inode currently does appropriate checks, but
+        * it might be "neater" to call ext2_get_inode first and check
+        * if the inode is valid.....
+        */
+       inode = iget(sb, ino);
+       if (inode == NULL)
+               return ERR_PTR(-ENOMEM);
+       if (is_bad_inode(inode)
+           || (generation && inode->i_generation != generation)
+               ) {
+               /* we didn't find the right inode.. */
+               iput(inode);
+               return ERR_PTR(-ESTALE);
+       }
+       /* now to find a dentry.
+        * If possible, get a well-connected one
+        */
+       result = d_alloc_anon(inode);
+       if (!result) {
+               iput(inode);
+               return ERR_PTR(-ENOMEM);
+       }
+       return result;
+}
+
+
 /* Yes, most of these are left as NULL!!
  * A NULL value implies the default, which works with ext2-like file
  * systems, but can be improved upon.
@@ -259,6 +299,7 @@ static struct super_operations ext2_sops = {
  */
 static struct export_operations ext2_export_ops = {
        .get_parent = ext2_get_parent,
+       .get_dentry = ext2_get_dentry,
 };
 
 static unsigned long get_sb_block(void **data)