diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2018-09-13 20:00:21 +0100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2018-09-13 20:00:21 +0100 |
commit | 8e318d2dbee66930f40a40c3b782bc26291f818e (patch) | |
tree | 4d40ab488941522e21fb6458841b1ae9285b9052 /queue-3.16 | |
parent | 5e2643d1961aff902ca81943f7f18de615297745 (diff) | |
download | linux-stable-queue-8e318d2dbee66930f40a40c3b782bc26291f818e.tar.gz |
Add various security fixes
Diffstat (limited to 'queue-3.16')
22 files changed, 1447 insertions, 0 deletions
diff --git a/queue-3.16/bluetooth-hidp-buffer-overflow-in-hidp_process_report.patch b/queue-3.16/bluetooth-hidp-buffer-overflow-in-hidp_process_report.patch new file mode 100644 index 00000000..4d68332d --- /dev/null +++ b/queue-3.16/bluetooth-hidp-buffer-overflow-in-hidp_process_report.patch @@ -0,0 +1,46 @@ +From: Mark Salyzyn <salyzyn@android.com> +Date: Tue, 31 Jul 2018 15:02:13 -0700 +Subject: Bluetooth: hidp: buffer overflow in hidp_process_report + +commit 7992c18810e568b95c869b227137a2215702a805 upstream. + +CVE-2018-9363 + +The buffer length is unsigned at all layers, but gets cast to int and +checked in hidp_process_report and can lead to a buffer overflow. +Switch len parameter to unsigned int to resolve issue. + +This affects 3.18 and newer kernels. + +Signed-off-by: Mark Salyzyn <salyzyn@android.com> +Fixes: a4b1b5877b514b276f0f31efe02388a9c2836728 ("HID: Bluetooth: hidp: make sure input buffers are big enough") +Cc: Marcel Holtmann <marcel@holtmann.org> +Cc: Johan Hedberg <johan.hedberg@gmail.com> +Cc: "David S. Miller" <davem@davemloft.net> +Cc: Kees Cook <keescook@chromium.org> +Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com> +Cc: linux-bluetooth@vger.kernel.org +Cc: netdev@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Cc: security@kernel.org +Cc: kernel-team@android.com +Acked-by: Kees Cook <keescook@chromium.org> +Signed-off-by: Marcel Holtmann <marcel@holtmann.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/bluetooth/hidp/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/bluetooth/hidp/core.c ++++ b/net/bluetooth/hidp/core.c +@@ -429,8 +429,8 @@ static void hidp_del_timer(struct hidp_s + del_timer(&session->timer); + } + +-static void hidp_process_report(struct hidp_session *session, +- int type, const u8 *data, int len, int intr) ++static void hidp_process_report(struct hidp_session *session, int type, ++ const u8 *data, unsigned int len, int intr) + { + if (len > HID_MAX_BUFFER_SIZE) + len = HID_MAX_BUFFER_SIZE; diff --git a/queue-3.16/ext4-add-corruption-check-in-ext4_xattr_set_entry.patch b/queue-3.16/ext4-add-corruption-check-in-ext4_xattr_set_entry.patch new file mode 100644 index 00000000..c98f9442 --- /dev/null +++ b/queue-3.16/ext4-add-corruption-check-in-ext4_xattr_set_entry.patch @@ -0,0 +1,93 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 13 Jun 2018 00:23:11 -0400 +Subject: ext4: add corruption check in ext4_xattr_set_entry() + +commit 5369a762c882c0b6e9599e4ebbb3a9ba9eee7e2d upstream. + +In theory this should have been caught earlier when the xattr list was +verified, but in case it got missed, it's simple enough to add check +to make sure we don't overrun the xattr buffer. + +This addresses CVE-2018-10879. + +https://bugzilla.kernel.org/show_bug.cgi?id=200001 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Reviewed-by: Andreas Dilger <adilger@dilger.ca> +[bwh: Backported to 3.16: + - Add inode parameter to ext4_xattr_set_entry() and update callers + - Return -EIO instead of -EFSCORRUPTED on error + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -610,14 +610,20 @@ static size_t ext4_xattr_free_space(stru + } + + static int +-ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s) ++ext4_xattr_set_entry(struct ext4_xattr_info *i, struct ext4_xattr_search *s, ++ struct inode *inode) + { +- struct ext4_xattr_entry *last; ++ struct ext4_xattr_entry *last, *next; + size_t free, min_offs = s->end - s->base, name_len = strlen(i->name); + + /* Compute min_offs and last. */ + last = s->first; +- for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { ++ for (; !IS_LAST_ENTRY(last); last = next) { ++ next = EXT4_XATTR_NEXT(last); ++ if ((void *)next >= s->end) { ++ EXT4_ERROR_INODE(inode, "corrupted xattr entries"); ++ return -EIO; ++ } + if (!last->e_value_block && last->e_value_size) { + size_t offs = le16_to_cpu(last->e_value_offs); + if (offs < min_offs) +@@ -798,7 +804,7 @@ ext4_xattr_block_set(handle_t *handle, s + ce = NULL; + } + ea_bdebug(bs->bh, "modifying in-place"); +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (!error) { + if (!IS_LAST_ENTRY(s->first)) + ext4_xattr_rehash(header(s->base), +@@ -851,7 +857,7 @@ ext4_xattr_block_set(handle_t *handle, s + s->end = s->base + sb->s_blocksize; + } + +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (error == -EIO) + goto bad_block; + if (error) +@@ -1021,7 +1027,7 @@ int ext4_xattr_ibody_inline_set(handle_t + + if (EXT4_I(inode)->i_extra_isize == 0) + return -ENOSPC; +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (error) { + if (error == -ENOSPC && + ext4_has_inline_data(inode)) { +@@ -1033,7 +1039,7 @@ int ext4_xattr_ibody_inline_set(handle_t + error = ext4_xattr_ibody_find(inode, i, is); + if (error) + return error; +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + } + if (error) + return error; +@@ -1059,7 +1065,7 @@ static int ext4_xattr_ibody_set(handle_t + + if (EXT4_I(inode)->i_extra_isize == 0) + return -ENOSPC; +- error = ext4_xattr_set_entry(i, s); ++ error = ext4_xattr_set_entry(i, s, inode); + if (error) + return error; + header = IHDR(inode, ext4_raw_inode(&is->iloc)); diff --git a/queue-3.16/ext4-add-more-inode-number-paranoia-checks.patch b/queue-3.16/ext4-add-more-inode-number-paranoia-checks.patch new file mode 100644 index 00000000..f4c9eb29 --- /dev/null +++ b/queue-3.16/ext4-add-more-inode-number-paranoia-checks.patch @@ -0,0 +1,65 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Sun, 17 Jun 2018 00:41:14 -0400 +Subject: ext4: add more inode number paranoia checks + +commit c37e9e013469521d9adb932d17a1795c139b36db upstream. + +If there is a directory entry pointing to a system inode (such as a +journal inode), complain and declare the file system to be corrupted. + +Also, if the superblock's first inode number field is too small, +refuse to mount the file system. + +This addresses CVE-2018-10882. + +https://bugzilla.kernel.org/show_bug.cgi?id=200069 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/ext4.h | 5 ----- + fs/ext4/inode.c | 3 ++- + fs/ext4/super.c | 5 +++++ + 3 files changed, 7 insertions(+), 6 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1422,11 +1422,6 @@ static inline struct timespec ext4_curre + static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) + { + return ino == EXT4_ROOT_INO || +- ino == EXT4_USR_QUOTA_INO || +- ino == EXT4_GRP_QUOTA_INO || +- ino == EXT4_BOOT_LOADER_INO || +- ino == EXT4_JOURNAL_INO || +- ino == EXT4_RESIZE_INO || + (ino >= EXT4_FIRST_INO(sb) && + ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); + } +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3957,7 +3957,8 @@ static int __ext4_get_inode_loc(struct i + int inodes_per_block, inode_offset; + + iloc->bh = NULL; +- if (!ext4_valid_inum(sb, inode->i_ino)) ++ if (inode->i_ino < EXT4_ROOT_INO || ++ inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) + return -EIO; + + iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3771,6 +3771,11 @@ static int ext4_fill_super(struct super_ + } else { + sbi->s_inode_size = le16_to_cpu(es->s_inode_size); + sbi->s_first_ino = le32_to_cpu(es->s_first_ino); ++ if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { ++ ext4_msg(sb, KERN_ERR, "invalid first ino: %u", ++ sbi->s_first_ino); ++ goto failed_mount; ++ } + if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || + (!is_power_of_2(sbi->s_inode_size)) || + (sbi->s_inode_size > blocksize)) { diff --git a/queue-3.16/ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch b/queue-3.16/ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch new file mode 100644 index 00000000..218f5482 --- /dev/null +++ b/queue-3.16/ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch @@ -0,0 +1,55 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 13 Jun 2018 23:00:48 -0400 +Subject: ext4: always check block group bounds in ext4_init_block_bitmap() + +commit 819b23f1c501b17b9694325471789e6b5cc2d0d2 upstream. + +Regardless of whether the flex_bg feature is set, we should always +check to make sure the bits we are setting in the block bitmap are +within the block group bounds. + +https://bugzilla.kernel.org/show_bug.cgi?id=199865 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/balloc.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -184,7 +184,6 @@ static int ext4_init_block_bitmap(struct + unsigned int bit, bit_max; + struct ext4_sb_info *sbi = EXT4_SB(sb); + ext4_fsblk_t start, tmp; +- int flex_bg = 0; + struct ext4_group_info *grp; + + J_ASSERT_BH(bh, buffer_locked(bh)); +@@ -217,22 +216,19 @@ static int ext4_init_block_bitmap(struct + + start = ext4_group_first_block_no(sb, block_group); + +- if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) +- flex_bg = 1; +- + /* Set bits for block and inode bitmaps, and inode table */ + tmp = ext4_block_bitmap(sb, gdp); +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + + tmp = ext4_inode_bitmap(sb, gdp); +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + + tmp = ext4_inode_table(sb, gdp); + for (; tmp < ext4_inode_table(sb, gdp) + + sbi->s_itb_per_group; tmp++) { +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + } + diff --git a/queue-3.16/ext4-always-verify-the-magic-number-in-xattr-blocks.patch b/queue-3.16/ext4-always-verify-the-magic-number-in-xattr-blocks.patch new file mode 100644 index 00000000..579f63c7 --- /dev/null +++ b/queue-3.16/ext4-always-verify-the-magic-number-in-xattr-blocks.patch @@ -0,0 +1,45 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 13 Jun 2018 00:51:28 -0400 +Subject: ext4: always verify the magic number in xattr blocks + +commit 513f86d73855ce556ea9522b6bfd79f87356dc3a upstream. + +If there an inode points to a block which is also some other type of +metadata block (such as a block allocation bitmap), the +buffer_verified flag can be set when it was validated as that other +metadata block type; however, it would make a really terrible external +attribute block. The reason why we use the verified flag is to avoid +constantly reverifying the block. However, it doesn't take much +overhead to make sure the magic number of the xattr block is correct, +and this will avoid potential crashes. + +This addresses CVE-2018-10879. + +https://bugzilla.kernel.org/show_bug.cgi?id=200001 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Reviewed-by: Andreas Dilger <adilger@dilger.ca> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/xattr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -213,12 +213,12 @@ ext4_xattr_check_block(struct inode *ino + { + int error; + +- if (buffer_verified(bh)) +- return 0; +- + if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || + BHDR(bh)->h_blocks != cpu_to_le32(1)) + return -EIO; ++ if (buffer_verified(bh)) ++ return 0; ++ + if (!ext4_xattr_block_csum_verify(inode, bh)) + return -EIO; + error = ext4_xattr_check_names(BFIRST(bh), bh->b_data + bh->b_size, diff --git a/queue-3.16/ext4-avoid-running-out-of-journal-credits-when-appending-to-an.patch b/queue-3.16/ext4-avoid-running-out-of-journal-credits-when-appending-to-an.patch new file mode 100644 index 00000000..af1d0b4c --- /dev/null +++ b/queue-3.16/ext4-avoid-running-out-of-journal-credits-when-appending-to-an.patch @@ -0,0 +1,116 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Sat, 16 Jun 2018 23:41:59 -0400 +Subject: ext4: avoid running out of journal credits when appending to an + inline file + +commit 8bc1379b82b8e809eef77a9fedbb75c6c297be19 upstream. + +Use a separate journal transaction if it turns out that we need to +convert an inline file to use an data block. Otherwise we could end +up failing due to not having journal credits. + +This addresses CVE-2018-10883. + +https://bugzilla.kernel.org/show_bug.cgi?id=200071 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2701,9 +2701,6 @@ extern struct buffer_head *ext4_get_firs + extern int ext4_inline_data_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, + int *has_inline); +-extern int ext4_try_to_evict_inline_data(handle_t *handle, +- struct inode *inode, +- int needed); + extern void ext4_inline_data_truncate(struct inode *inode, int *has_inline); + + extern int ext4_convert_inline_data(struct inode *inode); +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -877,11 +877,11 @@ retry_journal: + } + + if (ret == -ENOSPC) { ++ ext4_journal_stop(handle); + ret = ext4_da_convert_inline_data_to_extent(mapping, + inode, + flags, + fsdata); +- ext4_journal_stop(handle); + if (ret == -ENOSPC && + ext4_should_retry_alloc(inode->i_sb, &retries)) + goto retry_journal; +@@ -1839,42 +1839,6 @@ out: + return (error < 0 ? error : 0); + } + +-/* +- * Called during xattr set, and if we can sparse space 'needed', +- * just create the extent tree evict the data to the outer block. +- * +- * We use jbd2 instead of page cache to move data to the 1st block +- * so that the whole transaction can be committed as a whole and +- * the data isn't lost because of the delayed page cache write. +- */ +-int ext4_try_to_evict_inline_data(handle_t *handle, +- struct inode *inode, +- int needed) +-{ +- int error; +- struct ext4_xattr_entry *entry; +- struct ext4_inode *raw_inode; +- struct ext4_iloc iloc; +- +- error = ext4_get_inode_loc(inode, &iloc); +- if (error) +- return error; +- +- raw_inode = ext4_raw_inode(&iloc); +- entry = (struct ext4_xattr_entry *)((void *)raw_inode + +- EXT4_I(inode)->i_inline_off); +- if (EXT4_XATTR_LEN(entry->e_name_len) + +- EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { +- error = -ENOSPC; +- goto out; +- } +- +- error = ext4_convert_inline_data_nolock(handle, inode, &iloc); +-out: +- brelse(iloc.bh); +- return error; +-} +- + void ext4_inline_data_truncate(struct inode *inode, int *has_inline) + { + handle_t *handle; +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1028,22 +1028,8 @@ int ext4_xattr_ibody_inline_set(handle_t + if (EXT4_I(inode)->i_extra_isize == 0) + return -ENOSPC; + error = ext4_xattr_set_entry(i, s, inode); +- if (error) { +- if (error == -ENOSPC && +- ext4_has_inline_data(inode)) { +- error = ext4_try_to_evict_inline_data(handle, inode, +- EXT4_XATTR_LEN(strlen(i->name) + +- EXT4_XATTR_SIZE(i->value_len))); +- if (error) +- return error; +- error = ext4_xattr_ibody_find(inode, i, is); +- if (error) +- return error; +- error = ext4_xattr_set_entry(i, s, inode); +- } +- if (error) +- return error; +- } ++ if (error) ++ return error; + header = IHDR(inode, ext4_raw_inode(&is->iloc)); + if (!IS_LAST_ENTRY(s->first)) { + header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); diff --git a/queue-3.16/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch b/queue-3.16/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch new file mode 100644 index 00000000..41fe68a4 --- /dev/null +++ b/queue-3.16/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch @@ -0,0 +1,43 @@ +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 + +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> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/inline.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -438,6 +438,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.16/ext4-don-t-allow-r-w-mounts-if-metadata-blocks-overlap-the.patch b/queue-3.16/ext4-don-t-allow-r-w-mounts-if-metadata-blocks-overlap-the.patch new file mode 100644 index 00000000..2adfd509 --- /dev/null +++ b/queue-3.16/ext4-don-t-allow-r-w-mounts-if-metadata-blocks-overlap-the.patch @@ -0,0 +1,56 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Thu, 29 Mar 2018 22:10:35 -0400 +Subject: ext4: don't allow r/w mounts if metadata blocks overlap the + superblock + +commit 18db4b4e6fc31eda838dd1c1296d67dbcb3dc957 upstream. + +If some metadata block, such as an allocation bitmap, overlaps the +superblock, it's very likely that if the file system is mounted +read/write, the results will not be pretty. So disallow r/w mounts +for file systems corrupted in this particular way. + +Backport notes: +3.18.y is missing bc98a42c1f7d ("VFS: Convert sb->s_flags & MS_RDONLY +to sb_rdonly(sb)") and e462ec50cb5f ("VFS: Differentiate mount flags +(MS_*) from internal superblock flags") so we simply use the sb +MS_RDONLY check from pre bc98a42c1f7d in place of the sb_rdonly +function used in the upstream variant of the patch. + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Harsh Shandilya <harsh@prjkt.io> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/super.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2115,6 +2115,8 @@ static int ext4_check_descriptors(struct + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Block bitmap for group %u overlaps " + "superblock", 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: " +@@ -2127,6 +2129,8 @@ static int ext4_check_descriptors(struct + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Inode bitmap for group %u overlaps " + "superblock", 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: " +@@ -2139,6 +2143,8 @@ static int ext4_check_descriptors(struct + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Inode table for group %u overlaps " + "superblock", i); ++ if (!(sb->s_flags & MS_RDONLY)) ++ return 0; + } + if (inode_table < first_block || + inode_table + sbi->s_itb_per_group - 1 > last_block) { diff --git a/queue-3.16/ext4-fix-check-to-prevent-initializing-reserved-inodes.patch b/queue-3.16/ext4-fix-check-to-prevent-initializing-reserved-inodes.patch new file mode 100644 index 00000000..e095c6ec --- /dev/null +++ b/queue-3.16/ext4-fix-check-to-prevent-initializing-reserved-inodes.patch @@ -0,0 +1,68 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Sat, 28 Jul 2018 08:12:04 -0400 +Subject: ext4: fix check to prevent initializing reserved inodes + +commit 5012284700775a4e6e3fbe7eac4c543c4874b559 upstream. + +Commit 8844618d8aa7: "ext4: only look at the bg_flags field if it is +valid" will complain if block group zero does not have the +EXT4_BG_INODE_ZEROED flag set. Unfortunately, this is not correct, +since a freshly created file system has this flag cleared. It gets +almost immediately after the file system is mounted read-write --- but +the following somewhat unlikely sequence will end up triggering a +false positive report of a corrupted file system: + + mkfs.ext4 /dev/vdc + mount -o ro /dev/vdc /vdc + mount -o remount,rw /dev/vdc + +Instead, when initializing the inode table for block group zero, test +to make sure that itable_unused count is not too large, since that is +the case that will result in some or all of the reserved inodes +getting cleared. + +This fixes the failures reported by Eric Whiteney when running +generic/230 and generic/231 in the the nojournal test case. + +Fixes: 8844618d8aa7 ("ext4: only look at the bg_flags field if it is valid") +Reported-by: Eric Whitney <enwlinux@gmail.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/ialloc.c | 5 ++++- + fs/ext4/super.c | 8 +------- + 2 files changed, 5 insertions(+), 8 deletions(-) + +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -1289,7 +1289,10 @@ int ext4_init_inode_table(struct super_b + ext4_itable_unused_count(sb, gdp)), + sbi->s_inodes_per_block); + +- if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) { ++ if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group) || ++ ((group == 0) && ((EXT4_INODES_PER_GROUP(sb) - ++ ext4_itable_unused_count(sb, gdp)) < ++ EXT4_FIRST_INO(sb)))) { + ext4_error(sb, "Something is wrong with group %u: " + "used itable blocks: %d; " + "itable unused count: %u", +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3088,14 +3088,8 @@ static ext4_group_t ext4_has_uninit_itab + if (!gdp) + continue; + +- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)) +- continue; +- if (group != 0) ++ if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) + break; +- ext4_error(sb, "Inode table for bg 0 marked as " +- "needing zeroing"); +- if (sb->s_flags & MS_RDONLY) +- return ngroups; + } + + return group; diff --git a/queue-3.16/ext4-fix-false-negatives-and-false-positives-in.patch b/queue-3.16/ext4-fix-false-negatives-and-false-positives-in.patch new file mode 100644 index 00000000..10f67953 --- /dev/null +++ b/queue-3.16/ext4-fix-false-negatives-and-false-positives-in.patch @@ -0,0 +1,53 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Sun, 8 Jul 2018 19:35:02 -0400 +Subject: ext4: fix false negatives *and* false positives in + ext4_check_descriptors() + +commit 44de022c4382541cebdd6de4465d1f4f465ff1dd upstream. + +Ext4_check_descriptors() was getting called before s_gdb_count was +initialized. So for file systems w/o the meta_bg feature, allocation +bitmaps could overlap the block group descriptors and ext4 wouldn't +notice. + +For file systems with the meta_bg feature enabled, there was a +fencepost error which would cause the ext4_check_descriptors() to +incorrectly believe that the block allocation bitmap overlaps with the +block group descriptor blocks, and it would reject the mount. + +Fix both of these problems. + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/super.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2086,7 +2086,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 last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0); + ext4_fsblk_t block_bitmap; + ext4_fsblk_t inode_bitmap; + ext4_fsblk_t inode_table; +@@ -3987,6 +3987,7 @@ static int ext4_fill_super(struct super_ + goto failed_mount2; + } + } ++ sbi->s_gdb_count = db_count; + if (!ext4_check_descriptors(sb, logical_sb_block, &first_not_zeroed)) { + ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); + goto failed_mount2; +@@ -3999,7 +4000,6 @@ static int ext4_fill_super(struct super_ + goto failed_mount2; + } + +- sbi->s_gdb_count = db_count; + get_random_bytes(&sbi->s_next_generation, sizeof(u32)); + spin_lock_init(&sbi->s_next_gen_lock); + diff --git a/queue-3.16/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg.patch b/queue-3.16/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg.patch new file mode 100644 index 00000000..48efb4a7 --- /dev/null +++ b/queue-3.16/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg.patch @@ -0,0 +1,76 @@ +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 + +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> +[bwh: Backported to 3.16: Open-code sb_rdonly()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/super.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2086,6 +2086,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; +@@ -2118,6 +2119,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 " +@@ -2132,6 +2141,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 " +@@ -2146,6 +2163,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: " diff --git a/queue-3.16/ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch b/queue-3.16/ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch new file mode 100644 index 00000000..7a79e66d --- /dev/null +++ b/queue-3.16/ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch @@ -0,0 +1,36 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Sat, 16 Jun 2018 15:40:48 -0400 +Subject: ext4: never move the system.data xattr out of the inode body + +commit 8cdb5240ec5928b20490a2bb34cb87e9a5f40226 upstream. + +When expanding the extra isize space, we must never move the +system.data xattr out of the inode body. For performance reasons, it +doesn't make any sense, and the inline data implementation assumes +that system.data xattr is never in the external xattr block. + +This addresses CVE-2018-10880 + +https://bugzilla.kernel.org/show_bug.cgi?id=200005 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/xattr.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1370,6 +1370,11 @@ retry: + /* Find the entry best suited to be pushed into EA block */ + entry = NULL; + for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { ++ /* never move system.data out of the inode */ ++ if ((last->e_name_len == 4) && ++ (last->e_name_index == EXT4_XATTR_INDEX_SYSTEM) && ++ !memcmp(last->e_name, "data", 4)) ++ continue; + total_size = + EXT4_XATTR_SIZE(le32_to_cpu(last->e_value_size)) + + EXT4_XATTR_LEN(last->e_name_len); diff --git a/queue-3.16/ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch b/queue-3.16/ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch new file mode 100644 index 00000000..a3df4672 --- /dev/null +++ b/queue-3.16/ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch @@ -0,0 +1,133 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Thu, 14 Jun 2018 00:58:00 -0400 +Subject: ext4: only look at the bg_flags field if it is valid + +commit 8844618d8aa7a9973e7b527d038a2a589665002c upstream. + +The bg_flags field in the block group descripts is only valid if the +uninit_bg or metadata_csum feature is enabled. We were not +consistently looking at this field; fix this. + +Also block group #0 must never have uninitialized allocation bitmaps, +or need to be zeroed, since that's where the root inode, and other +special inodes are set up. Check for these conditions and mark the +file system as corrupted if they are detected. + +This addresses CVE-2018-10876. + +https://bugzilla.kernel.org/show_bug.cgi?id=199403 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: + - ext4_read_block_bitmap_nowait() and ext4_read_inode_bitmap() return + a pointer (NULL on error) instead of an error code + - Open-code sb_rdonly() + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/balloc.c | 11 ++++++++++- + fs/ext4/ialloc.c | 14 ++++++++++++-- + fs/ext4/mballoc.c | 6 ++++-- + fs/ext4/super.c | 11 ++++++++++- + 4 files changed, 36 insertions(+), 6 deletions(-) + +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -453,9 +453,18 @@ ext4_read_block_bitmap_nowait(struct sup + goto verify; + } + ext4_lock_group(sb, block_group); +- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + int err; + ++ if (block_group == 0) { ++ ext4_unlock_group(sb, block_group); ++ unlock_buffer(bh); ++ ext4_error(sb, "Block bitmap for bg 0 marked " ++ "uninitialized"); ++ put_bh(bh); ++ return NULL; ++ } + err = ext4_init_block_bitmap(sb, bh, block_group, desc); + set_bitmap_uptodate(bh); + set_buffer_uptodate(bh); +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -156,7 +156,16 @@ ext4_read_inode_bitmap(struct super_bloc + } + + ext4_lock_group(sb, block_group); +- if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) { ++ if (block_group == 0) { ++ ext4_unlock_group(sb, block_group); ++ unlock_buffer(bh); ++ ext4_error(sb, "Inode bitmap for bg 0 marked " ++ "uninitialized"); ++ put_bh(bh); ++ return NULL; ++ } + ext4_init_inode_bitmap(sb, bh, block_group, desc); + set_bitmap_uptodate(bh); + set_buffer_uptodate(bh); +@@ -910,7 +919,8 @@ got: + + /* recheck and clear flag under lock if we still need to */ + ext4_lock_group(sb, group); +- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); + ext4_free_group_clusters_set(sb, gdp, + ext4_free_clusters_after_init(sb, group, gdp)); +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -2418,7 +2418,8 @@ int ext4_mb_add_groupinfo(struct super_b + * initialize bb_free to be able to skip + * empty groups without initialization + */ +- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + meta_group_info[i]->bb_free = + ext4_free_clusters_after_init(sb, group, desc); + } else { +@@ -2943,7 +2944,8 @@ ext4_mb_mark_diskspace_used(struct ext4_ + #endif + ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, + ac->ac_b_ex.fe_len); +- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); + ext4_free_group_clusters_set(sb, gdp, + ext4_free_clusters_after_init(sb, +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3080,13 +3080,22 @@ static ext4_group_t ext4_has_uninit_itab + ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; + struct ext4_group_desc *gdp = NULL; + ++ if (!ext4_has_group_desc_csum(sb)) ++ return ngroups; ++ + for (group = 0; group < ngroups; group++) { + gdp = ext4_get_group_desc(sb, group, NULL); + if (!gdp) + continue; + +- if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) ++ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)) ++ continue; ++ if (group != 0) + break; ++ ext4_error(sb, "Inode table for bg 0 marked as " ++ "needing zeroing"); ++ if (sb->s_flags & MS_RDONLY) ++ return ngroups; + } + + return group; diff --git a/queue-3.16/ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch b/queue-3.16/ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch new file mode 100644 index 00000000..a5e0cfbf --- /dev/null +++ b/queue-3.16/ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch @@ -0,0 +1,47 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Thu, 14 Jun 2018 12:55:10 -0400 +Subject: ext4: verify the depth of extent tree in ext4_find_extent() + +commit bc890a60247171294acc0bd67d211fa4b88d40ba upstream. + +If there is a corupted file system where the claimed depth of the +extent tree is -1, this can cause a massive buffer overrun leading to +sadness. + +This addresses CVE-2018-10877. + +https://bugzilla.kernel.org/show_bug.cgi?id=199417 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: return -EIO instead of -EFSCORRUPTED] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/ext4_extents.h | 1 + + fs/ext4/extents.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +--- a/fs/ext4/ext4_extents.h ++++ b/fs/ext4/ext4_extents.h +@@ -103,6 +103,7 @@ struct ext4_extent_header { + }; + + #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) ++#define EXT4_MAX_EXTENT_DEPTH 5 + + #define EXT4_EXTENT_TAIL_OFFSET(hdr) \ + (sizeof(struct ext4_extent_header) + \ +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -851,6 +851,12 @@ ext4_ext_find_extent(struct inode *inode + + eh = ext_inode_hdr(inode); + depth = ext_depth(inode); ++ if (depth < 0 || depth > EXT4_MAX_EXTENT_DEPTH) { ++ EXT4_ERROR_INODE(inode, "inode has invalid extent depth: %d", ++ depth); ++ ret = -EIO; ++ goto err; ++ } + + /* account possible depth increase */ + if (!path) { diff --git a/queue-3.16/fix-up-non-directory-creation-in-sgid-directories.patch b/queue-3.16/fix-up-non-directory-creation-in-sgid-directories.patch new file mode 100644 index 00000000..3c3d8633 --- /dev/null +++ b/queue-3.16/fix-up-non-directory-creation-in-sgid-directories.patch @@ -0,0 +1,43 @@ +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Tue, 3 Jul 2018 17:10:19 -0700 +Subject: Fix up non-directory creation in SGID directories + +commit 0fa3ecd87848c9c93c2c828ef4c3a8ca36ce46c7 upstream. + +sgid directories have special semantics, making newly created files in +the directory belong to the group of the directory, and newly created +subdirectories will also become sgid. This is historically used for +group-shared directories. + +But group directories writable by non-group members should not imply +that such non-group members can magically join the group, so make sure +to clear the sgid bit on non-directories for non-members (but remember +that sgid without group execute means "mandatory locking", just to +confuse things even more). + +Reported-by: Jann Horn <jannh@google.com> +Cc: Andy Lutomirski <luto@kernel.org> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/inode.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1827,8 +1827,14 @@ void inode_init_owner(struct inode *inod + inode->i_uid = current_fsuid(); + if (dir && dir->i_mode & S_ISGID) { + inode->i_gid = dir->i_gid; ++ ++ /* Directories are special, and always inherit S_ISGID */ + if (S_ISDIR(mode)) + mode |= S_ISGID; ++ else if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP) && ++ !in_group_p(inode->i_gid) && ++ !capable_wrt_inode_uidgid(dir, CAP_FSETID)) ++ mode &= ~S_ISGID; + } else + inode->i_gid = current_fsgid(); + inode->i_mode = mode; diff --git a/queue-3.16/infiniband-fix-a-possible-use-after-free-bug.patch b/queue-3.16/infiniband-fix-a-possible-use-after-free-bug.patch new file mode 100644 index 00000000..b3895b1c --- /dev/null +++ b/queue-3.16/infiniband-fix-a-possible-use-after-free-bug.patch @@ -0,0 +1,51 @@ +From: Cong Wang <xiyou.wangcong@gmail.com> +Date: Fri, 1 Jun 2018 11:31:44 -0700 +Subject: infiniband: fix a possible use-after-free bug + +commit cb2595c1393b4a5211534e6f0a0fbad369e21ad8 upstream. + +ucma_process_join() will free the new allocated "mc" struct, +if there is any error after that, especially the copy_to_user(). + +But in parallel, ucma_leave_multicast() could find this "mc" +through idr_find() before ucma_process_join() frees it, since it +is already published. + +So "mc" could be used in ucma_leave_multicast() after it is been +allocated and freed in ucma_process_join(), since we don't refcnt +it. + +Fix this by separating "publish" from ID allocation, so that we +can get an ID first and publish it later after copy_to_user(). + +Fixes: c8f6a362bf3e ("RDMA/cma: Add multicast communication support") +Reported-by: Noam Rathaus <noamr@beyondsecurity.com> +Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/core/ucma.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -180,7 +180,7 @@ static struct ucma_multicast* ucma_alloc + return NULL; + + mutex_lock(&mut); +- mc->id = idr_alloc(&multicast_idr, mc, 0, 0, GFP_KERNEL); ++ mc->id = idr_alloc(&multicast_idr, NULL, 0, 0, GFP_KERNEL); + mutex_unlock(&mut); + if (mc->id < 0) + goto error; +@@ -1285,6 +1285,10 @@ static ssize_t ucma_process_join(struct + goto err3; + } + ++ mutex_lock(&mut); ++ idr_replace(&multicast_idr, mc, mc->id); ++ mutex_unlock(&mut); ++ + mutex_unlock(&file->mut); + ucma_put_ctx(ctx); + return 0; diff --git a/queue-3.16/jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch b/queue-3.16/jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch new file mode 100644 index 00000000..48dcac3a --- /dev/null +++ b/queue-3.16/jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch @@ -0,0 +1,38 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Sat, 16 Jun 2018 20:21:45 -0400 +Subject: jbd2: don't mark block as modified if the handle is out of credits + +commit e09463f220ca9a1a1ecfda84fcda658f99a1f12a upstream. + +Do not set the b_modified flag in block's journal head should not +until after we're sure that jbd2_journal_dirty_metadat() will not +abort with an error due to there not being enough space reserved in +the jbd2 handle. + +Otherwise, future attempts to modify the buffer may lead a large +number of spurious errors and warnings. + +This addresses CVE-2018-10883. + +https://bugzilla.kernel.org/show_bug.cgi?id=200071 + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: Drop the added logging statement, as it's on + a code path that doesn't exist here] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1288,11 +1288,11 @@ int jbd2_journal_dirty_metadata(handle_t + * of the transaction. This needs to be done + * once a transaction -bzzz + */ +- jh->b_modified = 1; + if (handle->h_buffer_credits <= 0) { + ret = -ENOSPC; + goto out_unlock_bh; + } ++ jh->b_modified = 1; + handle->h_buffer_credits--; + } + diff --git a/queue-3.16/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch b/queue-3.16/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch new file mode 100644 index 00000000..46cc6429 --- /dev/null +++ b/queue-3.16/scsi-libsas-defer-ata-device-eh-commands-to-libata.patch @@ -0,0 +1,127 @@ +From: Jason Yan <yanaijie@huawei.com> +Date: Thu, 8 Mar 2018 10:34:53 +0800 +Subject: scsi: libsas: defer ata device eh commands to libata + +commit 318aaf34f1179b39fa9c30fa0f3288b645beee39 upstream. + +When ata device doing EH, some commands still attached with tasks are +not passed to libata when abort failed or recover failed, so libata did +not handle these commands. After these commands done, sas task is freed, +but ata qc is not freed. This will cause ata qc leak and trigger a +warning like below: + +WARNING: CPU: 0 PID: 28512 at drivers/ata/libata-eh.c:4037 +ata_eh_finish+0xb4/0xcc +CPU: 0 PID: 28512 Comm: kworker/u32:2 Tainted: G W OE 4.14.0#1 +...... +Call trace: +[<ffff0000088b7bd0>] ata_eh_finish+0xb4/0xcc +[<ffff0000088b8420>] ata_do_eh+0xc4/0xd8 +[<ffff0000088b8478>] ata_std_error_handler+0x44/0x8c +[<ffff0000088b8068>] ata_scsi_port_error_handler+0x480/0x694 +[<ffff000008875fc4>] async_sas_ata_eh+0x4c/0x80 +[<ffff0000080f6be8>] async_run_entry_fn+0x4c/0x170 +[<ffff0000080ebd70>] process_one_work+0x144/0x390 +[<ffff0000080ec100>] worker_thread+0x144/0x418 +[<ffff0000080f2c98>] kthread+0x10c/0x138 +[<ffff0000080855dc>] ret_from_fork+0x10/0x18 + +If ata qc leaked too many, ata tag allocation will fail and io blocked +for ever. + +As suggested by Dan Williams, defer ata device commands to libata and +merge sas_eh_finish_cmd() with sas_eh_defer_cmd(). libata will handle +ata qcs correctly after this. + +Signed-off-by: Jason Yan <yanaijie@huawei.com> +CC: Xiaofei Tan <tanxiaofei@huawei.com> +CC: John Garry <john.garry@huawei.com> +CC: Dan Williams <dan.j.williams@intel.com> +Reviewed-by: Dan Williams <dan.j.williams@intel.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/scsi/libsas/sas_scsi_host.c | 33 ++++++++++++----------------- + 1 file changed, 13 insertions(+), 20 deletions(-) + +--- a/drivers/scsi/libsas/sas_scsi_host.c ++++ b/drivers/scsi/libsas/sas_scsi_host.c +@@ -250,6 +250,7 @@ out_done: + static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) + { + struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); ++ struct domain_device *dev = cmd_to_domain_dev(cmd); + struct sas_task *task = TO_SAS_TASK(cmd); + + /* At this point, we only get called following an actual abort +@@ -258,6 +259,14 @@ static void sas_eh_finish_cmd(struct scs + */ + sas_end_task(cmd, task); + ++ if (dev_is_sata(dev)) { ++ /* defer commands to libata so that libata EH can ++ * handle ata qcs correctly ++ */ ++ list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q); ++ return; ++ } ++ + /* now finish the command and move it on to the error + * handler done list, this also takes it off the + * error handler pending list. +@@ -265,22 +274,6 @@ static void sas_eh_finish_cmd(struct scs + scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); + } + +-static void sas_eh_defer_cmd(struct scsi_cmnd *cmd) +-{ +- struct domain_device *dev = cmd_to_domain_dev(cmd); +- struct sas_ha_struct *ha = dev->port->ha; +- struct sas_task *task = TO_SAS_TASK(cmd); +- +- if (!dev_is_sata(dev)) { +- sas_eh_finish_cmd(cmd); +- return; +- } +- +- /* report the timeout to libata */ +- sas_end_task(cmd, task); +- list_move_tail(&cmd->eh_entry, &ha->eh_ata_q); +-} +- + static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) + { + struct scsi_cmnd *cmd, *n; +@@ -288,7 +281,7 @@ static void sas_scsi_clear_queue_lu(stru + list_for_each_entry_safe(cmd, n, error_q, eh_entry) { + if (cmd->device->sdev_target == my_cmd->device->sdev_target && + cmd->device->lun == my_cmd->device->lun) +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + } + } + +@@ -677,12 +670,12 @@ static void sas_eh_handle_sas_errors(str + case TASK_IS_DONE: + SAS_DPRINTK("%s: task 0x%p is done\n", __func__, + task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_ABORTED: + SAS_DPRINTK("%s: task 0x%p is aborted\n", + __func__, task); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + continue; + case TASK_IS_AT_LU: + SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); +@@ -693,7 +686,7 @@ static void sas_eh_handle_sas_errors(str + "recovered\n", + SAS_ADDR(task->dev), + cmd->device->lun); +- sas_eh_defer_cmd(cmd); ++ sas_eh_finish_cmd(cmd); + sas_scsi_clear_queue_lu(work_q, cmd); + goto Again; + } diff --git a/queue-3.16/series b/queue-3.16/series index ff6ba44c..9263751b 100644 --- a/queue-3.16/series +++ b/queue-3.16/series @@ -18,3 +18,24 @@ kvm-x86-use-correct-privilege-level-for-sgdt-sidt-fxsave-fxrstor-access.patch sr-pass-down-correctly-sized-scsi-sense-buffer.patch jfs-fix-inconsistency-between-memory-allocation-and-ea_buf-max_size.patch scsi-sg-allocate-with-__gfp_zero-in-sg_build_indirect.patch +bluetooth-hidp-buffer-overflow-in-hidp_process_report.patch +scsi-libsas-defer-ata-device-eh-commands-to-libata.patch +xfs-set-format-back-to-extents-if-xfs_bmap_extents_to_btree.patch +ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch +ext4-fix-check-to-prevent-initializing-reserved-inodes.patch +ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch +ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch +ext4-don-t-allow-r-w-mounts-if-metadata-blocks-overlap-the.patch +ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg.patch +ext4-fix-false-negatives-and-false-positives-in.patch +ext4-add-corruption-check-in-ext4_xattr_set_entry.patch +ext4-always-verify-the-magic-number-in-xattr-blocks.patch +ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch +ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch +ext4-add-more-inode-number-paranoia-checks.patch +jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch +ext4-avoid-running-out-of-journal-credits-when-appending-to-an.patch +fix-up-non-directory-creation-in-sgid-directories.patch +x86-entry-64-remove-ebx-handling-from-error_entry-exit.patch +infiniband-fix-a-possible-use-after-free-bug.patch +usb-yurex-fix-out-of-bounds-uaccess-in-read-handler.patch diff --git a/queue-3.16/usb-yurex-fix-out-of-bounds-uaccess-in-read-handler.patch b/queue-3.16/usb-yurex-fix-out-of-bounds-uaccess-in-read-handler.patch new file mode 100644 index 00000000..f3839ee3 --- /dev/null +++ b/queue-3.16/usb-yurex-fix-out-of-bounds-uaccess-in-read-handler.patch @@ -0,0 +1,65 @@ +From: Jann Horn <jannh@google.com> +Date: Fri, 6 Jul 2018 17:12:56 +0200 +Subject: USB: yurex: fix out-of-bounds uaccess in read handler + +commit f1e255d60ae66a9f672ff9a207ee6cd8e33d2679 upstream. + +In general, accessing userspace memory beyond the length of the supplied +buffer in VFS read/write handlers can lead to both kernel memory corruption +(via kernel_read()/kernel_write(), which can e.g. be triggered via +sys_splice()) and privilege escalation inside userspace. + +Fix it by using simple_read_from_buffer() instead of custom logic. + +Fixes: 6bc235a2e24a ("USB: add driver for Meywa-Denki & Kayac YUREX") +Signed-off-by: Jann Horn <jannh@google.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/misc/yurex.c | 23 ++++++----------------- + 1 file changed, 6 insertions(+), 17 deletions(-) + +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -413,8 +413,7 @@ static int yurex_release(struct inode *i + static ssize_t yurex_read(struct file *file, char *buffer, size_t count, loff_t *ppos) + { + struct usb_yurex *dev; +- int retval = 0; +- int bytes_read = 0; ++ int len = 0; + char in_buffer[20]; + unsigned long flags; + +@@ -422,26 +421,16 @@ static ssize_t yurex_read(struct file *f + + mutex_lock(&dev->io_mutex); + if (!dev->interface) { /* already disconnected */ +- retval = -ENODEV; +- goto exit; ++ mutex_unlock(&dev->io_mutex); ++ return -ENODEV; + } + + spin_lock_irqsave(&dev->lock, flags); +- bytes_read = snprintf(in_buffer, 20, "%lld\n", dev->bbu); ++ len = snprintf(in_buffer, 20, "%lld\n", dev->bbu); + spin_unlock_irqrestore(&dev->lock, flags); +- +- if (*ppos < bytes_read) { +- if (copy_to_user(buffer, in_buffer + *ppos, bytes_read - *ppos)) +- retval = -EFAULT; +- else { +- retval = bytes_read - *ppos; +- *ppos += bytes_read; +- } +- } +- +-exit: + mutex_unlock(&dev->io_mutex); +- return retval; ++ ++ return simple_read_from_buffer(buffer, count, ppos, in_buffer, len); + } + + static ssize_t yurex_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) diff --git a/queue-3.16/x86-entry-64-remove-ebx-handling-from-error_entry-exit.patch b/queue-3.16/x86-entry-64-remove-ebx-handling-from-error_entry-exit.patch new file mode 100644 index 00000000..4e8e6ffd --- /dev/null +++ b/queue-3.16/x86-entry-64-remove-ebx-handling-from-error_entry-exit.patch @@ -0,0 +1,133 @@ +From: Andy Lutomirski <luto@kernel.org> +Date: Sun, 22 Jul 2018 11:05:09 -0700 +Subject: x86/entry/64: Remove %ebx handling from error_entry/exit + +commit b3681dd548d06deb2e1573890829dff4b15abf46 upstream. + +error_entry and error_exit communicate the user vs. kernel status of +the frame using %ebx. This is unnecessary -- the information is in +regs->cs. Just use regs->cs. + +This makes error_entry simpler and makes error_exit more robust. + +It also fixes a nasty bug. Before all the Spectre nonsense, the +xen_failsafe_callback entry point returned like this: + + ALLOC_PT_GPREGS_ON_STACK + SAVE_C_REGS + SAVE_EXTRA_REGS + ENCODE_FRAME_POINTER + jmp error_exit + +And it did not go through error_entry. This was bogus: RBX +contained garbage, and error_exit expected a flag in RBX. + +Fortunately, it generally contained *nonzero* garbage, so the +correct code path was used. As part of the Spectre fixes, code was +added to clear RBX to mitigate certain speculation attacks. Now, +depending on kernel configuration, RBX got zeroed and, when running +some Wine workloads, the kernel crashes. This was introduced by: + + commit 3ac6d8c787b8 ("x86/entry/64: Clear registers for exceptions/interrupts, to reduce speculation attack surface") + +With this patch applied, RBX is no longer needed as a flag, and the +problem goes away. + +I suspect that malicious userspace could use this bug to crash the +kernel even without the offending patch applied, though. + +[ Historical note: I wrote this patch as a cleanup before I was aware + of the bug it fixed. ] + +[ Note to stable maintainers: this should probably get applied to all + kernels. If you're nervous about that, a more conservative fix to + add xorl %ebx,%ebx; incl %ebx before the jump to error_exit should + also fix the problem. ] + +Reported-and-tested-by: M. Vefa Bicakci <m.v.b@runbox.com> +Signed-off-by: Andy Lutomirski <luto@kernel.org> +Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> +Cc: Borislav Petkov <bp@alien8.de> +Cc: Brian Gerst <brgerst@gmail.com> +Cc: Dave Hansen <dave.hansen@linux.intel.com> +Cc: Denys Vlasenko <dvlasenk@redhat.com> +Cc: Dominik Brodowski <linux@dominikbrodowski.net> +Cc: Greg KH <gregkh@linuxfoundation.org> +Cc: H. Peter Anvin <hpa@zytor.com> +Cc: Josh Poimboeuf <jpoimboe@redhat.com> +Cc: Juergen Gross <jgross@suse.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: xen-devel@lists.xenproject.org +Fixes: 3ac6d8c787b8 ("x86/entry/64: Clear registers for exceptions/interrupts, to reduce speculation attack surface") +Link: http://lkml.kernel.org/r/b5010a090d3586b2d6e06c7ad3ec5542d1241c45.1532282627.git.luto@kernel.org +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16: + - error_exit moved EBX to EAX before testing it, so delete both instructions + - error_exit does RESTORE_REST earlier, so adjust the offset to saved CS + accordingly + - Drop inapplicable comment changes + - Adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/x86/kernel/entry_64.S ++++ b/arch/x86/kernel/entry_64.S +@@ -1135,7 +1135,7 @@ ENTRY(\sym) + .if \paranoid + jmp paranoid_exit /* %ebx: no swapgs flag */ + .else +- jmp error_exit /* %ebx: no swapgs flag */ ++ jmp error_exit + .endif + + CFI_ENDPROC +@@ -1411,7 +1411,6 @@ END(paranoid_exit) + + /* + * Exception entry point. This expects an error code/orig_rax on the stack. +- * returns in "no swapgs flag" in %ebx. + */ + ENTRY(error_entry) + XCPT_FRAME +@@ -1440,7 +1439,6 @@ ENTRY(error_entry) + * the kernel CR3 here. + */ + SWITCH_KERNEL_CR3 +- xorl %ebx,%ebx + testl $3,CS+8(%rsp) + je error_kernelspace + error_swapgs: +@@ -1456,7 +1454,6 @@ error_sti: + * for these here too. + */ + error_kernelspace: +- incl %ebx + leaq native_irq_return_iret(%rip),%rcx + cmpq %rcx,RIP+8(%rsp) + je error_bad_iret +@@ -1477,22 +1474,18 @@ error_bad_iret: + mov %rsp,%rdi + call fixup_bad_iret + mov %rax,%rsp +- decl %ebx /* Return to usergs */ + jmp error_sti + CFI_ENDPROC + END(error_entry) + +- +-/* ebx: no swapgs flag (1: don't need swapgs, 0: need it) */ + ENTRY(error_exit) + DEFAULT_FRAME +- movl %ebx,%eax + RESTORE_REST + DISABLE_INTERRUPTS(CLBR_NONE) + TRACE_IRQS_OFF + GET_THREAD_INFO(%rcx) +- testl %eax,%eax +- jne retint_kernel ++ testb $3, CS-ARGOFFSET(%rsp) ++ jz retint_kernel + LOCKDEP_SYS_EXIT_IRQ + movl TI_flags(%rcx),%edx + movl $_TIF_WORK_MASK,%edi diff --git a/queue-3.16/xfs-set-format-back-to-extents-if-xfs_bmap_extents_to_btree.patch b/queue-3.16/xfs-set-format-back-to-extents-if-xfs_bmap_extents_to_btree.patch new file mode 100644 index 00000000..83d6e382 --- /dev/null +++ b/queue-3.16/xfs-set-format-back-to-extents-if-xfs_bmap_extents_to_btree.patch @@ -0,0 +1,37 @@ +From: Eric Sandeen <sandeen@redhat.com> +Date: Mon, 16 Apr 2018 23:07:27 -0700 +Subject: xfs: set format back to extents if xfs_bmap_extents_to_btree + +commit 2c4306f719b083d17df2963bc761777576b8ad1b upstream. + +If xfs_bmap_extents_to_btree fails in a mode where we call +xfs_iroot_realloc(-1) to de-allocate the root, set the +format back to extents. + +Otherwise we can assume we can dereference ifp->if_broot +based on the XFS_DINODE_FMT_BTREE format, and crash. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199423 +Signed-off-by: Eric Sandeen <sandeen@redhat.com> +Reviewed-by: Christoph Hellwig <hch@lst.de> +Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> +Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> +[bwh: Backported to 3.16: + - Only one failure path needs to be patched + - Adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/xfs/xfs_bmap.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/xfs/xfs_bmap.c ++++ b/fs/xfs/xfs_bmap.c +@@ -822,6 +822,8 @@ xfs_bmap_extents_to_btree( + *logflagsp = 0; + if ((error = xfs_alloc_vextent(&args))) { + xfs_iroot_realloc(ip, -1, whichfork); ++ ASSERT(ifp->if_broot == NULL); ++ XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_EXTENTS); + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); + return error; + } |