]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.7-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 Sep 2016 14:12:06 +0000 (16:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 Sep 2016 14:12:06 +0000 (16:12 +0200)
added patches:
ext4-avoid-deadlock-when-expanding-inode-size.patch
ext4-avoid-modifying-checksum-fields-directly-during-checksum-verification.patch
ext4-fix-xattr-shifting-when-expanding-inodes-part-2.patch
ext4-fix-xattr-shifting-when-expanding-inodes.patch
ext4-properly-align-shifted-xattrs-when-expanding-inodes.patch
ext4-validate-that-metadata-blocks-do-not-overlap-superblock.patch
irqchip-gic-allow-self-sgis-for-smp-on-up-configurations.patch

queue-4.7/ext4-avoid-deadlock-when-expanding-inode-size.patch [new file with mode: 0644]
queue-4.7/ext4-avoid-modifying-checksum-fields-directly-during-checksum-verification.patch [new file with mode: 0644]
queue-4.7/ext4-fix-xattr-shifting-when-expanding-inodes-part-2.patch [new file with mode: 0644]
queue-4.7/ext4-fix-xattr-shifting-when-expanding-inodes.patch [new file with mode: 0644]
queue-4.7/ext4-properly-align-shifted-xattrs-when-expanding-inodes.patch [new file with mode: 0644]
queue-4.7/ext4-validate-that-metadata-blocks-do-not-overlap-superblock.patch [new file with mode: 0644]
queue-4.7/irqchip-gic-allow-self-sgis-for-smp-on-up-configurations.patch [new file with mode: 0644]
queue-4.7/series

diff --git a/queue-4.7/ext4-avoid-deadlock-when-expanding-inode-size.patch b/queue-4.7/ext4-avoid-deadlock-when-expanding-inode-size.patch
new file mode 100644 (file)
index 0000000..b7b874e
--- /dev/null
@@ -0,0 +1,90 @@
+From 2e81a4eeedcaa66e35f58b81e0755b87057ce392 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 11 Aug 2016 12:38:55 -0400
+Subject: ext4: avoid deadlock when expanding inode size
+
+From: Jan Kara <jack@suse.cz>
+
+commit 2e81a4eeedcaa66e35f58b81e0755b87057ce392 upstream.
+
+When we need to move xattrs into external xattr block, we call
+ext4_xattr_block_set() from ext4_expand_extra_isize_ea(). That may end
+up calling ext4_mark_inode_dirty() again which will recurse back into
+the inode expansion code leading to deadlocks.
+
+Protect from recursion using EXT4_STATE_NO_EXPAND inode flag and move
+its management into ext4_expand_extra_isize_ea() since its manipulation
+is safe there (due to xattr_sem) from possible races with
+ext4_xattr_set_handle() which plays with it as well.
+
+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 |    2 --
+ fs/ext4/xattr.c |   19 +++++++++++++------
+ 2 files changed, 13 insertions(+), 8 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5460,8 +5460,6 @@ int ext4_mark_inode_dirty(handle_t *hand
+                                                     sbi->s_want_extra_isize,
+                                                     iloc, handle);
+                       if (ret) {
+-                              ext4_set_inode_state(inode,
+-                                                   EXT4_STATE_NO_EXPAND);
+                               if (mnt_count !=
+                                       le16_to_cpu(sbi->s_es->s_mnt_count)) {
+                                       ext4_warning(inode->i_sb,
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1357,12 +1357,14 @@ int ext4_expand_extra_isize_ea(struct in
+       int isize_diff; /* How much do we need to grow i_extra_isize */
+       down_write(&EXT4_I(inode)->xattr_sem);
++      /*
++       * Set EXT4_STATE_NO_EXPAND to avoid recursion when marking inode dirty
++       */
++      ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
+ retry:
+       isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize;
+-      if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) {
+-              up_write(&EXT4_I(inode)->xattr_sem);
+-              return 0;
+-      }
++      if (EXT4_I(inode)->i_extra_isize >= new_extra_isize)
++              goto out;
+       header = IHDR(inode, raw_inode);
+       entry = IFIRST(header);
+@@ -1391,8 +1393,7 @@ retry:
+                               (void *)header, total_ino,
+                               inode->i_sb->s_blocksize);
+               EXT4_I(inode)->i_extra_isize = new_extra_isize;
+-              error = 0;
+-              goto cleanup;
++              goto out;
+       }
+       /*
+@@ -1552,6 +1553,8 @@ retry:
+               kfree(bs);
+       }
+       brelse(bh);
++out:
++      ext4_clear_inode_state(inode, EXT4_STATE_NO_EXPAND);
+       up_write(&EXT4_I(inode)->xattr_sem);
+       return 0;
+@@ -1563,6 +1566,10 @@ cleanup:
+       kfree(is);
+       kfree(bs);
+       brelse(bh);
++      /*
++       * We deliberately leave EXT4_STATE_NO_EXPAND set here since inode
++       * size expansion failed.
++       */
+       up_write(&EXT4_I(inode)->xattr_sem);
+       return error;
+ }
diff --git a/queue-4.7/ext4-avoid-modifying-checksum-fields-directly-during-checksum-verification.patch b/queue-4.7/ext4-avoid-modifying-checksum-fields-directly-during-checksum-verification.patch
new file mode 100644 (file)
index 0000000..32fbe0c
--- /dev/null
@@ -0,0 +1,174 @@
+From b47820edd1634dc1208f9212b7ecfb4230610a23 Mon Sep 17 00:00:00 2001
+From: Daeho Jeong <daeho.jeong@samsung.com>
+Date: Sun, 3 Jul 2016 17:51:39 -0400
+Subject: ext4: avoid modifying checksum fields directly during checksum verification
+
+From: Daeho Jeong <daeho.jeong@samsung.com>
+
+commit b47820edd1634dc1208f9212b7ecfb4230610a23 upstream.
+
+We temporally change checksum fields in buffers of some types of
+metadata into '0' for verifying the checksum values. By doing this
+without locking the buffer, some metadata's checksums, which are
+being committed or written back to the storage, could be damaged.
+In our test, several metadata blocks were found with damaged metadata
+checksum value during recovery process. When we only verify the
+checksum value, we have to avoid modifying checksum fields directly.
+
+Signed-off-by: Daeho Jeong <daeho.jeong@samsung.com>
+Signed-off-by: Youngjin Gil <youngjin.gil@samsung.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
+Cc: Török Edwin <edwin@etorok.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/inode.c |   38 ++++++++++++++++++++++----------------
+ fs/ext4/namei.c |    9 ++++-----
+ fs/ext4/super.c |   18 +++++++++---------
+ fs/ext4/xattr.c |   13 +++++++------
+ 4 files changed, 42 insertions(+), 36 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -51,25 +51,31 @@ static __u32 ext4_inode_csum(struct inod
+                             struct ext4_inode_info *ei)
+ {
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+-      __u16 csum_lo;
+-      __u16 csum_hi = 0;
+       __u32 csum;
++      __u16 dummy_csum = 0;
++      int offset = offsetof(struct ext4_inode, i_checksum_lo);
++      unsigned int csum_size = sizeof(dummy_csum);
+-      csum_lo = le16_to_cpu(raw->i_checksum_lo);
+-      raw->i_checksum_lo = 0;
+-      if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
+-          EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) {
+-              csum_hi = le16_to_cpu(raw->i_checksum_hi);
+-              raw->i_checksum_hi = 0;
+-      }
+-
+-      csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)raw,
+-                         EXT4_INODE_SIZE(inode->i_sb));
++      csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)raw, offset);
++      csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, csum_size);
++      offset += csum_size;
++      csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
++                         EXT4_GOOD_OLD_INODE_SIZE - offset);
+-      raw->i_checksum_lo = cpu_to_le16(csum_lo);
+-      if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE &&
+-          EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi))
+-              raw->i_checksum_hi = cpu_to_le16(csum_hi);
++      if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) {
++              offset = offsetof(struct ext4_inode, i_checksum_hi);
++              csum = ext4_chksum(sbi, csum, (__u8 *)raw +
++                                 EXT4_GOOD_OLD_INODE_SIZE,
++                                 offset - EXT4_GOOD_OLD_INODE_SIZE);
++              if (EXT4_FITS_IN_INODE(raw, ei, i_checksum_hi)) {
++                      csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum,
++                                         csum_size);
++                      offset += csum_size;
++                      csum = ext4_chksum(sbi, csum, (__u8 *)raw + offset,
++                                         EXT4_INODE_SIZE(inode->i_sb) -
++                                         offset);
++              }
++      }
+       return csum;
+ }
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -420,15 +420,14 @@ static __le32 ext4_dx_csum(struct inode
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       __u32 csum;
+-      __le32 save_csum;
+       int size;
++      __u32 dummy_csum = 0;
++      int offset = offsetof(struct dx_tail, dt_checksum);
+       size = count_offset + (count * sizeof(struct dx_entry));
+-      save_csum = t->dt_checksum;
+-      t->dt_checksum = 0;
+       csum = ext4_chksum(sbi, ei->i_csum_seed, (__u8 *)dirent, size);
+-      csum = ext4_chksum(sbi, csum, (__u8 *)t, sizeof(struct dx_tail));
+-      t->dt_checksum = save_csum;
++      csum = ext4_chksum(sbi, csum, (__u8 *)t, offset);
++      csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum));
+       return cpu_to_le32(csum);
+ }
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2068,23 +2068,25 @@ failed:
+ static __le16 ext4_group_desc_csum(struct super_block *sb, __u32 block_group,
+                                  struct ext4_group_desc *gdp)
+ {
+-      int offset;
++      int offset = offsetof(struct ext4_group_desc, bg_checksum);
+       __u16 crc = 0;
+       __le32 le_group = cpu_to_le32(block_group);
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       if (ext4_has_metadata_csum(sbi->s_sb)) {
+               /* Use new metadata_csum algorithm */
+-              __le16 save_csum;
+               __u32 csum32;
++              __u16 dummy_csum = 0;
+-              save_csum = gdp->bg_checksum;
+-              gdp->bg_checksum = 0;
+               csum32 = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&le_group,
+                                    sizeof(le_group));
+-              csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp,
+-                                   sbi->s_desc_size);
+-              gdp->bg_checksum = save_csum;
++              csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp, offset);
++              csum32 = ext4_chksum(sbi, csum32, (__u8 *)&dummy_csum,
++                                   sizeof(dummy_csum));
++              offset += sizeof(dummy_csum);
++              if (offset < sbi->s_desc_size)
++                      csum32 = ext4_chksum(sbi, csum32, (__u8 *)gdp + offset,
++                                           sbi->s_desc_size - offset);
+               crc = csum32 & 0xFFFF;
+               goto out;
+@@ -2094,8 +2096,6 @@ static __le16 ext4_group_desc_csum(struc
+       if (!ext4_has_feature_gdt_csum(sb))
+               return 0;
+-      offset = offsetof(struct ext4_group_desc, bg_checksum);
+-
+       crc = crc16(~0, sbi->s_es->s_uuid, sizeof(sbi->s_es->s_uuid));
+       crc = crc16(crc, (__u8 *)&le_group, sizeof(le_group));
+       crc = crc16(crc, (__u8 *)gdp, offset);
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -121,17 +121,18 @@ static __le32 ext4_xattr_block_csum(stru
+ {
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+       __u32 csum;
+-      __le32 save_csum;
+       __le64 dsk_block_nr = cpu_to_le64(block_nr);
++      __u32 dummy_csum = 0;
++      int offset = offsetof(struct ext4_xattr_header, h_checksum);
+-      save_csum = hdr->h_checksum;
+-      hdr->h_checksum = 0;
+       csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&dsk_block_nr,
+                          sizeof(dsk_block_nr));
+-      csum = ext4_chksum(sbi, csum, (__u8 *)hdr,
+-                         EXT4_BLOCK_SIZE(inode->i_sb));
++      csum = ext4_chksum(sbi, csum, (__u8 *)hdr, offset);
++      csum = ext4_chksum(sbi, csum, (__u8 *)&dummy_csum, sizeof(dummy_csum));
++      offset += sizeof(dummy_csum);
++      csum = ext4_chksum(sbi, csum, (__u8 *)hdr + offset,
++                         EXT4_BLOCK_SIZE(inode->i_sb) - offset);
+-      hdr->h_checksum = save_csum;
+       return cpu_to_le32(csum);
+ }
diff --git a/queue-4.7/ext4-fix-xattr-shifting-when-expanding-inodes-part-2.patch b/queue-4.7/ext4-fix-xattr-shifting-when-expanding-inodes-part-2.patch
new file mode 100644 (file)
index 0000000..688571a
--- /dev/null
@@ -0,0 +1,48 @@
+From 418c12d08dc64a45107c467ec1ba29b5e69b0715 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 11 Aug 2016 11:58:32 -0400
+Subject: ext4: fix xattr shifting when expanding inodes part 2
+
+From: Jan Kara <jack@suse.cz>
+
+commit 418c12d08dc64a45107c467ec1ba29b5e69b0715 upstream.
+
+When multiple xattrs need to be moved out of inode, we did not properly
+recompute total size of xattr headers in the inode and the new header
+position. Thus when moving the second and further xattr we asked
+ext4_xattr_shift_entries() to move too much and from the wrong place,
+resulting in possible xattr value corruption or general memory
+corruption.
+
+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/xattr.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1515,6 +1515,7 @@ retry:
+               error = ext4_xattr_ibody_set(handle, inode, &i, is);
+               if (error)
+                       goto cleanup;
++              total_ino -= entry_size;
+               entry = IFIRST(header);
+               if (entry_size + EXT4_XATTR_SIZE(size) >= isize_diff)
+@@ -1525,11 +1526,11 @@ retry:
+               ext4_xattr_shift_entries(entry, -shift_bytes,
+                       (void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE +
+                       EXT4_I(inode)->i_extra_isize + shift_bytes,
+-                      (void *)header, total_ino - entry_size,
+-                      inode->i_sb->s_blocksize);
++                      (void *)header, total_ino, inode->i_sb->s_blocksize);
+               isize_diff -= shift_bytes;
+               EXT4_I(inode)->i_extra_isize += shift_bytes;
++              header = IHDR(inode, raw_inode);
+               i.name = b_entry_name;
+               i.value = buffer;
diff --git a/queue-4.7/ext4-fix-xattr-shifting-when-expanding-inodes.patch b/queue-4.7/ext4-fix-xattr-shifting-when-expanding-inodes.patch
new file mode 100644 (file)
index 0000000..c5e7f52
--- /dev/null
@@ -0,0 +1,115 @@
+From d0141191a20289f8955c1e03dad08e42e6f71ca9 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 11 Aug 2016 11:50:30 -0400
+Subject: ext4: fix xattr shifting when expanding inodes
+
+From: Jan Kara <jack@suse.cz>
+
+commit d0141191a20289f8955c1e03dad08e42e6f71ca9 upstream.
+
+The code in ext4_expand_extra_isize_ea() treated new_extra_isize
+argument sometimes as the desired target i_extra_isize and sometimes as
+the amount by which we need to grow current i_extra_isize. These happen
+to coincide when i_extra_isize is 0 which used to be the common case and
+so nobody noticed this until recently when we added i_projid to the
+inode and so i_extra_isize now needs to grow from 28 to 32 bytes.
+
+The result of these bugs was that we sometimes unnecessarily decided to
+move xattrs out of inode even if there was enough space and we often
+ended up corrupting in-inode xattrs because arguments to
+ext4_xattr_shift_entries() were just wrong. This could demonstrate
+itself as BUG_ON in ext4_xattr_shift_entries() triggering.
+
+Fix the problem by introducing new isize_diff variable and use it where
+appropriate.
+
+Reported-by: Dave Chinner <david@fromorbit.com>
+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/xattr.c |   27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1352,11 +1352,13 @@ int ext4_expand_extra_isize_ea(struct in
+       size_t min_offs, free;
+       int total_ino;
+       void *base, *start, *end;
+-      int extra_isize = 0, error = 0, tried_min_extra_isize = 0;
++      int error = 0, tried_min_extra_isize = 0;
+       int s_min_extra_isize = le16_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_min_extra_isize);
++      int isize_diff; /* How much do we need to grow i_extra_isize */
+       down_write(&EXT4_I(inode)->xattr_sem);
+ retry:
++      isize_diff = new_extra_isize - EXT4_I(inode)->i_extra_isize;
+       if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) {
+               up_write(&EXT4_I(inode)->xattr_sem);
+               return 0;
+@@ -1381,7 +1383,7 @@ retry:
+               goto cleanup;
+       free = ext4_xattr_free_space(last, &min_offs, base, &total_ino);
+-      if (free >= new_extra_isize) {
++      if (free >= isize_diff) {
+               entry = IFIRST(header);
+               ext4_xattr_shift_entries(entry, EXT4_I(inode)->i_extra_isize
+                               - new_extra_isize, (void *)raw_inode +
+@@ -1413,7 +1415,7 @@ retry:
+               end = bh->b_data + bh->b_size;
+               min_offs = end - base;
+               free = ext4_xattr_free_space(first, &min_offs, base, NULL);
+-              if (free < new_extra_isize) {
++              if (free < isize_diff) {
+                       if (!tried_min_extra_isize && s_min_extra_isize) {
+                               tried_min_extra_isize++;
+                               new_extra_isize = s_min_extra_isize;
+@@ -1427,7 +1429,7 @@ retry:
+               free = inode->i_sb->s_blocksize;
+       }
+-      while (new_extra_isize > 0) {
++      while (isize_diff > 0) {
+               size_t offs, size, entry_size;
+               struct ext4_xattr_entry *small_entry = NULL;
+               struct ext4_xattr_info i = {
+@@ -1458,7 +1460,7 @@ retry:
+                       EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) +
+                                       EXT4_XATTR_LEN(last->e_name_len);
+                       if (total_size <= free && total_size < min_total_size) {
+-                              if (total_size < new_extra_isize) {
++                              if (total_size < isize_diff) {
+                                       small_entry = last;
+                               } else {
+                                       entry = last;
+@@ -1515,20 +1517,19 @@ retry:
+                       goto cleanup;
+               entry = IFIRST(header);
+-              if (entry_size + EXT4_XATTR_SIZE(size) >= new_extra_isize)
+-                      shift_bytes = new_extra_isize;
++              if (entry_size + EXT4_XATTR_SIZE(size) >= isize_diff)
++                      shift_bytes = isize_diff;
+               else
+                       shift_bytes = entry_size + size;
+               /* Adjust the offsets and shift the remaining entries ahead */
+-              ext4_xattr_shift_entries(entry, EXT4_I(inode)->i_extra_isize -
+-                      shift_bytes, (void *)raw_inode +
+-                      EXT4_GOOD_OLD_INODE_SIZE + extra_isize + shift_bytes,
++              ext4_xattr_shift_entries(entry, -shift_bytes,
++                      (void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE +
++                      EXT4_I(inode)->i_extra_isize + shift_bytes,
+                       (void *)header, total_ino - entry_size,
+                       inode->i_sb->s_blocksize);
+-              extra_isize += shift_bytes;
+-              new_extra_isize -= shift_bytes;
+-              EXT4_I(inode)->i_extra_isize = extra_isize;
++              isize_diff -= shift_bytes;
++              EXT4_I(inode)->i_extra_isize += shift_bytes;
+               i.name = b_entry_name;
+               i.value = buffer;
diff --git a/queue-4.7/ext4-properly-align-shifted-xattrs-when-expanding-inodes.patch b/queue-4.7/ext4-properly-align-shifted-xattrs-when-expanding-inodes.patch
new file mode 100644 (file)
index 0000000..489882e
--- /dev/null
@@ -0,0 +1,32 @@
+From 443a8c41cd49de66a3fda45b32b9860ea0292b84 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Thu, 11 Aug 2016 12:00:01 -0400
+Subject: ext4: properly align shifted xattrs when expanding inodes
+
+From: Jan Kara <jack@suse.cz>
+
+commit 443a8c41cd49de66a3fda45b32b9860ea0292b84 upstream.
+
+We did not count with the padding of xattr value when computing desired
+shift of xattrs in the inode when expanding i_extra_isize. As a result
+we could create unaligned start of inline xattrs. Account for alignment
+properly.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/xattr.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -1521,7 +1521,7 @@ retry:
+               if (entry_size + EXT4_XATTR_SIZE(size) >= isize_diff)
+                       shift_bytes = isize_diff;
+               else
+-                      shift_bytes = entry_size + size;
++                      shift_bytes = entry_size + EXT4_XATTR_SIZE(size);
+               /* Adjust the offsets and shift the remaining entries ahead */
+               ext4_xattr_shift_entries(entry, -shift_bytes,
+                       (void *)raw_inode + EXT4_GOOD_OLD_INODE_SIZE +
diff --git a/queue-4.7/ext4-validate-that-metadata-blocks-do-not-overlap-superblock.patch b/queue-4.7/ext4-validate-that-metadata-blocks-do-not-overlap-superblock.patch
new file mode 100644 (file)
index 0000000..c7126cc
--- /dev/null
@@ -0,0 +1,78 @@
+From 829fa70dddadf9dd041d62b82cd7cea63943899d Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Mon, 1 Aug 2016 00:51:02 -0400
+Subject: ext4: validate that metadata blocks do not overlap superblock
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 829fa70dddadf9dd041d62b82cd7cea63943899d upstream.
+
+A number of fuzzing failures seem to be caused by allocation bitmaps
+or other metadata blocks being pointed at the superblock.
+
+This can cause kernel BUG or WARNings once the superblock is
+overwritten, so validate the group descriptor blocks to make sure this
+doesn't happen.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c |   18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2131,6 +2131,7 @@ void ext4_group_desc_csum_set(struct sup
+ /* Called at mount-time, super-block is locked */
+ static int ext4_check_descriptors(struct super_block *sb,
++                                ext4_fsblk_t sb_block,
+                                 ext4_group_t *first_not_zeroed)
+ {
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+@@ -2161,6 +2162,11 @@ static int ext4_check_descriptors(struct
+                       grp = i;
+               block_bitmap = ext4_block_bitmap(sb, gdp);
++              if (block_bitmap == sb_block) {
++                      ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++                               "Block bitmap for group %u overlaps "
++                               "superblock", i);
++              }
+               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 "
+@@ -2168,6 +2174,11 @@ static int ext4_check_descriptors(struct
+                       return 0;
+               }
+               inode_bitmap = ext4_inode_bitmap(sb, gdp);
++              if (inode_bitmap == sb_block) {
++                      ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++                               "Inode bitmap for group %u overlaps "
++                               "superblock", i);
++              }
+               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 "
+@@ -2175,6 +2186,11 @@ static int ext4_check_descriptors(struct
+                       return 0;
+               }
+               inode_table = ext4_inode_table(sb, gdp);
++              if (inode_table == sb_block) {
++                      ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
++                               "Inode table for group %u overlaps "
++                               "superblock", i);
++              }
+               if (inode_table < first_block ||
+                   inode_table + sbi->s_itb_per_group - 1 > last_block) {
+                       ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: "
+@@ -3677,7 +3693,7 @@ static int ext4_fill_super(struct super_
+                       goto failed_mount2;
+               }
+       }
+-      if (!ext4_check_descriptors(sb, &first_not_zeroed)) {
++      if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) {
+               ext4_msg(sb, KERN_ERR, "group descriptors corrupted!");
+               ret = -EFSCORRUPTED;
+               goto failed_mount2;
diff --git a/queue-4.7/irqchip-gic-allow-self-sgis-for-smp-on-up-configurations.patch b/queue-4.7/irqchip-gic-allow-self-sgis-for-smp-on-up-configurations.patch
new file mode 100644 (file)
index 0000000..da61856
--- /dev/null
@@ -0,0 +1,37 @@
+From 059e232089e45b0befc9933d31209c225e08b426 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier@arm.com>
+Date: Tue, 9 Aug 2016 07:50:44 +0100
+Subject: irqchip/gic: Allow self-SGIs for SMP on UP configurations
+
+From: Marc Zyngier <marc.zyngier@arm.com>
+
+commit 059e232089e45b0befc9933d31209c225e08b426 upstream.
+
+On systems where a single CPU is present, the GIC may not support
+having SGIs delivered to a target list. In that case, we use the
+self-SGI mechanism to allow the interrupt to be delivered locally.
+
+Tested-by: Fabio Estevam <fabio.estevam@nxp.com>
+Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/irqchip/irq-gic.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/irqchip/irq-gic.c
++++ b/drivers/irqchip/irq-gic.c
+@@ -769,6 +769,13 @@ static void gic_raise_softirq(const stru
+       int cpu;
+       unsigned long flags, map = 0;
++      if (unlikely(nr_cpu_ids == 1)) {
++              /* Only one CPU? let's do a self-IPI... */
++              writel_relaxed(2 << 24 | irq,
++                             gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
++              return;
++      }
++
+       raw_spin_lock_irqsave(&irq_controller_lock, flags);
+       /* Convert our logical CPU mask into a physical one. */
index 43d702ba9800ad1e9a99784757d17a5a12f8e162..d7bd01a5da9299f91ed13cc083909844893d3e4b 100644 (file)
@@ -4,3 +4,10 @@ kernel-add-noaudit-variant-of-ns_capable.patch
 net-use-ns_capable_noaudit-when-determining-net-sysctl-permissions.patch
 fs-check-for-invalid-i_uid-in-may_follow_link.patch
 cred-reject-inodes-with-invalid-ids-in-set_create_file_as.patch
+irqchip-gic-allow-self-sgis-for-smp-on-up-configurations.patch
+ext4-validate-that-metadata-blocks-do-not-overlap-superblock.patch
+ext4-fix-xattr-shifting-when-expanding-inodes.patch
+ext4-fix-xattr-shifting-when-expanding-inodes-part-2.patch
+ext4-properly-align-shifted-xattrs-when-expanding-inodes.patch
+ext4-avoid-deadlock-when-expanding-inode-size.patch
+ext4-avoid-modifying-checksum-fields-directly-during-checksum-verification.patch