]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.17-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Aug 2018 14:30:01 +0000 (16:30 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 7 Aug 2018 14:30:01 +0000 (16:30 +0200)
added patches:
xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch
xfs-validate-cached-inodes-are-free-when-allocated.patch

queue-4.17/series
queue-4.17/xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch [new file with mode: 0644]
queue-4.17/xfs-validate-cached-inodes-are-free-when-allocated.patch [new file with mode: 0644]

index 3b525c772b1098f0abce70d05f295f1715fb3c76..3dd9ee0957ad778787be1d28ba08086e67d024e8 100644 (file)
@@ -14,3 +14,5 @@ ring_buffer-tracing-inherit-the-tracing-setting-to-next-ring-buffer.patch
 i2c-imx-fix-reinit_completion-use.patch
 btrfs-fix-file-data-corruption-after-cloning-a-range-and-fsync.patch
 partially-revert-block-fail-op_is_write-requests-to-read-only-partitions.patch
+xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch
+xfs-validate-cached-inodes-are-free-when-allocated.patch
diff --git a/queue-4.17/xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch b/queue-4.17/xfs-don-t-call-xfs_da_shrink_inode-with-null-bp.patch
new file mode 100644 (file)
index 0000000..be8c53a
--- /dev/null
@@ -0,0 +1,45 @@
+From bb3d48dcf86a97dc25fe9fc2c11938e19cb4399a Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@sandeen.net>
+Date: Fri, 8 Jun 2018 09:53:49 -0700
+Subject: xfs: don't call xfs_da_shrink_inode with NULL bp
+
+From: Eric Sandeen <sandeen@sandeen.net>
+
+commit bb3d48dcf86a97dc25fe9fc2c11938e19cb4399a upstream.
+
+xfs_attr3_leaf_create may have errored out before instantiating a buffer,
+for example if the blkno is out of range.  In that case there is no work
+to do to remove it, and in fact xfs_da_shrink_inode will lead to an oops
+if we try.
+
+This also seems to fix a flaw where the original error from
+xfs_attr3_leaf_create gets overwritten in the cleanup case, and it
+removes a pointless assignment to bp which isn't used after this.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199969
+Reported-by: Xu, Wen <wen.xu@gatech.edu>
+Tested-by: Xu, Wen <wen.xu@gatech.edu>
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Cc: Eduardo Valentin <eduval@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/libxfs/xfs_attr_leaf.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/fs/xfs/libxfs/xfs_attr_leaf.c
++++ b/fs/xfs/libxfs/xfs_attr_leaf.c
+@@ -803,9 +803,8 @@ xfs_attr_shortform_to_leaf(
+       ASSERT(blkno == 0);
+       error = xfs_attr3_leaf_create(args, blkno, &bp);
+       if (error) {
+-              error = xfs_da_shrink_inode(args, 0, bp);
+-              bp = NULL;
+-              if (error)
++              /* xfs_attr3_leaf_create may not have instantiated a block */
++              if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0))
+                       goto out;
+               xfs_idata_realloc(dp, size, XFS_ATTR_FORK);     /* try to put */
+               memcpy(ifp->if_u1.if_data, tmpbuffer, size);    /* it back */
diff --git a/queue-4.17/xfs-validate-cached-inodes-are-free-when-allocated.patch b/queue-4.17/xfs-validate-cached-inodes-are-free-when-allocated.patch
new file mode 100644 (file)
index 0000000..302a97b
--- /dev/null
@@ -0,0 +1,157 @@
+From afca6c5b2595fc44383919fba740c194b0b76aff Mon Sep 17 00:00:00 2001
+From: Dave Chinner <dchinner@redhat.com>
+Date: Tue, 17 Apr 2018 17:17:34 -0700
+Subject: xfs: validate cached inodes are free when allocated
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit afca6c5b2595fc44383919fba740c194b0b76aff upstream.
+
+A recent fuzzed filesystem image cached random dcache corruption
+when the reproducer was run. This often showed up as panics in
+lookup_slow() on a null inode->i_ops pointer when doing pathwalks.
+
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
+....
+Call Trace:
+ lookup_slow+0x44/0x60
+ walk_component+0x3dd/0x9f0
+ link_path_walk+0x4a7/0x830
+ path_lookupat+0xc1/0x470
+ filename_lookup+0x129/0x270
+ user_path_at_empty+0x36/0x40
+ path_listxattr+0x98/0x110
+ SyS_listxattr+0x13/0x20
+ do_syscall_64+0xf5/0x280
+ entry_SYSCALL_64_after_hwframe+0x42/0xb7
+
+but had many different failure modes including deadlocks trying to
+lock the inode that was just allocated or KASAN reports of
+use-after-free violations.
+
+The cause of the problem was a corrupt INOBT on a v4 fs where the
+root inode was marked as free in the inobt record. Hence when we
+allocated an inode, it chose the root inode to allocate, found it in
+the cache and re-initialised it.
+
+We recently fixed a similar inode allocation issue caused by inobt
+record corruption problem in xfs_iget_cache_miss() in commit
+ee457001ed6c ("xfs: catch inode allocation state mismatch
+corruption"). This change adds similar checks to the cache-hit path
+to catch it, and turns the reproducer into a corruption shutdown
+situation.
+
+Reported-by: Wen Xu <wen.xu@gatech.edu>
+Signed-Off-By: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+[darrick: fix typos in comment]
+Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
+Cc: Eduardo Valentin <eduval@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_icache.c |   73 ++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 48 insertions(+), 25 deletions(-)
+
+--- a/fs/xfs/xfs_icache.c
++++ b/fs/xfs/xfs_icache.c
+@@ -309,6 +309,46 @@ xfs_reinit_inode(
+ }
+ /*
++ * If we are allocating a new inode, then check what was returned is
++ * actually a free, empty inode. If we are not allocating an inode,
++ * then check we didn't find a free inode.
++ *
++ * Returns:
++ *    0               if the inode free state matches the lookup context
++ *    -ENOENT         if the inode is free and we are not allocating
++ *    -EFSCORRUPTED   if there is any state mismatch at all
++ */
++static int
++xfs_iget_check_free_state(
++      struct xfs_inode        *ip,
++      int                     flags)
++{
++      if (flags & XFS_IGET_CREATE) {
++              /* should be a free inode */
++              if (VFS_I(ip)->i_mode != 0) {
++                      xfs_warn(ip->i_mount,
++"Corruption detected! Free inode 0x%llx not marked free! (mode 0x%x)",
++                              ip->i_ino, VFS_I(ip)->i_mode);
++                      return -EFSCORRUPTED;
++              }
++
++              if (ip->i_d.di_nblocks != 0) {
++                      xfs_warn(ip->i_mount,
++"Corruption detected! Free inode 0x%llx has blocks allocated!",
++                              ip->i_ino);
++                      return -EFSCORRUPTED;
++              }
++              return 0;
++      }
++
++      /* should be an allocated inode */
++      if (VFS_I(ip)->i_mode == 0)
++              return -ENOENT;
++
++      return 0;
++}
++
++/*
+  * Check the validity of the inode we just found it the cache
+  */
+ static int
+@@ -357,12 +397,12 @@ xfs_iget_cache_hit(
+       }
+       /*
+-       * If lookup is racing with unlink return an error immediately.
++       * Check the inode free state is valid. This also detects lookup
++       * racing with unlinks.
+        */
+-      if (VFS_I(ip)->i_mode == 0 && !(flags & XFS_IGET_CREATE)) {
+-              error = -ENOENT;
++      error = xfs_iget_check_free_state(ip, flags);
++      if (error)
+               goto out_error;
+-      }
+       /*
+        * If IRECLAIMABLE is set, we've torn down the VFS inode already.
+@@ -485,29 +525,12 @@ xfs_iget_cache_miss(
+       /*
+-       * If we are allocating a new inode, then check what was returned is
+-       * actually a free, empty inode. If we are not allocating an inode,
+-       * the check we didn't find a free inode.
++       * Check the inode free state is valid. This also detects lookup
++       * racing with unlinks.
+        */
+-      if (flags & XFS_IGET_CREATE) {
+-              if (VFS_I(ip)->i_mode != 0) {
+-                      xfs_warn(mp,
+-"Corruption detected! Free inode 0x%llx not marked free on disk",
+-                              ino);
+-                      error = -EFSCORRUPTED;
+-                      goto out_destroy;
+-              }
+-              if (ip->i_d.di_nblocks != 0) {
+-                      xfs_warn(mp,
+-"Corruption detected! Free inode 0x%llx has blocks allocated!",
+-                              ino);
+-                      error = -EFSCORRUPTED;
+-                      goto out_destroy;
+-              }
+-      } else if (VFS_I(ip)->i_mode == 0) {
+-              error = -ENOENT;
++      error = xfs_iget_check_free_state(ip, flags);
++      if (error)
+               goto out_destroy;
+-      }
+       /*
+        * Preload the radix tree so we can insert safely under the