]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 5 Jun 2016 20:55:47 +0000 (13:55 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 5 Jun 2016 20:55:47 +0000 (13:55 -0700)
added patches:
dma-debug-avoid-spinlock-recursion-when-disabling-dma-debug.patch
ext4-address-ubsan-warning-in-mb_find_order_for_block.patch
ext4-fix-hang-when-processing-corrupted-orphaned-inode-list.patch
ext4-silence-ubsan-in-ext4_mb_init.patch
xfs-fix-inode-validity-check-in-xfs_iflush_cluster.patch
xfs-skip-stale-inodes-in-xfs_iflush_cluster.patch
xfs-xfs_iflush_cluster-fails-to-abort-on-error.patch

queue-3.14/dma-debug-avoid-spinlock-recursion-when-disabling-dma-debug.patch [new file with mode: 0644]
queue-3.14/ext4-address-ubsan-warning-in-mb_find_order_for_block.patch [new file with mode: 0644]
queue-3.14/ext4-fix-hang-when-processing-corrupted-orphaned-inode-list.patch [new file with mode: 0644]
queue-3.14/ext4-silence-ubsan-in-ext4_mb_init.patch [new file with mode: 0644]
queue-3.14/series
queue-3.14/xfs-fix-inode-validity-check-in-xfs_iflush_cluster.patch [new file with mode: 0644]
queue-3.14/xfs-skip-stale-inodes-in-xfs_iflush_cluster.patch [new file with mode: 0644]
queue-3.14/xfs-xfs_iflush_cluster-fails-to-abort-on-error.patch [new file with mode: 0644]

diff --git a/queue-3.14/dma-debug-avoid-spinlock-recursion-when-disabling-dma-debug.patch b/queue-3.14/dma-debug-avoid-spinlock-recursion-when-disabling-dma-debug.patch
new file mode 100644 (file)
index 0000000..650c092
--- /dev/null
@@ -0,0 +1,40 @@
+From 3017cd63f26fc655d56875aaf497153ba60e9edf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
+Date: Thu, 26 May 2016 15:16:25 -0700
+Subject: dma-debug: avoid spinlock recursion when disabling dma-debug
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ville Syrjälä <ville.syrjala@linux.intel.com>
+
+commit 3017cd63f26fc655d56875aaf497153ba60e9edf upstream.
+
+With netconsole (at least) the pr_err("...  disablingn") call can
+recurse back into the dma-debug code, where it'll try to grab
+free_entries_lock again.  Avoid the problem by doing the printk after
+dropping the lock.
+
+Link: http://lkml.kernel.org/r/1463678421-18683-1-git-send-email-ville.syrjala@linux.intel.com
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ lib/dma-debug.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/lib/dma-debug.c
++++ b/lib/dma-debug.c
+@@ -646,9 +646,9 @@ static struct dma_debug_entry *dma_entry
+       spin_lock_irqsave(&free_entries_lock, flags);
+       if (list_empty(&free_entries)) {
+-              pr_err("DMA-API: debugging out of memory - disabling\n");
+               global_disable = true;
+               spin_unlock_irqrestore(&free_entries_lock, flags);
++              pr_err("DMA-API: debugging out of memory - disabling\n");
+               return NULL;
+       }
diff --git a/queue-3.14/ext4-address-ubsan-warning-in-mb_find_order_for_block.patch b/queue-3.14/ext4-address-ubsan-warning-in-mb_find_order_for_block.patch
new file mode 100644 (file)
index 0000000..40e3803
--- /dev/null
@@ -0,0 +1,74 @@
+From b5cb316cdf3a3f5f6125412b0f6065185240cfdc Mon Sep 17 00:00:00 2001
+From: Nicolai Stange <nicstange@gmail.com>
+Date: Thu, 5 May 2016 17:38:03 -0400
+Subject: ext4: address UBSAN warning in mb_find_order_for_block()
+
+From: Nicolai Stange <nicstange@gmail.com>
+
+commit b5cb316cdf3a3f5f6125412b0f6065185240cfdc upstream.
+
+Currently, in mb_find_order_for_block(), there's a loop like the following:
+
+  while (order <= e4b->bd_blkbits + 1) {
+    ...
+    bb += 1 << (e4b->bd_blkbits - order);
+  }
+
+Note that the updated bb is used in the loop's next iteration only.
+
+However, at the last iteration, that is at order == e4b->bd_blkbits + 1,
+the shift count becomes negative (c.f. C99 6.5.7(3)) and UBSAN reports
+
+  UBSAN: Undefined behaviour in fs/ext4/mballoc.c:1281:11
+  shift exponent -1 is negative
+  [...]
+  Call Trace:
+   [<ffffffff818c4d35>] dump_stack+0xbc/0x117
+   [<ffffffff818c4c79>] ? _atomic_dec_and_lock+0x169/0x169
+   [<ffffffff819411bb>] ubsan_epilogue+0xd/0x4e
+   [<ffffffff81941cbc>] __ubsan_handle_shift_out_of_bounds+0x1fb/0x254
+   [<ffffffff81941ac1>] ? __ubsan_handle_load_invalid_value+0x158/0x158
+   [<ffffffff816e93a0>] ? ext4_mb_generate_from_pa+0x590/0x590
+   [<ffffffff816502c8>] ? ext4_read_block_bitmap_nowait+0x598/0xe80
+   [<ffffffff816e7b7e>] mb_find_order_for_block+0x1ce/0x240
+   [...]
+
+Unless compilers start to do some fancy transformations (which at least
+GCC 6.0.0 doesn't currently do), the issue is of cosmetic nature only: the
+such calculated value of bb is never used again.
+
+Silence UBSAN by introducing another variable, bb_incr, holding the next
+increment to apply to bb and adjust that one by right shifting it by one
+position per loop iteration.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=114701
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=112161
+
+Signed-off-by: Nicolai Stange <nicstange@gmail.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/mballoc.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1236,6 +1236,7 @@ static void ext4_mb_unload_buddy(struct
+ static int mb_find_order_for_block(struct ext4_buddy *e4b, int block)
+ {
+       int order = 1;
++      int bb_incr = 1 << (e4b->bd_blkbits - 1);
+       void *bb;
+       BUG_ON(e4b->bd_bitmap == e4b->bd_buddy);
+@@ -1248,7 +1249,8 @@ static int mb_find_order_for_block(struc
+                       /* this block is part of buddy of order 'order' */
+                       return order;
+               }
+-              bb += 1 << (e4b->bd_blkbits - order);
++              bb += bb_incr;
++              bb_incr >>= 1;
+               order++;
+       }
+       return 0;
diff --git a/queue-3.14/ext4-fix-hang-when-processing-corrupted-orphaned-inode-list.patch b/queue-3.14/ext4-fix-hang-when-processing-corrupted-orphaned-inode-list.patch
new file mode 100644 (file)
index 0000000..336ea22
--- /dev/null
@@ -0,0 +1,58 @@
+From c9eb13a9105e2e418f72e46a2b6da3f49e696902 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sat, 30 Apr 2016 00:48:54 -0400
+Subject: ext4: fix hang when processing corrupted orphaned inode list
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit c9eb13a9105e2e418f72e46a2b6da3f49e696902 upstream.
+
+If the orphaned inode list contains inode #5, ext4_iget() returns a
+bad inode (since the bootloader inode should never be referenced
+directly).  Because of the bad inode, we end up processing the inode
+repeatedly and this hangs the machine.
+
+This can be reproduced via:
+
+   mke2fs -t ext4 /tmp/foo.img 100
+   debugfs -w -R "ssv last_orphan 5" /tmp/foo.img
+   mount -o loop /tmp/foo.img /mnt
+
+(But don't do this if you are using an unpatched kernel if you care
+about the system staying functional.  :-)
+
+This bug was found by the port of American Fuzzy Lop into the kernel
+to find file system problems[1].  (Since it *only* happens if inode #5
+shows up on the orphan list --- 3, 7, 8, etc. won't do it, it's not
+surprising that AFL needed two hours before it found it.)
+
+[1] http://events.linuxfoundation.org/sites/events/files/slides/AFL%20filesystem%20fuzzing%2C%20Vault%202016_0.pdf
+
+Reported by: Vegard Nossum <vegard.nossum@oracle.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ialloc.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/ialloc.c
++++ b/fs/ext4/ialloc.c
+@@ -1097,11 +1097,13 @@ struct inode *ext4_orphan_get(struct sup
+               goto iget_failed;
+       /*
+-       * If the orphans has i_nlinks > 0 then it should be able to be
+-       * truncated, otherwise it won't be removed from the orphan list
+-       * during processing and an infinite loop will result.
++       * If the orphans has i_nlinks > 0 then it should be able to
++       * be truncated, otherwise it won't be removed from the orphan
++       * list during processing and an infinite loop will result.
++       * Similarly, it must not be a bad inode.
+        */
+-      if (inode->i_nlink && !ext4_can_truncate(inode))
++      if ((inode->i_nlink && !ext4_can_truncate(inode)) ||
++          is_bad_inode(inode))
+               goto bad_orphan;
+       if (NEXT_ORPHAN(inode) > max_ino)
diff --git a/queue-3.14/ext4-silence-ubsan-in-ext4_mb_init.patch b/queue-3.14/ext4-silence-ubsan-in-ext4_mb_init.patch
new file mode 100644 (file)
index 0000000..bcb336a
--- /dev/null
@@ -0,0 +1,90 @@
+From 935244cd54b86ca46e69bc6604d2adfb1aec2d42 Mon Sep 17 00:00:00 2001
+From: Nicolai Stange <nicstange@gmail.com>
+Date: Thu, 5 May 2016 19:46:19 -0400
+Subject: ext4: silence UBSAN in ext4_mb_init()
+
+From: Nicolai Stange <nicstange@gmail.com>
+
+commit 935244cd54b86ca46e69bc6604d2adfb1aec2d42 upstream.
+
+Currently, in ext4_mb_init(), there's a loop like the following:
+
+  do {
+    ...
+    offset += 1 << (sb->s_blocksize_bits - i);
+    i++;
+  } while (i <= sb->s_blocksize_bits + 1);
+
+Note that the updated offset is used in the loop's next iteration only.
+
+However, at the last iteration, that is at i == sb->s_blocksize_bits + 1,
+the shift count becomes equal to (unsigned)-1 > 31 (c.f. C99 6.5.7(3))
+and UBSAN reports
+
+  UBSAN: Undefined behaviour in fs/ext4/mballoc.c:2621:15
+  shift exponent 4294967295 is too large for 32-bit type 'int'
+  [...]
+  Call Trace:
+   [<ffffffff818c4d25>] dump_stack+0xbc/0x117
+   [<ffffffff818c4c69>] ? _atomic_dec_and_lock+0x169/0x169
+   [<ffffffff819411ab>] ubsan_epilogue+0xd/0x4e
+   [<ffffffff81941cac>] __ubsan_handle_shift_out_of_bounds+0x1fb/0x254
+   [<ffffffff81941ab1>] ? __ubsan_handle_load_invalid_value+0x158/0x158
+   [<ffffffff814b6dc1>] ? kmem_cache_alloc+0x101/0x390
+   [<ffffffff816fc13b>] ? ext4_mb_init+0x13b/0xfd0
+   [<ffffffff814293c7>] ? create_cache+0x57/0x1f0
+   [<ffffffff8142948a>] ? create_cache+0x11a/0x1f0
+   [<ffffffff821c2168>] ? mutex_lock+0x38/0x60
+   [<ffffffff821c23ab>] ? mutex_unlock+0x1b/0x50
+   [<ffffffff814c26ab>] ? put_online_mems+0x5b/0xc0
+   [<ffffffff81429677>] ? kmem_cache_create+0x117/0x2c0
+   [<ffffffff816fcc49>] ext4_mb_init+0xc49/0xfd0
+   [...]
+
+Observe that the mentioned shift exponent, 4294967295, equals (unsigned)-1.
+
+Unless compilers start to do some fancy transformations (which at least
+GCC 6.0.0 doesn't currently do), the issue is of cosmetic nature only: the
+such calculated value of offset is never used again.
+
+Silence UBSAN by introducing another variable, offset_incr, holding the
+next increment to apply to offset and adjust that one by right shifting it
+by one position per loop iteration.
+
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=114701
+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=112161
+
+Signed-off-by: Nicolai Stange <nicstange@gmail.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/mballoc.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -2537,7 +2537,7 @@ int ext4_mb_init(struct super_block *sb)
+ {
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       unsigned i, j;
+-      unsigned offset;
++      unsigned offset, offset_incr;
+       unsigned max;
+       int ret;
+@@ -2566,11 +2566,13 @@ int ext4_mb_init(struct super_block *sb)
+       i = 1;
+       offset = 0;
++      offset_incr = 1 << (sb->s_blocksize_bits - 1);
+       max = sb->s_blocksize << 2;
+       do {
+               sbi->s_mb_offsets[i] = offset;
+               sbi->s_mb_maxs[i] = max;
+-              offset += 1 << (sb->s_blocksize_bits - i);
++              offset += offset_incr;
++              offset_incr = offset_incr >> 1;
+               max = max >> 1;
+               i++;
+       } while (i <= sb->s_blocksize_bits + 1);
index 12528224ae0ac865e4ea4231b43299d5e0b467d7..3459126f11acda42630e124d1609168eaa919034 100644 (file)
@@ -14,3 +14,10 @@ xen-events-don-t-move-disabled-irqs.patch
 sunrpc-fix-stripping-of-padded-mic-tokens.patch
 drm-gma500-fix-possible-out-of-bounds-read.patch
 drm-fb_helper-fix-references-to-dev-mode_config.num_connector.patch
+ext4-fix-hang-when-processing-corrupted-orphaned-inode-list.patch
+ext4-address-ubsan-warning-in-mb_find_order_for_block.patch
+ext4-silence-ubsan-in-ext4_mb_init.patch
+dma-debug-avoid-spinlock-recursion-when-disabling-dma-debug.patch
+xfs-xfs_iflush_cluster-fails-to-abort-on-error.patch
+xfs-fix-inode-validity-check-in-xfs_iflush_cluster.patch
+xfs-skip-stale-inodes-in-xfs_iflush_cluster.patch
diff --git a/queue-3.14/xfs-fix-inode-validity-check-in-xfs_iflush_cluster.patch b/queue-3.14/xfs-fix-inode-validity-check-in-xfs_iflush_cluster.patch
new file mode 100644 (file)
index 0000000..75096d0
--- /dev/null
@@ -0,0 +1,47 @@
+From 51b07f30a71c27405259a0248206ed4e22adbee2 Mon Sep 17 00:00:00 2001
+From: Dave Chinner <dchinner@redhat.com>
+Date: Wed, 18 May 2016 13:54:22 +1000
+Subject: xfs: fix inode validity check in xfs_iflush_cluster
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit 51b07f30a71c27405259a0248206ed4e22adbee2 upstream.
+
+Some careless idiot(*) wrote crap code in commit 1a3e8f3 ("xfs:
+convert inode cache lookups to use RCU locking") back in late 2010,
+and so xfs_iflush_cluster checks the wrong inode for whether it is
+still valid under RCU protection. Fix it to lock and check the
+correct inode.
+
+(*) Careless-idiot: Dave Chinner <dchinner@redhat.com>
+
+Discovered-by: Brain Foster <bfoster@redhat.com>
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_inode.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -2923,13 +2923,13 @@ xfs_iflush_cluster(
+                * We need to check under the i_flags_lock for a valid inode
+                * here. Skip it if it is not valid or the wrong inode.
+                */
+-              spin_lock(&ip->i_flags_lock);
+-              if (!ip->i_ino ||
++              spin_lock(&iq->i_flags_lock);
++              if (!iq->i_ino ||
+                   (XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) != first_index) {
+-                      spin_unlock(&ip->i_flags_lock);
++                      spin_unlock(&iq->i_flags_lock);
+                       continue;
+               }
+-              spin_unlock(&ip->i_flags_lock);
++              spin_unlock(&iq->i_flags_lock);
+               /*
+                * Do an un-protected check to see if the inode is dirty and
diff --git a/queue-3.14/xfs-skip-stale-inodes-in-xfs_iflush_cluster.patch b/queue-3.14/xfs-skip-stale-inodes-in-xfs_iflush_cluster.patch
new file mode 100644 (file)
index 0000000..a6886cb
--- /dev/null
@@ -0,0 +1,32 @@
+From 7d3aa7fe970791f1a674b14572a411accf2f4d4e Mon Sep 17 00:00:00 2001
+From: Dave Chinner <dchinner@redhat.com>
+Date: Wed, 18 May 2016 13:54:23 +1000
+Subject: xfs: skip stale inodes in xfs_iflush_cluster
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit 7d3aa7fe970791f1a674b14572a411accf2f4d4e upstream.
+
+We don't write back stale inodes so we should skip them in
+xfs_iflush_cluster, too.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Brian Foster <bfoster@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_inode.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -2925,6 +2925,7 @@ xfs_iflush_cluster(
+                */
+               spin_lock(&iq->i_flags_lock);
+               if (!iq->i_ino ||
++                  __xfs_iflags_test(iq, XFS_ISTALE) ||
+                   (XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) != first_index) {
+                       spin_unlock(&iq->i_flags_lock);
+                       continue;
diff --git a/queue-3.14/xfs-xfs_iflush_cluster-fails-to-abort-on-error.patch b/queue-3.14/xfs-xfs_iflush_cluster-fails-to-abort-on-error.patch
new file mode 100644 (file)
index 0000000..6a18e07
--- /dev/null
@@ -0,0 +1,76 @@
+From b1438f477934f5a4d5a44df26f3079a7575d5946 Mon Sep 17 00:00:00 2001
+From: Dave Chinner <dchinner@redhat.com>
+Date: Wed, 18 May 2016 13:53:42 +1000
+Subject: xfs: xfs_iflush_cluster fails to abort on error
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit b1438f477934f5a4d5a44df26f3079a7575d5946 upstream.
+
+When a failure due to an inode buffer occurs, the error handling
+fails to abort the inode writeback correctly. This can result in the
+inode being reclaimed whilst still in the AIL, leading to
+use-after-free situations as well as filesystems that cannot be
+unmounted as the inode log items left in the AIL never get removed.
+
+Fix this by ensuring fatal errors from xfs_imap_to_bp() result in
+the inode flush being aborted correctly.
+
+Reported-by: Shyam Kaushik <shyam@zadarastorage.com>
+Diagnosed-by: Shyam Kaushik <shyam@zadarastorage.com>
+Tested-by: Shyam Kaushik <shyam@zadarastorage.com>
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Dave Chinner <david@fromorbit.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_inode.c |   17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/fs/xfs/xfs_inode.c
++++ b/fs/xfs/xfs_inode.c
+@@ -3045,7 +3045,7 @@ xfs_iflush(
+       struct xfs_buf          **bpp)
+ {
+       struct xfs_mount        *mp = ip->i_mount;
+-      struct xfs_buf          *bp;
++      struct xfs_buf          *bp = NULL;
+       struct xfs_dinode       *dip;
+       int                     error;
+@@ -3087,14 +3087,22 @@ xfs_iflush(
+       }
+       /*
+-       * Get the buffer containing the on-disk inode.
++       * Get the buffer containing the on-disk inode. We are doing a try-lock
++       * operation here, so we may get  an EAGAIN error. In that case, we
++       * simply want to return with the inode still dirty.
++       *
++       * If we get any other error, we effectively have a corruption situation
++       * and we cannot flush the inode, so we treat it the same as failing
++       * xfs_iflush_int().
+        */
+       error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
+                              0);
+-      if (error || !bp) {
++      if (error == -EAGAIN) {
+               xfs_ifunlock(ip);
+               return error;
+       }
++      if (error)
++              goto corrupt_out;
+       /*
+        * First flush out the inode that xfs_iflush was called with.
+@@ -3122,7 +3130,8 @@ xfs_iflush(
+       return 0;
+ corrupt_out:
+-      xfs_buf_relse(bp);
++      if (bp)
++              xfs_buf_relse(bp);
+       xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+ cluster_corrupt_out:
+       error = XFS_ERROR(EFSCORRUPTED);