Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6050d47a authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o
Browse files

ext4: bail out from make_indexed_dir() on first error



When ext4_handle_dirty_dx_node() or ext4_handle_dirty_dirent_node()
fail, there's really something wrong with the fs and there's no point in
continuing further. Just return error from make_indexed_dir() in that
case. Also initialize frames array so that if we return early due to
error, dx_release() doesn't try to dereference uninitialized memory
(which could happen also due to error in do_split()).

Coverity-id: 741300
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
parent d48458d4
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -1816,17 +1816,31 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
		hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned;
	hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
	ext4fs_dirhash(name, namelen, &hinfo);
	memset(frames, 0, sizeof(frames));
	frame = frames;
	frame->entries = entries;
	frame->at = entries;
	frame->bh = bh;
	bh = bh2;

	ext4_handle_dirty_dx_node(handle, dir, frame->bh);
	ext4_handle_dirty_dirent_node(handle, dir, bh);
	retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
	if (retval)
		goto out_frames;	
	retval = ext4_handle_dirty_dirent_node(handle, dir, bh);
	if (retval)
		goto out_frames;	

	de = do_split(handle,dir, &bh, frame, &hinfo);
	if (IS_ERR(de)) {
		retval = PTR_ERR(de);
		goto out_frames;
	}
	dx_release(frames);

	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
	brelse(bh);
	return retval;
out_frames:
	/*
	 * Even if the block split failed, we have to properly write
	 * out all the changes we did so far. Otherwise we can end up
@@ -1834,12 +1848,6 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
	 */
	ext4_mark_inode_dirty(handle, dir);
	dx_release(frames);
		return PTR_ERR(de);
	}
	dx_release(frames);

	retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
	brelse(bh);
	return retval;
}