diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 1f6bc05593df..b7dcbef4d5aa 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1395,14 +1395,25 @@ int ext4_read_inline_dir(struct file *file, } inline_size = ext4_get_inline_size(inode); + + /* + * Hold an additional reference to the iloc buffer to prevent + * use-after-free. The buffer could be freed by another thread + * during ext4_read_inline_data() if we don't hold a reference. + */ + get_bh(iloc.bh); + dir_buf = kmalloc(inline_size, GFP_NOFS); if (!dir_buf) { ret = -ENOMEM; + brelse(iloc.bh); up_read(&EXT4_I(inode)->xattr_sem); goto out; } ret = ext4_read_inline_data(inode, dir_buf, inline_size, &iloc); + brelse(iloc.bh); + up_read(&EXT4_I(inode)->xattr_sem); if (ret < 0) goto out;