]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Oct 2017 18:15:34 +0000 (20:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Oct 2017 18:15:34 +0000 (20:15 +0200)
added patches:
drm-i915-bios-ignore-hdmi-on-port-a.patch
ext4-don-t-clear-sgid-when-inheriting-acls.patch
ext4-fix-data-corruption-for-mmap-writes.patch
ext4-only-call-ext4_truncate-when-size-isize.patch
ext4-validate-s_first_meta_bg-at-mount-time.patch
fs-super.c-fix-race-between-freeze_super-and-thaw_super.patch

queue-3.18/drm-i915-bios-ignore-hdmi-on-port-a.patch [new file with mode: 0644]
queue-3.18/ext4-don-t-clear-sgid-when-inheriting-acls.patch [new file with mode: 0644]
queue-3.18/ext4-fix-data-corruption-for-mmap-writes.patch [new file with mode: 0644]
queue-3.18/ext4-only-call-ext4_truncate-when-size-isize.patch [new file with mode: 0644]
queue-3.18/ext4-validate-s_first_meta_bg-at-mount-time.patch [new file with mode: 0644]
queue-3.18/fs-super.c-fix-race-between-freeze_super-and-thaw_super.patch [new file with mode: 0644]
queue-3.18/series

diff --git a/queue-3.18/drm-i915-bios-ignore-hdmi-on-port-a.patch b/queue-3.18/drm-i915-bios-ignore-hdmi-on-port-a.patch
new file mode 100644 (file)
index 0000000..4e8eff1
--- /dev/null
@@ -0,0 +1,48 @@
+From 2ba7d7e0437127314864238f8bfcb8369d81075c Mon Sep 17 00:00:00 2001
+From: Jani Nikula <jani.nikula@intel.com>
+Date: Thu, 21 Sep 2017 17:19:20 +0300
+Subject: drm/i915/bios: ignore HDMI on port A
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+commit 2ba7d7e0437127314864238f8bfcb8369d81075c upstream.
+
+The hardware state readout oopses after several warnings when trying to
+use HDMI on port A, if such a combination is configured in VBT. Filter
+the combo out already at the VBT parsing phase.
+
+v2: also ignore DVI (Ville)
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102889
+Cc: Imre Deak <imre.deak@intel.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Tested-by: Daniel Drake <dan@reactivated.net>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170921141920.18172-1-jani.nikula@intel.com
+(cherry picked from commit d27ffc1d00327c29b3aa97f941b42f0949f9e99f)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_bios.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/i915/intel_bios.c
++++ b/drivers/gpu/drm/i915/intel_bios.c
+@@ -940,6 +940,13 @@ static void parse_ddi_port(struct drm_i9
+       is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0;
+       is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR);
++      if (port == PORT_A && is_dvi) {
++              DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n",
++                            is_hdmi ? "/HDMI" : "");
++              is_dvi = false;
++              is_hdmi = false;
++      }
++
+       info->supports_dvi = is_dvi;
+       info->supports_hdmi = is_hdmi;
+       info->supports_dp = is_dp;
diff --git a/queue-3.18/ext4-don-t-clear-sgid-when-inheriting-acls.patch b/queue-3.18/ext4-don-t-clear-sgid-when-inheriting-acls.patch
new file mode 100644 (file)
index 0000000..2a5a94c
--- /dev/null
@@ -0,0 +1,77 @@
+From a3bb2d5587521eea6dab2d05326abb0afb460abd Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Sun, 30 Jul 2017 23:33:01 -0400
+Subject: ext4: Don't clear SGID when inheriting ACLs
+
+From: Jan Kara <jack@suse.cz>
+
+commit a3bb2d5587521eea6dab2d05326abb0afb460abd upstream.
+
+When new directory 'DIR1' is created in a directory 'DIR0' with SGID bit
+set, DIR1 is expected to have SGID bit set (and owning group equal to
+the owning group of 'DIR0'). However when 'DIR0' also has some default
+ACLs that 'DIR1' inherits, setting these ACLs will result in SGID bit on
+'DIR1' to get cleared if user is not member of the owning group.
+
+Fix the problem by moving posix_acl_update_mode() out of
+__ext4_set_acl() into ext4_set_acl(). That way the function will not be
+called when inheriting ACLs which is what we want as it prevents SGID
+bit clearing and the mode has been properly set by posix_acl_create()
+anyway.
+
+Fixes: 073931017b49d9458aa351605b43a7e34598caef
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/acl.c |   22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+--- a/fs/ext4/acl.c
++++ b/fs/ext4/acl.c
+@@ -200,13 +200,6 @@ __ext4_set_acl(handle_t *handle, struct
+       switch (type) {
+       case ACL_TYPE_ACCESS:
+               name_index = EXT4_XATTR_INDEX_POSIX_ACL_ACCESS;
+-              if (acl) {
+-                      error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
+-                      if (error)
+-                              return error;
+-                      inode->i_ctime = ext4_current_time(inode);
+-                      ext4_mark_inode_dirty(handle, inode);
+-              }
+               break;
+       case ACL_TYPE_DEFAULT:
+@@ -239,6 +232,8 @@ ext4_set_acl(struct inode *inode, struct
+ {
+       handle_t *handle;
+       int error, retries = 0;
++      umode_t mode = inode->i_mode;
++      int update_mode = 0;
+ retry:
+       handle = ext4_journal_start(inode, EXT4_HT_XATTR,
+@@ -246,7 +241,20 @@ retry:
+       if (IS_ERR(handle))
+               return PTR_ERR(handle);
++      if ((type == ACL_TYPE_ACCESS) && acl) {
++              error = posix_acl_update_mode(inode, &mode, &acl);
++              if (error)
++                      goto out_stop;
++              update_mode = 1;
++      }
++
+       error = __ext4_set_acl(handle, inode, type, acl);
++      if (!error && update_mode) {
++              inode->i_mode = mode;
++              inode->i_ctime = ext4_current_time(inode);
++              ext4_mark_inode_dirty(handle, inode);
++      }
++out_stop:
+       ext4_journal_stop(handle);
+       if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
+               goto retry;
diff --git a/queue-3.18/ext4-fix-data-corruption-for-mmap-writes.patch b/queue-3.18/ext4-fix-data-corruption-for-mmap-writes.patch
new file mode 100644 (file)
index 0000000..2adeb94
--- /dev/null
@@ -0,0 +1,65 @@
+From a056bdaae7a181f7dcc876cfab2f94538e508709 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 26 May 2017 17:45:45 -0400
+Subject: ext4: fix data corruption for mmap writes
+
+From: Jan Kara <jack@suse.cz>
+
+commit a056bdaae7a181f7dcc876cfab2f94538e508709 upstream.
+
+mpage_submit_page() can race with another process growing i_size and
+writing data via mmap to the written-back page. As mpage_submit_page()
+samples i_size too early, it may happen that ext4_bio_write_page()
+zeroes out too large tail of the page and thus corrupts user data.
+
+Fix the problem by sampling i_size only after the page has been
+write-protected in page tables by clear_page_dirty_for_io() call.
+
+Reported-by: Michael Zimmer <michael@swarm64.com>
+CC: stable@vger.kernel.org
+Fixes: cb20d5188366f04d96d2e07b1240cc92170ade40
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/inode.c |   24 +++++++++++++++++++-----
+ 1 file changed, 19 insertions(+), 5 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1780,15 +1780,29 @@ static int ext4_writepage(struct page *p
+ static int mpage_submit_page(struct mpage_da_data *mpd, struct page *page)
+ {
+       int len;
+-      loff_t size = i_size_read(mpd->inode);
++      loff_t size;
+       int err;
+       BUG_ON(page->index != mpd->first_page);
+-      if (page->index == size >> PAGE_CACHE_SHIFT)
+-              len = size & ~PAGE_CACHE_MASK;
+-      else
+-              len = PAGE_CACHE_SIZE;
+       clear_page_dirty_for_io(page);
++      /*
++       * We have to be very careful here!  Nothing protects writeback path
++       * against i_size changes and the page can be writeably mapped into
++       * page tables. So an application can be growing i_size and writing
++       * data through mmap while writeback runs. clear_page_dirty_for_io()
++       * write-protects our page in page tables and the page cannot get
++       * written to again until we release page lock. So only after
++       * clear_page_dirty_for_io() we are safe to sample i_size for
++       * ext4_bio_write_page() to zero-out tail of the written page. We rely
++       * on the barrier provided by TestClearPageDirty in
++       * clear_page_dirty_for_io() to make sure i_size is really sampled only
++       * after page tables are updated.
++       */
++      size = i_size_read(mpd->inode);
++      if (page->index == size >> PAGE_SHIFT)
++              len = size & ~PAGE_MASK;
++      else
++              len = PAGE_SIZE;
+       err = ext4_bio_write_page(&mpd->io_submit, page, len, mpd->wbc, false);
+       if (!err)
+               mpd->wbc->nr_to_write--;
diff --git a/queue-3.18/ext4-only-call-ext4_truncate-when-size-isize.patch b/queue-3.18/ext4-only-call-ext4_truncate-when-size-isize.patch
new file mode 100644 (file)
index 0000000..b5e2c54
--- /dev/null
@@ -0,0 +1,112 @@
+From 3da40c7b089810ac9cf2bb1e59633f619f3a7312 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Mon, 22 Jun 2015 00:31:26 -0400
+Subject: ext4: only call ext4_truncate when size <= isize
+
+From: Josef Bacik <jbacik@fb.com>
+
+commit 3da40c7b089810ac9cf2bb1e59633f619f3a7312 upstream.
+
+At LSF we decided that if we truncate up from isize we shouldn't trim
+fallocated blocks that were fallocated with KEEP_SIZE and are past the
+new i_size.  This patch fixes ext4 to do this.
+
+[ Completely reworked patch so that i_disksize would actually get set
+  when truncating up.  Also reworked the code for handling truncate so
+  that it's easier to handle. -- tytso ]
+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Lukas Czerner <lczerner@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/inode.c |   40 +++++++++++++++++++---------------------
+ 1 file changed, 19 insertions(+), 21 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4534,8 +4534,10 @@ int ext4_setattr(struct dentry *dentry,
+               ext4_journal_stop(handle);
+       }
+-      if (attr->ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
++      if (attr->ia_valid & ATTR_SIZE) {
+               handle_t *handle;
++              loff_t oldsize = inode->i_size;
++              int shrink = (attr->ia_size <= inode->i_size);
+               if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) {
+                       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+@@ -4543,24 +4545,26 @@ int ext4_setattr(struct dentry *dentry,
+                       if (attr->ia_size > sbi->s_bitmap_maxbytes)
+                               return -EFBIG;
+               }
++              if (!S_ISREG(inode->i_mode))
++                      return -EINVAL;
+               if (IS_I_VERSION(inode) && attr->ia_size != inode->i_size)
+                       inode_inc_iversion(inode);
+-              if (S_ISREG(inode->i_mode) &&
++              if (ext4_should_order_data(inode) &&
+                   (attr->ia_size < inode->i_size)) {
+-                      if (ext4_should_order_data(inode)) {
+-                              error = ext4_begin_ordered_truncate(inode,
++                      error = ext4_begin_ordered_truncate(inode,
+                                                           attr->ia_size);
+-                              if (error)
+-                                      goto err_out;
+-                      }
++                      if (error)
++                              goto err_out;
++              }
++              if (attr->ia_size != inode->i_size) {
+                       handle = ext4_journal_start(inode, EXT4_HT_INODE, 3);
+                       if (IS_ERR(handle)) {
+                               error = PTR_ERR(handle);
+                               goto err_out;
+                       }
+-                      if (ext4_handle_valid(handle)) {
++                      if (ext4_handle_valid(handle) && shrink) {
+                               error = ext4_orphan_add(handle, inode);
+                               orphan = 1;
+                       }
+@@ -4579,15 +4583,13 @@ int ext4_setattr(struct dentry *dentry,
+                       up_write(&EXT4_I(inode)->i_data_sem);
+                       ext4_journal_stop(handle);
+                       if (error) {
+-                              ext4_orphan_del(NULL, inode);
++                              if (orphan)
++                                      ext4_orphan_del(NULL, inode);
+                               goto err_out;
+                       }
+-              } else {
+-                      loff_t oldsize = inode->i_size;
+-
+-                      i_size_write(inode, attr->ia_size);
+-                      pagecache_isize_extended(inode, oldsize, inode->i_size);
+               }
++              if (!shrink)
++                      pagecache_isize_extended(inode, oldsize, inode->i_size);
+               /*
+                * Blocks are going to be removed from the inode. Wait
+@@ -4606,14 +4608,10 @@ int ext4_setattr(struct dentry *dentry,
+                * Truncate pagecache after we've waited for commit
+                * in data=journal mode to make pages freeable.
+                */
+-                      truncate_pagecache(inode, inode->i_size);
++              truncate_pagecache(inode, inode->i_size);
++              if (shrink)
++                      ext4_truncate(inode);
+       }
+-      /*
+-       * We want to call ext4_truncate() even if attr->ia_size ==
+-       * inode->i_size for cases like truncation of fallocated space
+-       */
+-      if (attr->ia_valid & ATTR_SIZE)
+-              ext4_truncate(inode);
+       if (!rc) {
+               setattr_copy(inode, attr);
diff --git a/queue-3.18/ext4-validate-s_first_meta_bg-at-mount-time.patch b/queue-3.18/ext4-validate-s_first_meta_bg-at-mount-time.patch
new file mode 100644 (file)
index 0000000..af66ee1
--- /dev/null
@@ -0,0 +1,69 @@
+From 3a4b77cd47bb837b8557595ec7425f281f2ca1fe Mon Sep 17 00:00:00 2001
+From: Eryu Guan <guaneryu@gmail.com>
+Date: Thu, 1 Dec 2016 15:08:37 -0500
+Subject: ext4: validate s_first_meta_bg at mount time
+
+From: Eryu Guan <guaneryu@gmail.com>
+
+commit 3a4b77cd47bb837b8557595ec7425f281f2ca1fe upstream.
+
+Ralf Spenneberg reported that he hit a kernel crash when mounting a
+modified ext4 image. And it turns out that kernel crashed when
+calculating fs overhead (ext4_calculate_overhead()), this is because
+the image has very large s_first_meta_bg (debug code shows it's
+842150400), and ext4 overruns the memory in count_overhead() when
+setting bitmap buffer, which is PAGE_SIZE.
+
+ext4_calculate_overhead():
+  buf = get_zeroed_page(GFP_NOFS);  <=== PAGE_SIZE buffer
+  blks = count_overhead(sb, i, buf);
+
+count_overhead():
+  for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { <=== j = 842150400
+          ext4_set_bit(EXT4_B2C(sbi, s++), buf);   <=== buffer overrun
+          count++;
+  }
+
+This can be reproduced easily for me by this script:
+
+  #!/bin/bash
+  rm -f fs.img
+  mkdir -p /mnt/ext4
+  fallocate -l 16M fs.img
+  mke2fs -t ext4 -O bigalloc,meta_bg,^resize_inode -F fs.img
+  debugfs -w -R "ssv first_meta_bg 842150400" fs.img
+  mount -o loop fs.img /mnt/ext4
+
+Fix it by validating s_first_meta_bg first at mount time, and
+refusing to mount if its value exceeds the largest possible meta_bg
+number.
+
+Reported-by: Ralf Spenneberg <ralf@os-t.de>
+Signed-off-by: Eryu Guan <guaneryu@gmail.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Andreas Dilger <adilger@dilger.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ fs/ext4/super.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3931,6 +3931,15 @@ static int ext4_fill_super(struct super_
+                       (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb)));
+       db_count = (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) /
+                  EXT4_DESC_PER_BLOCK(sb);
++      if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG)) {
++              if (le32_to_cpu(es->s_first_meta_bg) >= db_count) {
++                      ext4_msg(sb, KERN_WARNING,
++                               "first meta block group too large: %u "
++                               "(group descriptor block count %u)",
++                               le32_to_cpu(es->s_first_meta_bg), db_count);
++                      goto failed_mount;
++              }
++      }
+       sbi->s_group_desc = ext4_kvmalloc(db_count *
+                                         sizeof(struct buffer_head *),
+                                         GFP_KERNEL);
diff --git a/queue-3.18/fs-super.c-fix-race-between-freeze_super-and-thaw_super.patch b/queue-3.18/fs-super.c-fix-race-between-freeze_super-and-thaw_super.patch
new file mode 100644 (file)
index 0000000..4fbec28
--- /dev/null
@@ -0,0 +1,49 @@
+From 89f39af129382a40d7cd1f6914617282cfeee28e Mon Sep 17 00:00:00 2001
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Mon, 26 Sep 2016 18:07:48 +0200
+Subject: fs/super.c: fix race between freeze_super() and thaw_super()
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+commit 89f39af129382a40d7cd1f6914617282cfeee28e upstream.
+
+Change thaw_super() to check frozen != SB_FREEZE_COMPLETE rather than
+frozen == SB_UNFROZEN, otherwise it can race with freeze_super() which
+drops sb->s_umount after SB_FREEZE_WRITE to preserve the lock ordering.
+
+In this case thaw_super() will wrongly call s_op->unfreeze_fs() before
+it was actually frozen, and call sb_freeze_unlock() which leads to the
+unbalanced percpu_up_write(). Unfortunately lockdep can't detect this,
+so this triggers misc BUG_ON()'s in kernel/rcu/sync.c.
+
+Reported-and-tested-by: Nikolay Borisov <kernel@kyup.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/super.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -1346,8 +1346,8 @@ int freeze_super(struct super_block *sb)
+               }
+       }
+       /*
+-       * This is just for debugging purposes so that fs can warn if it
+-       * sees write activity when frozen is set to SB_FREEZE_COMPLETE.
++       * For debugging purposes so that fs can warn if it sees write activity
++       * when frozen is set to SB_FREEZE_COMPLETE, and for thaw_super().
+        */
+       sb->s_writers.frozen = SB_FREEZE_COMPLETE;
+       up_write(&sb->s_umount);
+@@ -1366,7 +1366,7 @@ int thaw_super(struct super_block *sb)
+       int error;
+       down_write(&sb->s_umount);
+-      if (sb->s_writers.frozen == SB_UNFROZEN) {
++      if (sb->s_writers.frozen != SB_FREEZE_COMPLETE) {
+               up_write(&sb->s_umount);
+               return -EINVAL;
+       }
index dadd2be32039f89f97b52b2c38f22c5e5974d6cb..c12495f08ca3c69a197e7a0a1554995ab9ee9eb0 100644 (file)
@@ -24,3 +24,9 @@ lsm-fix-smack_inode_removexattr-and-xattr_getsecurity-memleak.patch
 alsa-usx2y-suppress-kernel-warning-at-page-allocation-failures.patch
 driver-core-platform-don-t-read-past-the-end-of-driver_override-buffer.patch
 hid-i2c-hid-allocate-hid-buffers-for-real-worst-case.patch
+drm-i915-bios-ignore-hdmi-on-port-a.patch
+ext4-only-call-ext4_truncate-when-size-isize.patch
+fs-super.c-fix-race-between-freeze_super-and-thaw_super.patch
+ext4-fix-data-corruption-for-mmap-writes.patch
+ext4-don-t-clear-sgid-when-inheriting-acls.patch
+ext4-validate-s_first_meta_bg-at-mount-time.patch