]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 May 2020 12:10:19 +0000 (14:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 May 2020 12:10:19 +0000 (14:10 +0200)
added patches:
ext4-avoid-declaring-fs-inconsistent-due-to-invalid-file-handles.patch
ext4-don-t-perform-block-validity-checks-on-the-journal-inode.patch
ext4-fix-block-validity-checks-for-journal-inodes-using-indirect-blocks.patch
ext4-protect-journal-inode-s-blocks-using-block_validity.patch
ext4-unsigned-int-compared-against-zero.patch

queue-4.14/ext4-avoid-declaring-fs-inconsistent-due-to-invalid-file-handles.patch [new file with mode: 0644]
queue-4.14/ext4-don-t-perform-block-validity-checks-on-the-journal-inode.patch [new file with mode: 0644]
queue-4.14/ext4-fix-block-validity-checks-for-journal-inodes-using-indirect-blocks.patch [new file with mode: 0644]
queue-4.14/ext4-protect-journal-inode-s-blocks-using-block_validity.patch [new file with mode: 0644]
queue-4.14/ext4-unsigned-int-compared-against-zero.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/ext4-avoid-declaring-fs-inconsistent-due-to-invalid-file-handles.patch b/queue-4.14/ext4-avoid-declaring-fs-inconsistent-due-to-invalid-file-handles.patch
new file mode 100644 (file)
index 0000000..18632c0
--- /dev/null
@@ -0,0 +1,328 @@
+From 8a363970d1dc38c4ec4ad575c862f776f468d057 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 19 Dec 2018 12:29:13 -0500
+Subject: ext4: avoid declaring fs inconsistent due to invalid file handles
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 8a363970d1dc38c4ec4ad575c862f776f468d057 upstream.
+
+If we receive a file handle, either from NFS or open_by_handle_at(2),
+and it points at an inode which has not been initialized, and the file
+system has metadata checksums enabled, we shouldn't try to get the
+inode, discover the checksum is invalid, and then declare the file
+system as being inconsistent.
+
+This can be reproduced by creating a test file system via "mke2fs -t
+ext4 -O metadata_csum /tmp/foo.img 8M", mounting it, cd'ing into that
+directory, and then running the following program.
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+
+struct handle {
+       struct file_handle fh;
+       unsigned char fid[MAX_HANDLE_SZ];
+};
+
+int main(int argc, char **argv)
+{
+       struct handle h = {{8, 1 }, { 12, }};
+
+       open_by_handle_at(AT_FDCWD, &h.fh, O_RDONLY);
+       return 0;
+}
+
+Google-Bug-Id: 120690101
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Ashwin H <ashwinh@vmware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h   |   15 +++++++++++++--
+ fs/ext4/ialloc.c |    2 +-
+ fs/ext4/inode.c  |   49 ++++++++++++++++++++++++++++++++++---------------
+ fs/ext4/ioctl.c  |    2 +-
+ fs/ext4/namei.c  |    4 ++--
+ fs/ext4/resize.c |    5 +++--
+ fs/ext4/super.c  |   19 +++++--------------
+ fs/ext4/xattr.c  |    5 +++--
+ 8 files changed, 62 insertions(+), 39 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -2509,8 +2509,19 @@ int do_journal_get_write_access(handle_t
+ #define FALL_BACK_TO_NONDELALLOC 1
+ #define CONVERT_INLINE_DATA    2
+-extern struct inode *ext4_iget(struct super_block *, unsigned long);
+-extern struct inode *ext4_iget_normal(struct super_block *, unsigned long);
++typedef enum {
++      EXT4_IGET_NORMAL =      0,
++      EXT4_IGET_SPECIAL =     0x0001, /* OK to iget a system inode */
++      EXT4_IGET_HANDLE =      0x0002  /* Inode # is from a handle */
++} ext4_iget_flags;
++
++extern struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
++                               ext4_iget_flags flags, const char *function,
++                               unsigned int line);
++
++#define ext4_iget(sb, ino, flags) \
++      __ext4_iget((sb), (ino), (flags), __func__, __LINE__)
++
+ extern int  ext4_write_inode(struct inode *, struct writeback_control *);
+ extern int  ext4_setattr(struct dentry *, struct iattr *);
+ extern int  ext4_getattr(const struct path *, struct kstat *, u32, unsigned int);
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1239,7 +1239,7 @@ struct inode *ext4_orphan_get(struct sup
+       if (!ext4_test_bit(bit, bitmap_bh->b_data))
+               goto bad_orphan;
+-      inode = ext4_iget(sb, ino);
++      inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
+               ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4695,7 +4695,9 @@ int ext4_get_projid(struct inode *inode,
+       return 0;
+ }
+-struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
++struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
++                        ext4_iget_flags flags, const char *function,
++                        unsigned int line)
+ {
+       struct ext4_iloc iloc;
+       struct ext4_inode *raw_inode;
+@@ -4709,6 +4711,18 @@ struct inode *ext4_iget(struct super_blo
+       gid_t i_gid;
+       projid_t i_projid;
++      if (((flags & EXT4_IGET_NORMAL) &&
++           (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)) ||
++          (ino < EXT4_ROOT_INO) ||
++          (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))) {
++              if (flags & EXT4_IGET_HANDLE)
++                      return ERR_PTR(-ESTALE);
++              __ext4_error(sb, function, line,
++                           "inode #%lu: comm %s: iget: illegal inode #",
++                           ino, current->comm);
++              return ERR_PTR(-EFSCORRUPTED);
++      }
++
+       inode = iget_locked(sb, ino);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+@@ -4724,18 +4738,26 @@ struct inode *ext4_iget(struct super_blo
+       raw_inode = ext4_raw_inode(&iloc);
+       if ((ino == EXT4_ROOT_INO) && (raw_inode->i_links_count == 0)) {
+-              EXT4_ERROR_INODE(inode, "root inode unallocated");
++              ext4_error_inode(inode, function, line, 0,
++                               "iget: root inode unallocated");
+               ret = -EFSCORRUPTED;
+               goto bad_inode;
+       }
++      if ((flags & EXT4_IGET_HANDLE) &&
++          (raw_inode->i_links_count == 0) && (raw_inode->i_mode == 0)) {
++              ret = -ESTALE;
++              goto bad_inode;
++      }
++
+       if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
+               ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize);
+               if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize >
+                       EXT4_INODE_SIZE(inode->i_sb) ||
+                   (ei->i_extra_isize & 3)) {
+-                      EXT4_ERROR_INODE(inode,
+-                                       "bad extra_isize %u (inode size %u)",
++                      ext4_error_inode(inode, function, line, 0,
++                                       "iget: bad extra_isize %u "
++                                       "(inode size %u)",
+                                        ei->i_extra_isize,
+                                        EXT4_INODE_SIZE(inode->i_sb));
+                       ret = -EFSCORRUPTED;
+@@ -4757,7 +4779,8 @@ struct inode *ext4_iget(struct super_blo
+       }
+       if (!ext4_inode_csum_verify(inode, raw_inode, ei)) {
+-              EXT4_ERROR_INODE(inode, "checksum invalid");
++              ext4_error_inode(inode, function, line, 0,
++                               "iget: checksum invalid");
+               ret = -EFSBADCRC;
+               goto bad_inode;
+       }
+@@ -4813,7 +4836,8 @@ struct inode *ext4_iget(struct super_blo
+                       ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
+       inode->i_size = ext4_isize(sb, raw_inode);
+       if ((size = i_size_read(inode)) < 0) {
+-              EXT4_ERROR_INODE(inode, "bad i_size value: %lld", size);
++              ext4_error_inode(inode, function, line, 0,
++                               "iget: bad i_size value: %lld", size);
+               ret = -EFSCORRUPTED;
+               goto bad_inode;
+       }
+@@ -4899,7 +4923,8 @@ struct inode *ext4_iget(struct super_blo
+       ret = 0;
+       if (ei->i_file_acl &&
+           !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) {
+-              EXT4_ERROR_INODE(inode, "bad extended attribute block %llu",
++              ext4_error_inode(inode, function, line, 0,
++                               "iget: bad extended attribute block %llu",
+                                ei->i_file_acl);
+               ret = -EFSCORRUPTED;
+               goto bad_inode;
+@@ -4954,7 +4979,8 @@ struct inode *ext4_iget(struct super_blo
+               make_bad_inode(inode);
+       } else {
+               ret = -EFSCORRUPTED;
+-              EXT4_ERROR_INODE(inode, "bogus i_mode (%o)", inode->i_mode);
++              ext4_error_inode(inode, function, line, 0,
++                               "iget: bogus i_mode (%o)", inode->i_mode);
+               goto bad_inode;
+       }
+       brelse(iloc.bh);
+@@ -4969,13 +4995,6 @@ bad_inode:
+       return ERR_PTR(ret);
+ }
+-struct inode *ext4_iget_normal(struct super_block *sb, unsigned long ino)
+-{
+-      if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
+-              return ERR_PTR(-EFSCORRUPTED);
+-      return ext4_iget(sb, ino);
+-}
+-
+ static int ext4_inode_blocks_set(handle_t *handle,
+                               struct ext4_inode *raw_inode,
+                               struct ext4_inode_info *ei)
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -111,7 +111,7 @@ static long swap_inode_boot_loader(struc
+       if (!inode_owner_or_capable(inode) || !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+-      inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO);
++      inode_bl = ext4_iget(sb, EXT4_BOOT_LOADER_INO, EXT4_IGET_SPECIAL);
+       if (IS_ERR(inode_bl))
+               return PTR_ERR(inode_bl);
+       ei_bl = EXT4_I(inode_bl);
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -1597,7 +1597,7 @@ static struct dentry *ext4_lookup(struct
+                                        dentry);
+                       return ERR_PTR(-EFSCORRUPTED);
+               }
+-              inode = ext4_iget_normal(dir->i_sb, ino);
++              inode = ext4_iget(dir->i_sb, ino, EXT4_IGET_NORMAL);
+               if (inode == ERR_PTR(-ESTALE)) {
+                       EXT4_ERROR_INODE(dir,
+                                        "deleted inode referenced: %u",
+@@ -1639,7 +1639,7 @@ struct dentry *ext4_get_parent(struct de
+               return ERR_PTR(-EFSCORRUPTED);
+       }
+-      return d_obtain_alias(ext4_iget_normal(child->d_sb, ino));
++      return d_obtain_alias(ext4_iget(child->d_sb, ino, EXT4_IGET_NORMAL));
+ }
+ /*
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1652,7 +1652,7 @@ int ext4_group_add(struct super_block *s
+                                    "No reserved GDT blocks, can't resize");
+                       return -EPERM;
+               }
+-              inode = ext4_iget(sb, EXT4_RESIZE_INO);
++              inode = ext4_iget(sb, EXT4_RESIZE_INO, EXT4_IGET_SPECIAL);
+               if (IS_ERR(inode)) {
+                       ext4_warning(sb, "Error opening resize inode");
+                       return PTR_ERR(inode);
+@@ -1980,7 +1980,8 @@ retry:
+               }
+               if (!resize_inode)
+-                      resize_inode = ext4_iget(sb, EXT4_RESIZE_INO);
++                      resize_inode = ext4_iget(sb, EXT4_RESIZE_INO,
++                                               EXT4_IGET_SPECIAL);
+               if (IS_ERR(resize_inode)) {
+                       ext4_warning(sb, "Error opening resize inode");
+                       return PTR_ERR(resize_inode);
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1126,20 +1126,11 @@ static struct inode *ext4_nfs_get_inode(
+ {
+       struct inode *inode;
+-      if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
+-              return ERR_PTR(-ESTALE);
+-      if (ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count))
+-              return ERR_PTR(-ESTALE);
+-
+-      /* iget isn't really right if the inode is currently unallocated!!
+-       *
+-       * ext4_read_inode will return a bad_inode if the inode had been
+-       * deleted, so we should be safe.
+-       *
++      /*
+        * Currently we don't know the generation for parent directory, so
+        * a generation of 0 means "accept any"
+        */
+-      inode = ext4_iget_normal(sb, ino);
++      inode = ext4_iget(sb, ino, EXT4_IGET_HANDLE);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
+       if (generation && inode->i_generation != generation) {
+@@ -4370,7 +4361,7 @@ no_journal:
+        * so we can safely mount the rest of the filesystem now.
+        */
+-      root = ext4_iget(sb, EXT4_ROOT_INO);
++      root = ext4_iget(sb, EXT4_ROOT_INO, EXT4_IGET_SPECIAL);
+       if (IS_ERR(root)) {
+               ext4_msg(sb, KERN_ERR, "get root inode failed");
+               ret = PTR_ERR(root);
+@@ -4620,7 +4611,7 @@ static struct inode *ext4_get_journal_in
+        * happen if we iget() an unused inode, as the subsequent iput()
+        * will try to delete it.
+        */
+-      journal_inode = ext4_iget(sb, journal_inum);
++      journal_inode = ext4_iget(sb, journal_inum, EXT4_IGET_SPECIAL);
+       if (IS_ERR(journal_inode)) {
+               ext4_msg(sb, KERN_ERR, "no journal found");
+               return NULL;
+@@ -5693,7 +5684,7 @@ static int ext4_quota_enable(struct supe
+       if (!qf_inums[type])
+               return -EPERM;
+-      qf_inode = ext4_iget(sb, qf_inums[type]);
++      qf_inode = ext4_iget(sb, qf_inums[type], EXT4_IGET_SPECIAL);
+       if (IS_ERR(qf_inode)) {
+               ext4_error(sb, "Bad quota inode # %lu", qf_inums[type]);
+               return PTR_ERR(qf_inode);
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -383,7 +383,7 @@ static int ext4_xattr_inode_iget(struct
+       struct inode *inode;
+       int err;
+-      inode = ext4_iget(parent->i_sb, ea_ino);
++      inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_NORMAL);
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
+               ext4_error(parent->i_sb,
+@@ -1486,7 +1486,8 @@ ext4_xattr_inode_cache_find(struct inode
+       }
+       while (ce) {
+-              ea_inode = ext4_iget(inode->i_sb, ce->e_value);
++              ea_inode = ext4_iget(inode->i_sb, ce->e_value,
++                                   EXT4_IGET_NORMAL);
+               if (!IS_ERR(ea_inode) &&
+                   !is_bad_inode(ea_inode) &&
+                   (EXT4_I(ea_inode)->i_flags & EXT4_EA_INODE_FL) &&
diff --git a/queue-4.14/ext4-don-t-perform-block-validity-checks-on-the-journal-inode.patch b/queue-4.14/ext4-don-t-perform-block-validity-checks-on-the-journal-inode.patch
new file mode 100644 (file)
index 0000000..1518ba2
--- /dev/null
@@ -0,0 +1,56 @@
+From 0a944e8a6c66ca04c7afbaa17e22bf208a8b37f0 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 22 May 2019 10:27:01 -0400
+Subject: ext4: don't perform block validity checks on the journal inode
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 0a944e8a6c66ca04c7afbaa17e22bf208a8b37f0 upstream.
+
+Since the journal inode is already checked when we added it to the
+block validity's system zone, if we check it again, we'll just trigger
+a failure.
+
+This was causing failures like this:
+
+[   53.897001] EXT4-fs error (device sda): ext4_find_extent:909: inode
+#8: comm jbd2/sda-8: pblk 121667583 bad header/extent: invalid extent entries - magic f30a, entries 8, max 340(340), depth 0(0)
+[   53.931430] jbd2_journal_bmap: journal block not found at offset 49 on sda-8
+[   53.938480] Aborting journal on device sda-8.
+
+... but only if the system was under enough memory pressure that
+logical->physical mapping for the journal inode gets pushed out of the
+extent cache.  (This is why it wasn't noticed earlier.)
+
+Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
+Reported-by: Dan Rue <dan.rue@linaro.org>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Tested-by: Naresh Kamboju <naresh.kamboju@linaro.org>
+Signed-off-by: Ashwin H <ashwinh@vmware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/extents.c |   12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -554,10 +554,14 @@ __read_extent_tree_block(const char *fun
+       }
+       if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE))
+               return bh;
+-      err = __ext4_ext_check(function, line, inode,
+-                             ext_block_hdr(bh), depth, pblk);
+-      if (err)
+-              goto errout;
++      if (!ext4_has_feature_journal(inode->i_sb) ||
++          (inode->i_ino !=
++           le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) {
++              err = __ext4_ext_check(function, line, inode,
++                                     ext_block_hdr(bh), depth, pblk);
++              if (err)
++                      goto errout;
++      }
+       set_buffer_verified(bh);
+       /*
+        * If this is a leaf block, cache all of its entries
diff --git a/queue-4.14/ext4-fix-block-validity-checks-for-journal-inodes-using-indirect-blocks.patch b/queue-4.14/ext4-fix-block-validity-checks-for-journal-inodes-using-indirect-blocks.patch
new file mode 100644 (file)
index 0000000..c8d1650
--- /dev/null
@@ -0,0 +1,43 @@
+From 170417c8c7bb2cbbdd949bf5c443c0c8f24a203b Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 15 May 2019 00:51:19 -0400
+Subject: ext4: fix block validity checks for journal inodes using indirect blocks
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 170417c8c7bb2cbbdd949bf5c443c0c8f24a203b upstream.
+
+Commit 345c0dbf3a30 ("ext4: protect journal inode's blocks using
+block_validity") failed to add an exception for the journal inode in
+ext4_check_blockref(), which is the function used by ext4_get_branch()
+for indirect blocks.  This caused attempts to read from the ext3-style
+journals to fail with:
+
+[  848.968550] EXT4-fs error (device sdb7): ext4_get_branch:171: inode #8: block 30343695: comm jbd2/sdb7-8: invalid block
+
+Fix this by adding the missing exception check.
+
+Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
+Reported-by: Arthur Marsh <arthur.marsh@internode.on.net>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Ashwin H <ashwinh@vmware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/block_validity.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -275,6 +275,11 @@ int ext4_check_blockref(const char *func
+       __le32 *bref = p;
+       unsigned int blk;
++      if (ext4_has_feature_journal(inode->i_sb) &&
++          (inode->i_ino ==
++           le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
++              return 0;
++
+       while (bref < p+max) {
+               blk = le32_to_cpu(*bref++);
+               if (blk &&
diff --git a/queue-4.14/ext4-protect-journal-inode-s-blocks-using-block_validity.patch b/queue-4.14/ext4-protect-journal-inode-s-blocks-using-block_validity.patch
new file mode 100644 (file)
index 0000000..5f3c48c
--- /dev/null
@@ -0,0 +1,102 @@
+From 345c0dbf3a30872d9b204db96b5857cd00808cae Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Tue, 9 Apr 2019 23:37:08 -0400
+Subject: ext4: protect journal inode's blocks using block_validity
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 345c0dbf3a30872d9b204db96b5857cd00808cae upstream.
+
+Add the blocks which belong to the journal inode to block_validity's
+system zone so attempts to deallocate or overwrite the journal due a
+corrupted file system where the journal blocks are also claimed by
+another inode.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=202879
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Ashwin H <ashwinh@vmware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/block_validity.c |   48 +++++++++++++++++++++++++++++++++++++++++++++++
+ fs/ext4/inode.c          |    4 +++
+ 2 files changed, 52 insertions(+)
+
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -137,6 +137,48 @@ static void debug_print_tree(struct ext4
+       printk(KERN_CONT "\n");
+ }
++static int ext4_protect_reserved_inode(struct super_block *sb, u32 ino)
++{
++      struct inode *inode;
++      struct ext4_sb_info *sbi = EXT4_SB(sb);
++      struct ext4_map_blocks map;
++      u32 i = 0, err = 0, num, n;
++
++      if ((ino < EXT4_ROOT_INO) ||
++          (ino > le32_to_cpu(sbi->s_es->s_inodes_count)))
++              return -EINVAL;
++      inode = ext4_iget(sb, ino, EXT4_IGET_SPECIAL);
++      if (IS_ERR(inode))
++              return PTR_ERR(inode);
++      num = (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
++      while (i < num) {
++              map.m_lblk = i;
++              map.m_len = num - i;
++              n = ext4_map_blocks(NULL, inode, &map, 0);
++              if (n < 0) {
++                      err = n;
++                      break;
++              }
++              if (n == 0) {
++                      i++;
++              } else {
++                      if (!ext4_data_block_valid(sbi, map.m_pblk, n)) {
++                              ext4_error(sb, "blocks %llu-%llu from inode %u "
++                                         "overlap system zone", map.m_pblk,
++                                         map.m_pblk + map.m_len - 1, ino);
++                              err = -EFSCORRUPTED;
++                              break;
++                      }
++                      err = add_system_zone(sbi, map.m_pblk, n);
++                      if (err < 0)
++                              break;
++                      i += n;
++              }
++      }
++      iput(inode);
++      return err;
++}
++
+ int ext4_setup_system_zone(struct super_block *sb)
+ {
+       ext4_group_t ngroups = ext4_get_groups_count(sb);
+@@ -171,6 +213,12 @@ int ext4_setup_system_zone(struct super_
+               if (ret)
+                       return ret;
+       }
++      if (ext4_has_feature_journal(sb) && sbi->s_es->s_journal_inum) {
++              ret = ext4_protect_reserved_inode(sb,
++                              le32_to_cpu(sbi->s_es->s_journal_inum));
++              if (ret)
++                      return ret;
++      }
+       if (test_opt(sb, DEBUG))
+               debug_print_tree(EXT4_SB(sb));
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -407,6 +407,10 @@ static int __check_block_validity(struct
+                               unsigned int line,
+                               struct ext4_map_blocks *map)
+ {
++      if (ext4_has_feature_journal(inode->i_sb) &&
++          (inode->i_ino ==
++           le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum)))
++              return 0;
+       if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk,
+                                  map->m_len)) {
+               ext4_error_inode(inode, func, line, map->m_pblk,
diff --git a/queue-4.14/ext4-unsigned-int-compared-against-zero.patch b/queue-4.14/ext4-unsigned-int-compared-against-zero.patch
new file mode 100644 (file)
index 0000000..2700572
--- /dev/null
@@ -0,0 +1,36 @@
+From fbbbbd2f28aec991f3fbc248df211550fbdfd58c Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.king@canonical.com>
+Date: Fri, 10 May 2019 22:06:38 -0400
+Subject: ext4: unsigned int compared against zero
+
+From: Colin Ian King <colin.king@canonical.com>
+
+commit fbbbbd2f28aec991f3fbc248df211550fbdfd58c upstream.
+
+There are two cases where u32 variables n and err are being checked
+for less than zero error values, the checks is always false because
+the variables are not signed. Fix this by making the variables ints.
+
+Addresses-Coverity: ("Unsigned compared against 0")
+Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity")
+Signed-off-by: Colin Ian King <colin.king@canonical.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Ashwin H <ashwinh@vmware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/block_validity.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/block_validity.c
++++ b/fs/ext4/block_validity.c
+@@ -142,7 +142,8 @@ static int ext4_protect_reserved_inode(s
+       struct inode *inode;
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct ext4_map_blocks map;
+-      u32 i = 0, err = 0, num, n;
++      u32 i = 0, num;
++      int err = 0, n;
+       if ((ino < EXT4_ROOT_INO) ||
+           (ino > le32_to_cpu(sbi->s_es->s_inodes_count)))
index 832e22886e05eacf593be2ee106b4efad853ac36..28d7cddbb5cfe401f6515a3fd424bd7619e61acd 100644 (file)
@@ -108,3 +108,8 @@ ext4-increase-wait-time-needed-before-reuse-of-delet.patch
 ext4-convert-bug_on-s-to-warn_on-s-in-mballoc.c.patch
 of-unittest-kmemleak-on-changeset-destroy.patch
 hwmon-jc42-fix-name-to-have-no-illegal-characters.patch
+ext4-avoid-declaring-fs-inconsistent-due-to-invalid-file-handles.patch
+ext4-protect-journal-inode-s-blocks-using-block_validity.patch
+ext4-don-t-perform-block-validity-checks-on-the-journal-inode.patch
+ext4-fix-block-validity-checks-for-journal-inodes-using-indirect-blocks.patch
+ext4-unsigned-int-compared-against-zero.patch