Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Aug 2016 19:37:11 +0000 (12:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Aug 2016 19:37:11 +0000 (12:37 -0700)
Pull ext4 fixes from Ted Ts'o:
 "Fix bugs that could cause kernel deadlocks or file system corruption
  while moving xattrs to expand the extended inode.

  Also add some sanity checks to the block group descriptors to make
  sure we don't end up overwriting the superblock"

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4: avoid deadlock when expanding inode size
  ext4: properly align shifted xattrs when expanding inodes
  ext4: fix xattr shifting when expanding inodes part 2
  ext4: fix xattr shifting when expanding inodes
  ext4: validate that metadata blocks do not overlap superblock
  ext4: reserve xattr index for the Hurd

1  2 
fs/ext4/inode.c
fs/ext4/super.c

diff --combined fs/ext4/inode.c
index 3131747199e160f5feca6c322a2b4190201108bf,13c95b290263a2b9b62b42ecce2c6ce1e4ed696a..c6ea25a190f88b09354e93cb7245586af2dbc87a
@@@ -987,7 -987,7 +987,7 @@@ struct buffer_head *ext4_bread(handle_
                return bh;
        if (!bh || buffer_uptodate(bh))
                return bh;
 -      ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh);
 +      ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh);
        wait_on_buffer(bh);
        if (buffer_uptodate(bh))
                return bh;
@@@ -1141,7 -1141,7 +1141,7 @@@ static int ext4_block_write_begin(struc
                if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
                    !buffer_unwritten(bh) &&
                    (block_start < from || block_end > to)) {
 -                      ll_rw_block(READ, 1, &bh);
 +                      ll_rw_block(REQ_OP_READ, 0, 1, &bh);
                        *wait_bh++ = bh;
                        decrypt = ext4_encrypted_inode(inode) &&
                                S_ISREG(inode->i_mode);
@@@ -3727,7 -3727,7 +3727,7 @@@ static int __ext4_block_zero_page_range
  
        if (!buffer_uptodate(bh)) {
                err = -EIO;
 -              ll_rw_block(READ, 1, &bh);
 +              ll_rw_block(REQ_OP_READ, 0, 1, &bh);
                wait_on_buffer(bh);
                /* Uhhuh. Read error. Complain and punt. */
                if (!buffer_uptodate(bh))
@@@ -4310,7 -4310,7 +4310,7 @@@ make_io
                trace_ext4_load_inode(inode);
                get_bh(bh);
                bh->b_end_io = end_buffer_read_sync;
 -              submit_bh(READ | REQ_META | REQ_PRIO, bh);
 +              submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh);
                wait_on_buffer(bh);
                if (!buffer_uptodate(bh)) {
                        EXT4_ERROR_INODE_BLOCK(inode, block,
@@@ -5466,8 -5466,6 +5466,6 @@@ int ext4_mark_inode_dirty(handle_t *han
                                                      sbi->s_want_extra_isize,
                                                      iloc, handle);
                        if (ret) {
-                               ext4_set_inode_state(inode,
-                                                    EXT4_STATE_NO_EXPAND);
                                if (mnt_count !=
                                        le16_to_cpu(sbi->s_es->s_mnt_count)) {
                                        ext4_warning(inode->i_sb,
diff --combined fs/ext4/super.c
index 1c593aa0218eee5cec9e2dac0adf8aaa97056d8b,da3146e8d49ad73b589a8b97bdb58062b36e7118..3ec8708989ca016c3dd9e7e2d9bd479a1cd9beaf
@@@ -2211,6 -2211,7 +2211,7 @@@ void ext4_group_desc_csum_set(struct su
  
  /* Called at mount-time, super-block is locked */
  static int ext4_check_descriptors(struct super_block *sb,
+                                 ext4_fsblk_t sb_block,
                                  ext4_group_t *first_not_zeroed)
  {
        struct ext4_sb_info *sbi = EXT4_SB(sb);
                        grp = i;
  
                block_bitmap = ext4_block_bitmap(sb, gdp);
+               if (block_bitmap == sb_block) {
+                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+                                "Block bitmap for group %u overlaps "
+                                "superblock", i);
+               }
                if (block_bitmap < first_block || block_bitmap > last_block) {
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
                               "Block bitmap for group %u not in group "
                        return 0;
                }
                inode_bitmap = ext4_inode_bitmap(sb, gdp);
+               if (inode_bitmap == sb_block) {
+                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+                                "Inode bitmap for group %u overlaps "
+                                "superblock", i);
+               }
                if (inode_bitmap < first_block || inode_bitmap > last_block) {
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
                               "Inode bitmap for group %u not in group "
                        return 0;
                }
                inode_table = ext4_inode_table(sb, gdp);
+               if (inode_table == sb_block) {
+                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+                                "Inode table for group %u overlaps "
+                                "superblock", i);
+               }
                if (inode_table < first_block ||
                    inode_table + sbi->s_itb_per_group - 1 > last_block) {
                        ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
@@@ -3757,7 -3773,7 +3773,7 @@@ static int ext4_fill_super(struct super
                        goto failed_mount2;
                }
        }
-       if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
+       if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
                ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
                ret = -EFSCORRUPTED;
                goto failed_mount2;
@@@ -4307,7 -4323,7 +4323,7 @@@ static journal_t *ext4_get_dev_journal(
                goto out_bdev;
        }
        journal->j_private = sb;
 -      ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer);
 +      ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer);
        wait_on_buffer(journal->j_sb_buffer);
        if (!buffer_uptodate(journal->j_sb_buffer)) {
                ext4_msg(sb, KERN_ERR, "I/O error on journal device");