Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Sep 2018 07:13:47 +0000 (09:13 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 17 Sep 2018 07:13:47 +0000 (09:13 +0200)
Ted writes:
Various ext4 bug fixes; primarily making ext4 more robust against
maliciously crafted file systems, and some DAX fixes.

* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  ext4, dax: set ext4_dax_aops for dax files
  ext4, dax: add ext4_bmap to ext4_dax_aops
  ext4: don't mark mmp buffer head dirty
  ext4: show test_dummy_encryption mount option in /proc/mounts
  ext4: close race between direct IO and ext4_break_layouts()
  ext4: fix online resizing for bigalloc file systems with a 1k block size
  ext4: fix online resize's handling of a too-small final block group
  ext4: recalucate superblock checksum after updating free blocks/inodes
  ext4: avoid arithemetic overflow that can trigger a BUG
  ext4: avoid divide by zero fault when deleting corrupted inline directories
  ext4: check to make sure the rename(2)'s destination is not freed
  ext4: add nonstring annotations to ext4.h

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

diff --combined fs/ext4/ext4.h
index 0f0edd1cd0cd259f81eb0349e25ae9efb34641cc,ac05bd86643a74ad6ae11e2d9ed78ef198cbe5ae..caff935fbeb8f100049bf0aab09f7e14c53fa40e
  #define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_EXT4_FS_ENCRYPTION)
  #include <linux/fscrypt.h>
  
+ #include <linux/compiler.h>
+ /* Until this gets included into linux/compiler-gcc.h */
+ #ifndef __nonstring
+ #if defined(GCC_VERSION) && (GCC_VERSION >= 80000)
+ #define __nonstring __attribute__((nonstring))
+ #else
+ #define __nonstring
+ #endif
+ #endif
  /*
   * The fourth extended filesystem constants/structures
   */
@@@ -675,6 -686,9 +686,9 @@@ enum 
  /* Max physical block we can address w/o extents */
  #define EXT4_MAX_BLOCK_FILE_PHYS      0xFFFFFFFF
  
+ /* Max logical block we can support */
+ #define EXT4_MAX_LOGICAL_BLOCK                0xFFFFFFFF
  /*
   * Structure of an inode on the disk
   */
@@@ -1226,7 -1240,7 +1240,7 @@@ struct ext4_super_block 
        __le32  s_feature_ro_compat;    /* readonly-compatible feature set */
  /*68*/        __u8    s_uuid[16];             /* 128-bit uuid for volume */
  /*78*/        char    s_volume_name[16];      /* volume name */
- /*88*/        char    s_last_mounted[64];     /* directory where last mounted */
+ /*88*/        char    s_last_mounted[64] __nonstring; /* directory where last mounted */
  /*C8*/        __le32  s_algorithm_usage_bitmap; /* For compression */
        /*
         * Performance hints.  Directory preallocation should only
        __le32  s_first_error_time;     /* first time an error happened */
        __le32  s_first_error_ino;      /* inode involved in first error */
        __le64  s_first_error_block;    /* block involved of first error */
-       __u8    s_first_error_func[32]; /* function where the error happened */
+       __u8    s_first_error_func[32] __nonstring;     /* function where the error happened */
        __le32  s_first_error_line;     /* line number where error happened */
        __le32  s_last_error_time;      /* most recent time of an error */
        __le32  s_last_error_ino;       /* inode involved in last error */
        __le32  s_last_error_line;      /* line number where error happened */
        __le64  s_last_error_block;     /* block involved of last error */
-       __u8    s_last_error_func[32];  /* function where the error happened */
+       __u8    s_last_error_func[32] __nonstring;      /* function where the error happened */
  #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts)
        __u8    s_mount_opts[64];
        __le32  s_usr_quota_inum;       /* inode for tracking user quota */
@@@ -3062,7 -3076,7 +3076,7 @@@ static inline void ext4_set_de_type(str
  /* readpages.c */
  extern int ext4_mpage_readpages(struct address_space *mapping,
                                struct list_head *pages, struct page *page,
 -                              unsigned nr_pages);
 +                              unsigned nr_pages, bool is_readahead);
  
  /* symlink.c */
  extern const struct inode_operations ext4_encrypted_symlink_inode_operations;
diff --combined fs/ext4/inode.c
index d0dd585add6a005684c569d6edaecc481f926f2d,f73f18a68165675eba2147b57c28a2de9b2fe572..d767e993591d93f335ae85b876a5c12ceae35b7a
@@@ -3325,8 -3325,7 +3325,8 @@@ static int ext4_readpage(struct file *f
                ret = ext4_readpage_inline(inode, page);
  
        if (ret == -EAGAIN)
 -              return ext4_mpage_readpages(page->mapping, NULL, page, 1);
 +              return ext4_mpage_readpages(page->mapping, NULL, page, 1,
 +                                              false);
  
        return ret;
  }
@@@ -3341,7 -3340,7 +3341,7 @@@ ext4_readpages(struct file *file, struc
        if (ext4_has_inline_data(inode))
                return 0;
  
 -      return ext4_mpage_readpages(mapping, pages, NULL, nr_pages);
 +      return ext4_mpage_readpages(mapping, pages, NULL, nr_pages, true);
  }
  
  static void ext4_invalidatepage(struct page *page, unsigned int offset,
@@@ -3413,12 -3412,16 +3413,16 @@@ static int ext4_iomap_begin(struct inod
  {
        struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
        unsigned int blkbits = inode->i_blkbits;
-       unsigned long first_block = offset >> blkbits;
-       unsigned long last_block = (offset + length - 1) >> blkbits;
+       unsigned long first_block, last_block;
        struct ext4_map_blocks map;
        bool delalloc = false;
        int ret;
  
+       if ((offset >> blkbits) > EXT4_MAX_LOGICAL_BLOCK)
+               return -EINVAL;
+       first_block = offset >> blkbits;
+       last_block = min_t(loff_t, (offset + length - 1) >> blkbits,
+                          EXT4_MAX_LOGICAL_BLOCK);
  
        if (flags & IOMAP_REPORT) {
                if (ext4_has_inline_data(inode)) {
@@@ -3948,6 -3951,7 +3952,7 @@@ static const struct address_space_opera
        .writepages             = ext4_dax_writepages,
        .direct_IO              = noop_direct_IO,
        .set_page_dirty         = noop_set_page_dirty,
+       .bmap                   = ext4_bmap,
        .invalidatepage         = noop_invalidatepage,
  };
  
@@@ -4192,9 -4196,8 +4197,8 @@@ int ext4_update_disksize_before_punch(s
        return 0;
  }
  
- static void ext4_wait_dax_page(struct ext4_inode_info *ei, bool *did_unlock)
+ static void ext4_wait_dax_page(struct ext4_inode_info *ei)
  {
-       *did_unlock = true;
        up_write(&ei->i_mmap_sem);
        schedule();
        down_write(&ei->i_mmap_sem);
@@@ -4204,14 -4207,12 +4208,12 @@@ int ext4_break_layouts(struct inode *in
  {
        struct ext4_inode_info *ei = EXT4_I(inode);
        struct page *page;
-       bool retry;
        int error;
  
        if (WARN_ON_ONCE(!rwsem_is_locked(&ei->i_mmap_sem)))
                return -EINVAL;
  
        do {
-               retry = false;
                page = dax_layout_busy_page(inode->i_mapping);
                if (!page)
                        return 0;
                error = ___wait_var_event(&page->_refcount,
                                atomic_read(&page->_refcount) == 1,
                                TASK_INTERRUPTIBLE, 0, 0,
-                               ext4_wait_dax_page(ei, &retry));
-       } while (error == 0 && retry);
+                               ext4_wait_dax_page(ei));
+       } while (error == 0);
  
        return error;
  }
@@@ -4895,6 -4896,7 +4897,7 @@@ struct inode *ext4_iget(struct super_bl
                 * not initialized on a new filesystem. */
        }
        ei->i_flags = le32_to_cpu(raw_inode->i_flags);
+       ext4_set_inode_flags(inode);
        inode->i_blocks = ext4_inode_blocks(raw_inode, ei);
        ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo);
        if (ext4_has_feature_64bit(sb))
                goto bad_inode;
        }
        brelse(iloc.bh);
-       ext4_set_inode_flags(inode);
  
        unlock_new_inode(inode);
        return inode;
diff --combined fs/ext4/super.c
index 5863fd22e90bb20c102274f3e320637858bdef87,a430fb3e9720da0caa0ed449a0f8d808bd7bbb30..1145109968efd356a812744537d94d929b62f7ce
@@@ -2145,6 -2145,8 +2145,8 @@@ static int _ext4_show_options(struct se
                SEQ_OPTS_PRINT("max_dir_size_kb=%u", sbi->s_max_dir_size_kb);
        if (test_opt(sb, DATA_ERR_ABORT))
                SEQ_OPTS_PUTS("data_err=abort");
+       if (DUMMY_ENCRYPTION_ENABLED(sbi))
+               SEQ_OPTS_PUTS("test_dummy_encryption");
  
        ext4_show_quota_options(seq, sb);
        return 0;
@@@ -3529,7 -3531,7 +3531,7 @@@ static int ext4_fill_super(struct super
        sbi->s_sb_block = sb_block;
        if (sb->s_bdev->bd_part)
                sbi->s_sectors_written_start =
 -                      part_stat_read(sb->s_bdev->bd_part, sectors[1]);
 +                      part_stat_read(sb->s_bdev->bd_part, sectors[STAT_WRITE]);
  
        /* Cleanup superblock name */
        strreplace(sb->s_id, '/', '!');
@@@ -4378,11 -4380,13 +4380,13 @@@ no_journal
        block = ext4_count_free_clusters(sb);
        ext4_free_blocks_count_set(sbi->s_es, 
                                   EXT4_C2B(sbi, block));
+       ext4_superblock_csum_set(sb);
        err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
                                  GFP_KERNEL);
        if (!err) {
                unsigned long freei = ext4_count_free_inodes(sb);
                sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
+               ext4_superblock_csum_set(sb);
                err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
                                          GFP_KERNEL);
        }
@@@ -4838,8 -4842,7 +4842,8 @@@ static int ext4_commit_super(struct sup
        if (sb->s_bdev->bd_part)
                es->s_kbytes_written =
                        cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
 -                          ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) -
 +                          ((part_stat_read(sb->s_bdev->bd_part,
 +                                           sectors[STAT_WRITE]) -
                              EXT4_SB(sb)->s_sectors_written_start) >> 1));
        else
                es->s_kbytes_written =