ext4: fix buffer leak in __ext4_read_dirblock() on error path
[sfrench/cifs-2.6.git] / fs / ext4 / namei.c
index 116ff68c5bd4337b7cb751330d091fcab24eecba..6a6b90363ef1b2344c053d0a751a4c8a5989cde2 100644 (file)
@@ -126,6 +126,7 @@ static struct buffer_head *__ext4_read_dirblock(struct inode *inode,
        if (!is_dx_block && type == INDEX) {
                ext4_error_inode(inode, func, line, block,
                       "directory leaf block found instead of index block");
+               brelse(bh);
                return ERR_PTR(-EFSCORRUPTED);
        }
        if (!ext4_has_metadata_csum(inode->i_sb) ||
@@ -2261,7 +2262,7 @@ again:
                        dxroot->info.indirect_levels += 1;
                        dxtrace(printk(KERN_DEBUG
                                       "Creating %d level index...\n",
-                                      info->indirect_levels));
+                                      dxroot->info.indirect_levels));
                        err = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
                        if (err)
                                goto journal_error;
@@ -2811,7 +2812,9 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
                        list_del_init(&EXT4_I(inode)->i_orphan);
                        mutex_unlock(&sbi->s_orphan_lock);
                }
-       }
+       } else
+               brelse(iloc.bh);
+
        jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
        jbd_debug(4, "orphan inode %lu will point to %d\n",
                        inode->i_ino, NEXT_ORPHAN(inode));
@@ -3478,6 +3481,12 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        int credits;
        u8 old_file_type;
 
+       if (new.inode && new.inode->i_nlink == 0) {
+               EXT4_ERROR_INODE(new.inode,
+                                "target of rename is already freed");
+               return -EFSCORRUPTED;
+       }
+
        if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT)) &&
            (!projid_eq(EXT4_I(new_dir)->i_projid,
                        EXT4_I(old_dentry->d_inode)->i_projid)))