]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Jul 2018 12:49:38 +0000 (14:49 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Jul 2018 12:49:38 +0000 (14:49 +0200)
added patches:
cifs-fix-infinite-loop-when-using-hard-mount-option.patch
ext4-add-more-mount-time-checks-of-the-superblock.patch
ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch
ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch

queue-3.18/cifs-fix-infinite-loop-when-using-hard-mount-option.patch [new file with mode: 0644]
queue-3.18/ext4-add-more-mount-time-checks-of-the-superblock.patch [new file with mode: 0644]
queue-3.18/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch [new file with mode: 0644]
queue-3.18/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch [new file with mode: 0644]
queue-3.18/series

diff --git a/queue-3.18/cifs-fix-infinite-loop-when-using-hard-mount-option.patch b/queue-3.18/cifs-fix-infinite-loop-when-using-hard-mount-option.patch
new file mode 100644 (file)
index 0000000..db559e0
--- /dev/null
@@ -0,0 +1,129 @@
+From 7ffbe65578b44fafdef577a360eb0583929f7c6e Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <paulo@paulo.ac>
+Date: Thu, 5 Jul 2018 13:46:34 -0300
+Subject: cifs: Fix infinite loop when using hard mount option
+
+From: Paulo Alcantara <paulo@paulo.ac>
+
+commit 7ffbe65578b44fafdef577a360eb0583929f7c6e upstream.
+
+For every request we send, whether it is SMB1 or SMB2+, we attempt to
+reconnect tcon (cifs_reconnect_tcon or smb2_reconnect) before carrying
+out the request.
+
+So, while server->tcpStatus != CifsNeedReconnect, we wait for the
+reconnection to succeed on wait_event_interruptible_timeout(). If it
+returns, that means that either the condition was evaluated to true, or
+timeout elapsed, or it was interrupted by a signal.
+
+Since we're not handling the case where the process woke up due to a
+received signal (-ERESTARTSYS), the next call to
+wait_event_interruptible_timeout() will _always_ fail and we end up
+looping forever inside either cifs_reconnect_tcon() or smb2_reconnect().
+
+Here's an example of how to trigger that:
+
+$ mount.cifs //foo/share /mnt/test -o
+username=foo,password=foo,vers=1.0,hard
+
+(break connection to server before executing bellow cmd)
+$ stat -f /mnt/test & sleep 140
+[1] 2511
+
+$ ps -aux -q 2511
+USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
+root      2511  0.0  0.0  12892  1008 pts/0    S    12:24   0:00 stat -f
+/mnt/test
+
+$ kill -9 2511
+
+(wait for a while; process is stuck in the kernel)
+$ ps -aux -q 2511
+USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
+root      2511 83.2  0.0  12892  1008 pts/0    R    12:24  30:01 stat -f
+/mnt/test
+
+By using 'hard' mount point means that cifs.ko will keep retrying
+indefinitely, however we must allow the process to be killed otherwise
+it would hang the system.
+
+Signed-off-by: Paulo Alcantara <palcantara@suse.de>
+Cc: stable@vger.kernel.org
+Reviewed-by: Aurelien Aptel <aaptel@suse.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifssmb.c |   10 ++++++++--
+ fs/cifs/smb2pdu.c |   18 ++++++++++++------
+ 2 files changed, 20 insertions(+), 8 deletions(-)
+
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -150,8 +150,14 @@ cifs_reconnect_tcon(struct cifs_tcon *tc
+        * greater than cifs socket timeout which is 7 seconds
+        */
+       while (server->tcpStatus == CifsNeedReconnect) {
+-              wait_event_interruptible_timeout(server->response_q,
+-                      (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
++              rc = wait_event_interruptible_timeout(server->response_q,
++                                                    (server->tcpStatus != CifsNeedReconnect),
++                                                    10 * HZ);
++              if (rc < 0) {
++                      cifs_dbg(FYI, "%s: aborting reconnect due to a received"
++                               " signal by the process\n", __func__);
++                      return -ERESTARTSYS;
++              }
+               /* are we still trying to reconnect? */
+               if (server->tcpStatus != CifsNeedReconnect)
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -144,7 +144,7 @@ out:
+ static int
+ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
+ {
+-      int rc = 0;
++      int rc;
+       struct nls_table *nls_codepage;
+       struct cifs_ses *ses;
+       struct TCP_Server_Info *server;
+@@ -155,10 +155,10 @@ smb2_reconnect(__le16 smb2_command, stru
+        * for those three - in the calling routine.
+        */
+       if (tcon == NULL)
+-              return rc;
++              return 0;
+       if (smb2_command == SMB2_TREE_CONNECT)
+-              return rc;
++              return 0;
+       if (tcon->tidStatus == CifsExiting) {
+               /*
+@@ -201,8 +201,14 @@ smb2_reconnect(__le16 smb2_command, stru
+                       return -EAGAIN;
+               }
+-              wait_event_interruptible_timeout(server->response_q,
+-                      (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
++              rc = wait_event_interruptible_timeout(server->response_q,
++                                                    (server->tcpStatus != CifsNeedReconnect),
++                                                    10 * HZ);
++              if (rc < 0) {
++                      cifs_dbg(FYI, "%s: aborting reconnect due to a received"
++                               " signal by the process\n", __func__);
++                      return -ERESTARTSYS;
++              }
+               /* are we still trying to reconnect? */
+               if (server->tcpStatus != CifsNeedReconnect)
+@@ -220,7 +226,7 @@ smb2_reconnect(__le16 smb2_command, stru
+       }
+       if (!tcon->ses->need_reconnect && !tcon->need_reconnect)
+-              return rc;
++              return 0;
+       nls_codepage = load_nls_default();
diff --git a/queue-3.18/ext4-add-more-mount-time-checks-of-the-superblock.patch b/queue-3.18/ext4-add-more-mount-time-checks-of-the-superblock.patch
new file mode 100644 (file)
index 0000000..63d72df
--- /dev/null
@@ -0,0 +1,99 @@
+From bfe0a5f47ada40d7984de67e59a7d3390b9b9ecc Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sun, 17 Jun 2018 18:11:20 -0400
+Subject: ext4: add more mount time checks of the superblock
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit bfe0a5f47ada40d7984de67e59a7d3390b9b9ecc upstream.
+
+The kernel's ext4 mount-time checks were more permissive than
+e2fsprogs's libext2fs checks when opening a file system.  The
+superblock is considered too insane for debugfs or e2fsck to operate
+on it, the kernel has no business trying to mount it.
+
+This will make file system fuzzing tools work harder, but the failure
+cases that they find will be more useful and be easier to evaluate.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c |   37 ++++++++++++++++++++++++++-----------
+ 1 file changed, 26 insertions(+), 11 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3738,6 +3738,13 @@ static int ext4_fill_super(struct super_
+                        le32_to_cpu(es->s_log_block_size));
+               goto failed_mount;
+       }
++      if (le32_to_cpu(es->s_log_cluster_size) >
++          (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
++              ext4_msg(sb, KERN_ERR,
++                       "Invalid log cluster size: %u",
++                       le32_to_cpu(es->s_log_cluster_size));
++              goto failed_mount;
++      }
+       if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) {
+               ext4_msg(sb, KERN_ERR,
+@@ -3861,13 +3868,6 @@ static int ext4_fill_super(struct super_
+                                "block size (%d)", clustersize, blocksize);
+                       goto failed_mount;
+               }
+-              if (le32_to_cpu(es->s_log_cluster_size) >
+-                  (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) {
+-                      ext4_msg(sb, KERN_ERR,
+-                               "Invalid log cluster size: %u",
+-                               le32_to_cpu(es->s_log_cluster_size));
+-                      goto failed_mount;
+-              }
+               sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) -
+                       le32_to_cpu(es->s_log_block_size);
+               sbi->s_clusters_per_group =
+@@ -3888,10 +3888,10 @@ static int ext4_fill_super(struct super_
+               }
+       } else {
+               if (clustersize != blocksize) {
+-                      ext4_warning(sb, "fragment/cluster size (%d) != "
+-                                   "block size (%d)", clustersize,
+-                                   blocksize);
+-                      clustersize = blocksize;
++                      ext4_msg(sb, KERN_ERR,
++                               "fragment/cluster size (%d) != "
++                               "block size (%d)", clustersize, blocksize);
++                      goto failed_mount;
+               }
+               if (sbi->s_blocks_per_group > blocksize * 8) {
+                       ext4_msg(sb, KERN_ERR,
+@@ -3945,6 +3945,13 @@ static int ext4_fill_super(struct super_
+                        ext4_blocks_count(es));
+               goto failed_mount;
+       }
++      if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) &&
++          (sbi->s_cluster_ratio == 1)) {
++              ext4_msg(sb, KERN_WARNING, "bad geometry: first data "
++                       "block is 0 with a 1k block and cluster size");
++              goto failed_mount;
++      }
++
+       blocks_count = (ext4_blocks_count(es) -
+                       le32_to_cpu(es->s_first_data_block) +
+                       EXT4_BLOCKS_PER_GROUP(sb) - 1);
+@@ -3980,6 +3987,14 @@ static int ext4_fill_super(struct super_
+               ret = -ENOMEM;
+               goto failed_mount;
+       }
++      if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) !=
++          le32_to_cpu(es->s_inodes_count)) {
++              ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu",
++                       le32_to_cpu(es->s_inodes_count),
++                       ((u64)sbi->s_groups_count * sbi->s_inodes_per_group));
++              ret = -EINVAL;
++              goto failed_mount;
++      }
+       if (ext4_proc_root)
+               sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root);
diff --git a/queue-3.18/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch b/queue-3.18/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch
new file mode 100644 (file)
index 0000000..aec23c8
--- /dev/null
@@ -0,0 +1,48 @@
+From 6e8ab72a812396996035a37e5ca4b3b99b5d214b Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Fri, 15 Jun 2018 12:28:16 -0400
+Subject: ext4: clear i_data in ext4_inode_info when removing inline data
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 6e8ab72a812396996035a37e5ca4b3b99b5d214b upstream.
+
+When converting from an inode from storing the data in-line to a data
+block, ext4_destroy_inline_data_nolock() was only clearing the on-disk
+copy of the i_blocks[] array.  It was not clearing copy of the
+i_blocks[] in ext4_inode_info, in i_data[], which is the copy actually
+used by ext4_map_blocks().
+
+This didn't matter much if we are using extents, since the extents
+header would be invalid and thus the extents could would re-initialize
+the extents tree.  But if we are using indirect blocks, the previous
+contents of the i_blocks array will be treated as block numbers, with
+potentially catastrophic results to the file system integrity and/or
+user data.
+
+This gets worse if the file system is using a 1k block size and
+s_first_data is zero, but even without this, the file system can get
+quite badly corrupted.
+
+This addresses CVE-2018-10881.
+
+https://bugzilla.kernel.org/show_bug.cgi?id=200015
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/inline.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -432,6 +432,7 @@ static int ext4_destroy_inline_data_nolo
+       memset((void *)ext4_raw_inode(&is.iloc)->i_block,
+               0, EXT4_MIN_INLINE_DATA_SIZE);
++      memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE);
+       if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
+                                     EXT4_FEATURE_INCOMPAT_EXTENTS)) {
diff --git a/queue-3.18/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch b/queue-3.18/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch
new file mode 100644 (file)
index 0000000..b98c058
--- /dev/null
@@ -0,0 +1,79 @@
+From 77260807d1170a8cf35dbb06e07461a655f67eee Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Wed, 13 Jun 2018 23:08:26 -0400
+Subject: ext4: make sure bitmaps and the inode table don't overlap with bg descriptors
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 77260807d1170a8cf35dbb06e07461a655f67eee upstream.
+
+It's really bad when the allocation bitmaps and the inode table
+overlap with the block group descriptors, since it causes random
+corruption of the bg descriptors.  So we really want to head those off
+at the pass.
+
+https://bugzilla.kernel.org/show_bug.cgi?id=199865
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: stable@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c |   25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2064,6 +2064,7 @@ static int ext4_check_descriptors(struct
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       ext4_fsblk_t last_block;
++      ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1;
+       ext4_fsblk_t block_bitmap;
+       ext4_fsblk_t inode_bitmap;
+       ext4_fsblk_t inode_table;
+@@ -2096,6 +2097,14 @@ static int ext4_check_descriptors(struct
+                       if (!(sb->s_flags & MS_RDONLY))
+                               return 0;
+               }
++              if (block_bitmap >= sb_block + 1 &&
++                  block_bitmap <= last_bg_block) {
++                      ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++                               "Block bitmap for group %u overlaps "
++                               "block group descriptors", i);
++                      if (!(sb->s_flags & MS_RDONLY))
++                              return 0;
++              }
+               if (block_bitmap < first_block || block_bitmap > last_block) {
+                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+                              "Block bitmap for group %u not in group "
+@@ -2110,6 +2119,14 @@ static int ext4_check_descriptors(struct
+                       if (!(sb->s_flags & MS_RDONLY))
+                               return 0;
+               }
++              if (inode_bitmap >= sb_block + 1 &&
++                  inode_bitmap <= last_bg_block) {
++                      ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++                               "Inode bitmap for group %u overlaps "
++                               "block group descriptors", i);
++                      if (!(sb->s_flags & MS_RDONLY))
++                              return 0;
++              }
+               if (inode_bitmap < first_block || inode_bitmap > last_block) {
+                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+                              "Inode bitmap for group %u not in group "
+@@ -2124,6 +2141,14 @@ static int ext4_check_descriptors(struct
+                       if (!(sb->s_flags & MS_RDONLY))
+                               return 0;
+               }
++              if (inode_table >= sb_block + 1 &&
++                  inode_table <= last_bg_block) {
++                      ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++                               "Inode table for group %u overlaps "
++                               "block group descriptors", i);
++                      if (!(sb->s_flags & MS_RDONLY))
++                              return 0;
++              }
+               if (inode_table < first_block ||
+                   inode_table + sbi->s_itb_per_group - 1 > last_block) {
+                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
index d7adbe76058f64efb2be3936ef191a640e330c77..353e2618dbc90f94d857a791738a3dae2ddc1542 100644 (file)
@@ -7,3 +7,7 @@ atm-zatm-fix-memcmp-casting.patch
 net-qmi_wwan-add-netgear-aircard-779s.patch
 net-sonic-use-dma_mapping_error.patch
 scsi-sg-mitigate-read-write-abuse.patch
+cifs-fix-infinite-loop-when-using-hard-mount-option.patch
+ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch
+ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch
+ext4-add-more-mount-time-checks-of-the-superblock.patch