Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org

authored by

Jan Kara and committed by
Theodore Ts'o
6050d47a d48458d4

+18 -10
+18 -10
fs/ext4/namei.c
··· 1816 1816 hinfo.hash_version += EXT4_SB(dir->i_sb)->s_hash_unsigned; 1817 1817 hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed; 1818 1818 ext4fs_dirhash(name, namelen, &hinfo); 1819 + memset(frames, 0, sizeof(frames)); 1819 1820 frame = frames; 1820 1821 frame->entries = entries; 1821 1822 frame->at = entries; 1822 1823 frame->bh = bh; 1823 1824 bh = bh2; 1824 1825 1825 - ext4_handle_dirty_dx_node(handle, dir, frame->bh); 1826 - ext4_handle_dirty_dirent_node(handle, dir, bh); 1826 + retval = ext4_handle_dirty_dx_node(handle, dir, frame->bh); 1827 + if (retval) 1828 + goto out_frames; 1829 + retval = ext4_handle_dirty_dirent_node(handle, dir, bh); 1830 + if (retval) 1831 + goto out_frames; 1827 1832 1828 1833 de = do_split(handle,dir, &bh, frame, &hinfo); 1829 1834 if (IS_ERR(de)) { 1830 - /* 1831 - * Even if the block split failed, we have to properly write 1832 - * out all the changes we did so far. Otherwise we can end up 1833 - * with corrupted filesystem. 1834 - */ 1835 - ext4_mark_inode_dirty(handle, dir); 1836 - dx_release(frames); 1837 - return PTR_ERR(de); 1835 + retval = PTR_ERR(de); 1836 + goto out_frames; 1838 1837 } 1839 1838 dx_release(frames); 1840 1839 1841 1840 retval = add_dirent_to_buf(handle, dentry, inode, de, bh); 1842 1841 brelse(bh); 1842 + return retval; 1843 + out_frames: 1844 + /* 1845 + * Even if the block split failed, we have to properly write 1846 + * out all the changes we did so far. Otherwise we can end up 1847 + * with corrupted filesystem. 1848 + */ 1849 + ext4_mark_inode_dirty(handle, dir); 1850 + dx_release(frames); 1843 1851 return retval; 1844 1852 } 1845 1853