ext3: Avoid uninitialized memory references with a corrupted htree directory
[pandora-kernel.git] / fs / ext3 / namei.c
index 672cea1..d093cbb 100644 (file)
@@ -858,6 +858,7 @@ static struct buffer_head *ext3_find_entry(struct inode *dir,
        struct buffer_head * bh_use[NAMEI_RA_SIZE];
        struct buffer_head * bh, *ret = NULL;
        unsigned long start, block, b;
+       const u8 *name = entry->name;
        int ra_max = 0;         /* Number of bh's in the readahead
                                   buffer, bh_use[] */
        int ra_ptr = 0;         /* Current index into readahead
@@ -871,6 +872,16 @@ static struct buffer_head *ext3_find_entry(struct inode *dir,
        namelen = entry->len;
        if (namelen > EXT3_NAME_LEN)
                return NULL;
+       if ((namelen <= 2) && (name[0] == '.') &&
+           (name[1] == '.' || name[1] == 0)) {
+               /*
+                * "." or ".." will only be in the first block
+                * NFS may look up ".."; "." should be handled by the VFS
+                */
+               block = start = 0;
+               nblocks = 1;
+               goto restart;
+       }
        if (is_dx(dir)) {
                bh = ext3_dx_find_entry(dir, entry, res_dir, &err);
                /*
@@ -961,9 +972,8 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
                        struct qstr *entry, struct ext3_dir_entry_2 **res_dir,
                        int *err)
 {
-       struct super_block * sb;
+       struct super_block *sb = dir->i_sb;
        struct dx_hash_info     hinfo;
-       u32 hash;
        struct dx_frame frames[2], *frame;
        struct ext3_dir_entry_2 *de, *top;
        struct buffer_head *bh;
@@ -972,18 +982,8 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
        int namelen = entry->len;
        const u8 *name = entry->name;
 
-       sb = dir->i_sb;
-       /* NFS may look up ".." - look at dx_root directory block */
-       if (namelen > 2 || name[0] != '.'|| (namelen == 2 && name[1] != '.')) {
-               if (!(frame = dx_probe(entry, dir, &hinfo, frames, err)))
-                       return NULL;
-       } else {
-               frame = frames;
-               frame->bh = NULL;                       /* for dx_release() */
-               frame->at = (struct dx_entry *)frames;  /* hack for zero entry*/
-               dx_set_block(frame->at, 0);             /* dx_root block is 0 */
-       }
-       hash = hinfo.hash;
+       if (!(frame = dx_probe(entry, dir, &hinfo, frames, err)))
+               return NULL;
        do {
                block = dx_get_block(frame->at);
                if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
@@ -1009,7 +1009,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
                }
                brelse (bh);
                /* Check to see if we should continue to search */
-               retval = ext3_htree_next_block(dir, hash, frame,
+               retval = ext3_htree_next_block(dir, hinfo.hash, frame,
                                               frames, NULL);
                if (retval < 0) {
                        ext3_warning(sb, __func__,