From: Greg Kroah-Hartman Date: Wed, 8 Mar 2017 15:40:08 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.4.53~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=be285ff8032cf9a315ee08320bac0d86d55bd52c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: block-loop-fix-race-between-i-o-and-set_status.patch ext4-do-not-polute-the-extents-cache-while-shifting-extents.patch ext4-fix-data-corruption-in-data-journal-mode.patch ext4-fix-inline-data-error-paths.patch ext4-fix-use-after-iput-when-fscrypt-contexts-are-inconsistent.patch ext4-include-forgotten-start-block-on-fallocate-insert-range.patch ext4-preserve-the-needs_recovery-flag-when-the-journal-is-aborted.patch ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch ext4-trim-allocation-requests-to-group-size.patch jbd2-don-t-leak-modified-metadata-buffers-on-an-aborted-journal.patch loop-fix-lo_flags_partscan-hang.patch mei-remove-support-for-broken-parallel-read.patch samples-seccomp-fix-64-bit-comparison-macros.patch --- diff --git a/queue-4.9/block-loop-fix-race-between-i-o-and-set_status.patch b/queue-4.9/block-loop-fix-race-between-i-o-and-set_status.patch new file mode 100644 index 00000000000..dd480eb167d --- /dev/null +++ b/queue-4.9/block-loop-fix-race-between-i-o-and-set_status.patch @@ -0,0 +1,100 @@ +From ecdd09597a57251323b0de50e3d45e69298c4a83 Mon Sep 17 00:00:00 2001 +From: Ming Lei +Date: Sat, 11 Feb 2017 11:40:45 +0800 +Subject: block/loop: fix race between I/O and set_status + +From: Ming Lei + +commit ecdd09597a57251323b0de50e3d45e69298c4a83 upstream. + +Inside set_status, transfer need to setup again, so +we have to drain IO before the transition, otherwise +oops may be triggered like the following: + + divide error: 0000 [#1] SMP KASAN + CPU: 0 PID: 2935 Comm: loop7 Not tainted 4.10.0-rc7+ #213 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs + 01/01/2011 + task: ffff88006ba1e840 task.stack: ffff880067338000 + RIP: 0010:transfer_xor+0x1d1/0x440 drivers/block/loop.c:110 + RSP: 0018:ffff88006733f108 EFLAGS: 00010246 + RAX: 0000000000000000 RBX: ffff8800688d7000 RCX: 0000000000000059 + RDX: 0000000000000000 RSI: 1ffff1000d743f43 RDI: ffff880068891c08 + RBP: ffff88006733f160 R08: ffff8800688d7001 R09: 0000000000000000 + R10: 0000000000000000 R11: 0000000000000000 R12: ffff8800688d7000 + R13: ffff880067b7d000 R14: dffffc0000000000 R15: 0000000000000000 + FS: 0000000000000000(0000) GS:ffff88006d000000(0000) + knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00000000006c17e0 CR3: 0000000066e3b000 CR4: 00000000001406f0 + Call Trace: + lo_do_transfer drivers/block/loop.c:251 [inline] + lo_read_transfer drivers/block/loop.c:392 [inline] + do_req_filebacked drivers/block/loop.c:541 [inline] + loop_handle_cmd drivers/block/loop.c:1677 [inline] + loop_queue_work+0xda0/0x49b0 drivers/block/loop.c:1689 + kthread_worker_fn+0x4c3/0xa30 kernel/kthread.c:630 + kthread+0x326/0x3f0 kernel/kthread.c:227 + ret_from_fork+0x31/0x40 arch/x86/entry/entry_64.S:430 + Code: 03 83 e2 07 41 29 df 42 0f b6 04 30 4d 8d 44 24 01 38 d0 7f 08 + 84 c0 0f 85 62 02 00 00 44 89 f8 41 0f b6 48 ff 25 ff 01 00 00 99 + 7d c8 48 63 d2 48 03 55 d0 48 89 d0 48 89 d7 48 c1 e8 03 83 + RIP: transfer_xor+0x1d1/0x440 drivers/block/loop.c:110 RSP: + ffff88006733f108 + ---[ end trace 0166f7bd3b0c0933 ]--- + +Reported-by: Dmitry Vyukov +Signed-off-by: Ming Lei +Tested-by: Dmitry Vyukov +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/loop.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1097,9 +1097,12 @@ loop_set_status(struct loop_device *lo, + if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) + return -EINVAL; + ++ /* I/O need to be drained during transfer transition */ ++ blk_mq_freeze_queue(lo->lo_queue); ++ + err = loop_release_xfer(lo); + if (err) +- return err; ++ goto exit; + + if (info->lo_encrypt_type) { + unsigned int type = info->lo_encrypt_type; +@@ -1114,12 +1117,14 @@ loop_set_status(struct loop_device *lo, + + err = loop_init_xfer(lo, xfer, info); + if (err) +- return err; ++ goto exit; + + if (lo->lo_offset != info->lo_offset || + lo->lo_sizelimit != info->lo_sizelimit) +- if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) +- return -EFBIG; ++ if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) { ++ err = -EFBIG; ++ goto exit; ++ } + + loop_config_discard(lo); + +@@ -1156,7 +1161,9 @@ loop_set_status(struct loop_device *lo, + /* update dio if lo_offset or transfer is changed */ + __loop_update_dio(lo, lo->use_dio); + +- return 0; ++ exit: ++ blk_mq_unfreeze_queue(lo->lo_queue); ++ return err; + } + + static int diff --git a/queue-4.9/ext4-do-not-polute-the-extents-cache-while-shifting-extents.patch b/queue-4.9/ext4-do-not-polute-the-extents-cache-while-shifting-extents.patch new file mode 100644 index 00000000000..5372ea78f22 --- /dev/null +++ b/queue-4.9/ext4-do-not-polute-the-extents-cache-while-shifting-extents.patch @@ -0,0 +1,61 @@ +From 03e916fa8b5577d85471452a3d0c5738aa658dae Mon Sep 17 00:00:00 2001 +From: Roman Pen +Date: Sun, 8 Jan 2017 21:00:35 -0500 +Subject: ext4: do not polute the extents cache while shifting extents + +From: Roman Pen + +commit 03e916fa8b5577d85471452a3d0c5738aa658dae upstream. + +Inside ext4_ext_shift_extents() function ext4_find_extent() is called +without EXT4_EX_NOCACHE flag, which should prevent cache population. + +This leads to oudated offsets in the extents tree and wrong blocks +afterwards. + +Patch fixes the problem providing EXT4_EX_NOCACHE flag for each +ext4_find_extents() call inside ext4_ext_shift_extents function. + +Fixes: 331573febb6a2 +Signed-off-by: Roman Pen +Signed-off-by: Theodore Ts'o +Cc: Namjae Jeon +Cc: Andreas Dilger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5344,7 +5344,8 @@ ext4_ext_shift_extents(struct inode *ino + ext4_lblk_t stop, *iterator, ex_start, ex_end; + + /* Let path point to the last extent */ +- path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0); ++ path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, ++ EXT4_EX_NOCACHE); + if (IS_ERR(path)) + return PTR_ERR(path); + +@@ -5360,7 +5361,8 @@ ext4_ext_shift_extents(struct inode *ino + * sure the hole is big enough to accommodate the shift. + */ + if (SHIFT == SHIFT_LEFT) { +- path = ext4_find_extent(inode, start - 1, &path, 0); ++ path = ext4_find_extent(inode, start - 1, &path, ++ EXT4_EX_NOCACHE); + if (IS_ERR(path)) + return PTR_ERR(path); + depth = path->p_depth; +@@ -5398,7 +5400,8 @@ ext4_ext_shift_extents(struct inode *ino + * becomes NULL to indicate the end of the loop. + */ + while (iterator && start <= stop) { +- path = ext4_find_extent(inode, *iterator, &path, 0); ++ path = ext4_find_extent(inode, *iterator, &path, ++ EXT4_EX_NOCACHE); + if (IS_ERR(path)) + return PTR_ERR(path); + depth = path->p_depth; diff --git a/queue-4.9/ext4-fix-data-corruption-in-data-journal-mode.patch b/queue-4.9/ext4-fix-data-corruption-in-data-journal-mode.patch new file mode 100644 index 00000000000..418ba51baba --- /dev/null +++ b/queue-4.9/ext4-fix-data-corruption-in-data-journal-mode.patch @@ -0,0 +1,73 @@ +From 3b136499e906460919f0d21a49db1aaccf0ae963 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 27 Jan 2017 14:35:38 -0500 +Subject: ext4: fix data corruption in data=journal mode + +From: Jan Kara + +commit 3b136499e906460919f0d21a49db1aaccf0ae963 upstream. + +ext4_journalled_write_end() did not propely handle all the cases when +generic_perform_write() did not copy all the data into the target page +and could mark buffers with uninitialized contents as uptodate and dirty +leading to possible data corruption (which would be quickly fixed by +generic_perform_write() retrying the write but still). Fix the problem +by carefully handling the case when the page that is written to is not +uptodate. + +Reported-by: Al Viro +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1379,7 +1379,9 @@ errout: + * set the buffer to be dirty, since in data=journalled mode we need + * to call ext4_handle_dirty_metadata() instead. + */ +-static void zero_new_buffers(struct page *page, unsigned from, unsigned to) ++static void ext4_journalled_zero_new_buffers(handle_t *handle, ++ struct page *page, ++ unsigned from, unsigned to) + { + unsigned int block_start = 0, block_end; + struct buffer_head *head, *bh; +@@ -1396,7 +1398,7 @@ static void zero_new_buffers(struct page + size = min(to, block_end) - start; + + zero_user(page, start, size); +- set_buffer_uptodate(bh); ++ write_end_fn(handle, bh); + } + clear_buffer_new(bh); + } +@@ -1428,15 +1430,16 @@ static int ext4_journalled_write_end(str + if (ext4_has_inline_data(inode)) + copied = ext4_write_inline_data_end(inode, pos, len, + copied, page); +- else { +- if (copied < len) { +- if (!PageUptodate(page)) +- copied = 0; +- zero_new_buffers(page, from+copied, to); +- } +- ++ else if (unlikely(copied < len) && !PageUptodate(page)) { ++ copied = 0; ++ ext4_journalled_zero_new_buffers(handle, page, from, to); ++ } else { ++ if (unlikely(copied < len)) ++ ext4_journalled_zero_new_buffers(handle, page, ++ from + copied, to); + ret = ext4_walk_page_buffers(handle, page_buffers(page), from, +- to, &partial, write_end_fn); ++ from + copied, &partial, ++ write_end_fn); + if (!partial) + SetPageUptodate(page); + } diff --git a/queue-4.9/ext4-fix-inline-data-error-paths.patch b/queue-4.9/ext4-fix-inline-data-error-paths.patch new file mode 100644 index 00000000000..e8a4497367a --- /dev/null +++ b/queue-4.9/ext4-fix-inline-data-error-paths.patch @@ -0,0 +1,83 @@ +From eb5efbcb762aee4b454b04f7115f73ccbcf8f0ef Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 4 Feb 2017 23:04:00 -0500 +Subject: ext4: fix inline data error paths + +From: Theodore Ts'o + +commit eb5efbcb762aee4b454b04f7115f73ccbcf8f0ef upstream. + +The write_end() function must always unlock the page and drop its ref +count, even on an error. + +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inline.c | 9 ++++++++- + fs/ext4/inode.c | 20 +++++++++++++++----- + 2 files changed, 23 insertions(+), 6 deletions(-) + +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -933,8 +933,15 @@ int ext4_da_write_inline_data_end(struct + struct page *page) + { + int i_size_changed = 0; ++ int ret; + +- copied = ext4_write_inline_data_end(inode, pos, len, copied, page); ++ ret = ext4_write_inline_data_end(inode, pos, len, copied, page); ++ if (ret < 0) { ++ unlock_page(page); ++ put_page(page); ++ return ret; ++ } ++ copied = ret; + + /* + * No need to use i_size_read() here, the i_size +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1324,8 +1324,11 @@ static int ext4_write_end(struct file *f + if (ext4_has_inline_data(inode)) { + ret = ext4_write_inline_data_end(inode, pos, len, + copied, page); +- if (ret < 0) ++ if (ret < 0) { ++ unlock_page(page); ++ put_page(page); + goto errout; ++ } + copied = ret; + } else + copied = block_write_end(file, mapping, pos, +@@ -1427,10 +1430,16 @@ static int ext4_journalled_write_end(str + + BUG_ON(!ext4_handle_valid(handle)); + +- if (ext4_has_inline_data(inode)) +- copied = ext4_write_inline_data_end(inode, pos, len, +- copied, page); +- else if (unlikely(copied < len) && !PageUptodate(page)) { ++ if (ext4_has_inline_data(inode)) { ++ ret = ext4_write_inline_data_end(inode, pos, len, ++ copied, page); ++ if (ret < 0) { ++ unlock_page(page); ++ put_page(page); ++ goto errout; ++ } ++ copied = ret; ++ } else if (unlikely(copied < len) && !PageUptodate(page)) { + copied = 0; + ext4_journalled_zero_new_buffers(handle, page, from, to); + } else { +@@ -1465,6 +1474,7 @@ static int ext4_journalled_write_end(str + */ + ext4_orphan_add(handle, inode); + ++errout: + ret2 = ext4_journal_stop(handle); + if (!ret) + ret = ret2; diff --git a/queue-4.9/ext4-fix-use-after-iput-when-fscrypt-contexts-are-inconsistent.patch b/queue-4.9/ext4-fix-use-after-iput-when-fscrypt-contexts-are-inconsistent.patch new file mode 100644 index 00000000000..cdb121863eb --- /dev/null +++ b/queue-4.9/ext4-fix-use-after-iput-when-fscrypt-contexts-are-inconsistent.patch @@ -0,0 +1,45 @@ +From dd01b690f8f4b1e414f89e5a9a5326bf720d6652 Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Wed, 1 Feb 2017 21:07:11 -0500 +Subject: ext4: fix use-after-iput when fscrypt contexts are inconsistent + +From: Eric Biggers + +commit dd01b690f8f4b1e414f89e5a9a5326bf720d6652 upstream. + +In the case where the child's encryption context was inconsistent with +its parent directory, we were using inode->i_sb and inode->i_ino after +the inode had already been iput(). Fix this by doing the iput() in the +correct places. + +Note: only ext4 had this bug, not f2fs and ubifs. + +Fixes: d9cdc9033181 ("ext4 crypto: enforce context consistency") +Signed-off-by: Eric Biggers +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -1616,13 +1616,15 @@ static struct dentry *ext4_lookup(struct + !fscrypt_has_permitted_context(dir, inode)) { + int nokey = ext4_encrypted_inode(inode) && + !fscrypt_has_encryption_key(inode); +- iput(inode); +- if (nokey) ++ if (nokey) { ++ iput(inode); + return ERR_PTR(-ENOKEY); ++ } + ext4_warning(inode->i_sb, + "Inconsistent encryption contexts: %lu/%lu", + (unsigned long) dir->i_ino, + (unsigned long) inode->i_ino); ++ iput(inode); + return ERR_PTR(-EPERM); + } + } diff --git a/queue-4.9/ext4-include-forgotten-start-block-on-fallocate-insert-range.patch b/queue-4.9/ext4-include-forgotten-start-block-on-fallocate-insert-range.patch new file mode 100644 index 00000000000..cac10417c14 --- /dev/null +++ b/queue-4.9/ext4-include-forgotten-start-block-on-fallocate-insert-range.patch @@ -0,0 +1,113 @@ +From 2a9b8cba62c0741109c33a2be700ff3d7703a7c2 Mon Sep 17 00:00:00 2001 +From: Roman Pen +Date: Sun, 8 Jan 2017 20:59:35 -0500 +Subject: ext4: Include forgotten start block on fallocate insert range + +From: Roman Pen + +commit 2a9b8cba62c0741109c33a2be700ff3d7703a7c2 upstream. + +While doing 'insert range' start block should be also shifted right. +The bug can be easily reproduced by the following test: + + ptr = malloc(4096); + assert(ptr); + + fd = open("./ext4.file", O_CREAT | O_TRUNC | O_RDWR, 0600); + assert(fd >= 0); + + rc = fallocate(fd, 0, 0, 8192); + assert(rc == 0); + for (i = 0; i < 2048; i++) + *((unsigned short *)ptr + i) = 0xbeef; + rc = pwrite(fd, ptr, 4096, 0); + assert(rc == 4096); + rc = pwrite(fd, ptr, 4096, 4096); + assert(rc == 4096); + + for (block = 2; block < 1000; block++) { + rc = fallocate(fd, FALLOC_FL_INSERT_RANGE, 4096, 4096); + assert(rc == 0); + + for (i = 0; i < 2048; i++) + *((unsigned short *)ptr + i) = block; + + rc = pwrite(fd, ptr, 4096, 4096); + assert(rc == 4096); + } + +Because start block is not included in the range the hole appears at +the wrong offset (just after the desired offset) and the following +pwrite() overwrites already existent block, keeping hole untouched. + +Simple way to verify wrong behaviour is to check zeroed blocks after +the test: + + $ hexdump ./ext4.file | grep '0000 0000' + +The root cause of the bug is a wrong range (start, stop], where start +should be inclusive, i.e. [start, stop]. + +This patch fixes the problem by including start into the range. But +not to break left shift (range collapse) stop points to the beginning +of the a block, not to the end. + +The other not obvious change is an iterator check on validness in a +main loop. Because iterator is unsigned the following corner case +should be considered with care: insert a block at 0 offset, when stop +variables overflows and never becomes less than start, which is 0. +To handle this special case iterator is set to NULL to indicate that +end of the loop is reached. + +Fixes: 331573febb6a2 +Signed-off-by: Roman Pen +Signed-off-by: Theodore Ts'o +Cc: Namjae Jeon +Cc: Andreas Dilger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5353,8 +5353,7 @@ ext4_ext_shift_extents(struct inode *ino + if (!extent) + goto out; + +- stop = le32_to_cpu(extent->ee_block) + +- ext4_ext_get_actual_len(extent); ++ stop = le32_to_cpu(extent->ee_block); + + /* + * In case of left shift, Don't start shifting extents until we make +@@ -5393,8 +5392,12 @@ ext4_ext_shift_extents(struct inode *ino + else + iterator = &stop; + +- /* Its safe to start updating extents */ +- while (start < stop) { ++ /* ++ * Its safe to start updating extents. Start and stop are unsigned, so ++ * in case of right shift if extent with 0 block is reached, iterator ++ * becomes NULL to indicate the end of the loop. ++ */ ++ while (iterator && start <= stop) { + path = ext4_find_extent(inode, *iterator, &path, 0); + if (IS_ERR(path)) + return PTR_ERR(path); +@@ -5422,8 +5425,11 @@ ext4_ext_shift_extents(struct inode *ino + ext4_ext_get_actual_len(extent); + } else { + extent = EXT_FIRST_EXTENT(path[depth].p_hdr); +- *iterator = le32_to_cpu(extent->ee_block) > 0 ? +- le32_to_cpu(extent->ee_block) - 1 : 0; ++ if (le32_to_cpu(extent->ee_block) > 0) ++ *iterator = le32_to_cpu(extent->ee_block) - 1; ++ else ++ /* Beginning is reached, end of the loop */ ++ iterator = NULL; + /* Update path extent in case we need to stop */ + while (le32_to_cpu(extent->ee_block) < start) + extent++; diff --git a/queue-4.9/ext4-preserve-the-needs_recovery-flag-when-the-journal-is-aborted.patch b/queue-4.9/ext4-preserve-the-needs_recovery-flag-when-the-journal-is-aborted.patch new file mode 100644 index 00000000000..b649e139648 --- /dev/null +++ b/queue-4.9/ext4-preserve-the-needs_recovery-flag-when-the-journal-is-aborted.patch @@ -0,0 +1,51 @@ +From 97abd7d4b5d9c48ec15c425485f054e1c15e591b Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 4 Feb 2017 23:38:06 -0500 +Subject: ext4: preserve the needs_recovery flag when the journal is aborted + +From: Theodore Ts'o + +commit 97abd7d4b5d9c48ec15c425485f054e1c15e591b upstream. + +If the journal is aborted, the needs_recovery feature flag should not +be removed. Otherwise, it's the journal might not get replayed and +this could lead to more data getting lost. + +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -825,6 +825,7 @@ static void ext4_put_super(struct super_ + { + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_super_block *es = sbi->s_es; ++ int aborted = 0; + int i, err; + + ext4_unregister_li_request(sb); +@@ -834,9 +835,10 @@ static void ext4_put_super(struct super_ + destroy_workqueue(sbi->rsv_conversion_wq); + + if (sbi->s_journal) { ++ aborted = is_journal_aborted(sbi->s_journal); + err = jbd2_journal_destroy(sbi->s_journal); + sbi->s_journal = NULL; +- if (err < 0) ++ if ((err < 0) && !aborted) + ext4_abort(sb, "Couldn't clean up the journal"); + } + +@@ -847,7 +849,7 @@ static void ext4_put_super(struct super_ + ext4_mb_release(sb); + ext4_ext_release(sb); + +- if (!(sb->s_flags & MS_RDONLY)) { ++ if (!(sb->s_flags & MS_RDONLY) && !aborted) { + ext4_clear_feature_journal_needs_recovery(sb); + es->s_state = cpu_to_le16(sbi->s_mount_state); + } diff --git a/queue-4.9/ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch b/queue-4.9/ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch new file mode 100644 index 00000000000..cc7a7a84b6c --- /dev/null +++ b/queue-4.9/ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch @@ -0,0 +1,32 @@ +From 4753d8a24d4588657bc0a4cd66d4e282dff15c8c Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 5 Feb 2017 01:26:48 -0500 +Subject: ext4: return EROFS if device is r/o and journal replay is needed + +From: Theodore Ts'o + +commit 4753d8a24d4588657bc0a4cd66d4e282dff15c8c upstream. + +If the file system requires journal recovery, and the device is +read-ony, return EROFS to the mount system call. This allows xfstests +generic/050 to pass. + +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3913,7 +3913,8 @@ static int ext4_fill_super(struct super_ + * root first: it may be modified in the journal! + */ + if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) { +- if (ext4_load_journal(sb, es, journal_devnum)) ++ err = ext4_load_journal(sb, es, journal_devnum); ++ if (err) + goto failed_mount3a; + } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) && + ext4_has_feature_journal_needs_recovery(sb)) { diff --git a/queue-4.9/ext4-trim-allocation-requests-to-group-size.patch b/queue-4.9/ext4-trim-allocation-requests-to-group-size.patch new file mode 100644 index 00000000000..8d43bd93efa --- /dev/null +++ b/queue-4.9/ext4-trim-allocation-requests-to-group-size.patch @@ -0,0 +1,39 @@ +From cd648b8a8fd5071d232242d5ee7ee3c0815776af Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 27 Jan 2017 14:34:30 -0500 +Subject: ext4: trim allocation requests to group size + +From: Jan Kara + +commit cd648b8a8fd5071d232242d5ee7ee3c0815776af upstream. + +If filesystem groups are artifically small (using parameter -g to +mkfs.ext4), ext4_mb_normalize_request() can result in a request that is +larger than a block group. Trim the request size to not confuse +allocation code. + +Reported-by: "Kirill A. Shutemov" +Signed-off-by: Jan Kara +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/mballoc.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -3123,6 +3123,13 @@ ext4_mb_normalize_request(struct ext4_al + if (ar->pright && start + size - 1 >= ar->lright) + size -= start + size - ar->lright; + ++ /* ++ * Trim allocation request for filesystems with artificially small ++ * groups. ++ */ ++ if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)) ++ size = EXT4_BLOCKS_PER_GROUP(ac->ac_sb); ++ + end = start + size; + + /* check we don't cross already preallocated blocks */ diff --git a/queue-4.9/jbd2-don-t-leak-modified-metadata-buffers-on-an-aborted-journal.patch b/queue-4.9/jbd2-don-t-leak-modified-metadata-buffers-on-an-aborted-journal.patch new file mode 100644 index 00000000000..b9776cf2da1 --- /dev/null +++ b/queue-4.9/jbd2-don-t-leak-modified-metadata-buffers-on-an-aborted-journal.patch @@ -0,0 +1,34 @@ +From e112666b4959b25a8552d63bc564e1059be703e8 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 4 Feb 2017 23:14:19 -0500 +Subject: jbd2: don't leak modified metadata buffers on an aborted journal + +From: Theodore Ts'o + +commit e112666b4959b25a8552d63bc564e1059be703e8 upstream. + +If the journal has been aborted, we shouldn't mark the underlying +buffer head as dirty, since that will cause the metadata block to get +modified. And if the journal has been aborted, we shouldn't allow +this since it will almost certainly lead to a corrupted file system. + +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/transaction.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1863,7 +1863,9 @@ static void __jbd2_journal_temp_unlink_b + + __blist_del_buffer(list, jh); + jh->b_jlist = BJ_None; +- if (test_clear_buffer_jbddirty(bh)) ++ if (transaction && is_journal_aborted(transaction->t_journal)) ++ clear_buffer_jbddirty(bh); ++ else if (test_clear_buffer_jbddirty(bh)) + mark_buffer_dirty(bh); /* Expose it to the VM */ + } + diff --git a/queue-4.9/loop-fix-lo_flags_partscan-hang.patch b/queue-4.9/loop-fix-lo_flags_partscan-hang.patch new file mode 100644 index 00000000000..411a03bec9e --- /dev/null +++ b/queue-4.9/loop-fix-lo_flags_partscan-hang.patch @@ -0,0 +1,55 @@ +From e02898b423802b1f3a3aaa7f16e896da069ba8f7 Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Wed, 1 Mar 2017 10:42:38 -0800 +Subject: loop: fix LO_FLAGS_PARTSCAN hang + +From: Omar Sandoval + +commit e02898b423802b1f3a3aaa7f16e896da069ba8f7 upstream. + +loop_reread_partitions() needs to do I/O, but we just froze the queue, +so we end up waiting forever. This can easily be reproduced with losetup +-P. Fix it by moving the reread to after we unfreeze the queue. + +Fixes: ecdd09597a57 ("block/loop: fix race between I/O and set_status") +Reported-by: Tejun Heo +Signed-off-by: Omar Sandoval +Reviewed-by: Ming Lei +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/loop.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1142,13 +1142,6 @@ loop_set_status(struct loop_device *lo, + (info->lo_flags & LO_FLAGS_AUTOCLEAR)) + lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; + +- if ((info->lo_flags & LO_FLAGS_PARTSCAN) && +- !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { +- lo->lo_flags |= LO_FLAGS_PARTSCAN; +- lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; +- loop_reread_partitions(lo, lo->lo_device); +- } +- + lo->lo_encrypt_key_size = info->lo_encrypt_key_size; + lo->lo_init[0] = info->lo_init[0]; + lo->lo_init[1] = info->lo_init[1]; +@@ -1163,6 +1156,14 @@ loop_set_status(struct loop_device *lo, + + exit: + blk_mq_unfreeze_queue(lo->lo_queue); ++ ++ if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) && ++ !(lo->lo_flags & LO_FLAGS_PARTSCAN)) { ++ lo->lo_flags |= LO_FLAGS_PARTSCAN; ++ lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN; ++ loop_reread_partitions(lo, lo->lo_device); ++ } ++ + return err; + } + diff --git a/queue-4.9/mei-remove-support-for-broken-parallel-read.patch b/queue-4.9/mei-remove-support-for-broken-parallel-read.patch new file mode 100644 index 00000000000..4e02572e13c --- /dev/null +++ b/queue-4.9/mei-remove-support-for-broken-parallel-read.patch @@ -0,0 +1,84 @@ +From cb97fbbcac15982406e0c74cd5512a8b6fcf10b3 Mon Sep 17 00:00:00 2001 +From: Alexander Usyskin +Date: Wed, 8 Feb 2017 00:41:45 +0200 +Subject: mei: remove support for broken parallel read + +From: Alexander Usyskin + +commit cb97fbbcac15982406e0c74cd5512a8b6fcf10b3 upstream. + +Parallel reads from multiple threads on a file descriptor +are not well defined and racy. It is safer to return to original +behavior and simply fail the additional read. +The solution is to remove request for next read credit. + +Fixes: ff1586a7ea57 ("mei: enqueue consecutive reads") +Signed-off-by: Alexander Usyskin +Signed-off-by: Tomas Winkler +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/mei/main.c | 48 ++++++++++++++++++++++++++---------------------- + 1 file changed, 26 insertions(+), 22 deletions(-) + +--- a/drivers/misc/mei/main.c ++++ b/drivers/misc/mei/main.c +@@ -182,32 +182,36 @@ static ssize_t mei_read(struct file *fil + goto out; + } + +- if (rets == -EBUSY && +- !mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, file)) { +- rets = -ENOMEM; +- goto out; ++ ++again: ++ mutex_unlock(&dev->device_lock); ++ if (wait_event_interruptible(cl->rx_wait, ++ !list_empty(&cl->rd_completed) || ++ !mei_cl_is_connected(cl))) { ++ if (signal_pending(current)) ++ return -EINTR; ++ return -ERESTARTSYS; + } ++ mutex_lock(&dev->device_lock); + +- do { +- mutex_unlock(&dev->device_lock); ++ if (!mei_cl_is_connected(cl)) { ++ rets = -ENODEV; ++ goto out; ++ } + +- if (wait_event_interruptible(cl->rx_wait, +- (!list_empty(&cl->rd_completed)) || +- (!mei_cl_is_connected(cl)))) { +- +- if (signal_pending(current)) +- return -EINTR; +- return -ERESTARTSYS; +- } +- +- mutex_lock(&dev->device_lock); +- if (!mei_cl_is_connected(cl)) { +- rets = -ENODEV; +- goto out; +- } ++ cb = mei_cl_read_cb(cl, file); ++ if (!cb) { ++ /* ++ * For amthif all the waiters are woken up, ++ * but only fp with matching cb->fp get the cb, ++ * the others have to return to wait on read. ++ */ ++ if (cl == &dev->iamthif_cl) ++ goto again; + +- cb = mei_cl_read_cb(cl, file); +- } while (!cb); ++ rets = 0; ++ goto out; ++ } + + copy_buffer: + /* now copy the data to user space */ diff --git a/queue-4.9/samples-seccomp-fix-64-bit-comparison-macros.patch b/queue-4.9/samples-seccomp-fix-64-bit-comparison-macros.patch new file mode 100644 index 00000000000..bcdd74e1926 --- /dev/null +++ b/queue-4.9/samples-seccomp-fix-64-bit-comparison-macros.patch @@ -0,0 +1,196 @@ +From 916cafdc95843fb9af5fd5f83ca499d75473d107 Mon Sep 17 00:00:00 2001 +From: Mathias Svensson +Date: Fri, 6 Jan 2017 13:32:39 -0800 +Subject: samples/seccomp: fix 64-bit comparison macros +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mathias Svensson + +commit 916cafdc95843fb9af5fd5f83ca499d75473d107 upstream. + +There were some bugs in the JNE64 and JLT64 comparision macros. This fixes +them, improves comments, and cleans up the file while we are at it. + +Reported-by: Stephen Röttger +Signed-off-by: Mathias Svensson +Signed-off-by: Kees Cook +Signed-off-by: James Morris +Signed-off-by: Greg Kroah-Hartman + +--- + samples/seccomp/bpf-helper.h | 125 ++++++++++++++++++++++++------------------- + 1 file changed, 72 insertions(+), 53 deletions(-) + +--- a/samples/seccomp/bpf-helper.h ++++ b/samples/seccomp/bpf-helper.h +@@ -138,7 +138,7 @@ union arg64 { + #define ARG_32(idx) \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)) + +-/* Loads hi into A and lo in X */ ++/* Loads lo into M[0] and hi into M[1] and A */ + #define ARG_64(idx) \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \ + BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \ +@@ -153,88 +153,107 @@ union arg64 { + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \ + jt + +-/* Checks the lo, then swaps to check the hi. A=lo,X=hi */ ++#define JA32(value, jt) \ ++ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \ ++ jt ++ ++#define JGE32(value, jt) \ ++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \ ++ jt ++ ++#define JGT32(value, jt) \ ++ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \ ++ jt ++ ++#define JLE32(value, jt) \ ++ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \ ++ jt ++ ++#define JLT32(value, jt) \ ++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \ ++ jt ++ ++/* ++ * All the JXX64 checks assume lo is saved in M[0] and hi is saved in both ++ * A and M[1]. This invariant is kept by restoring A if necessary. ++ */ + #define JEQ64(lo, hi, jt) \ ++ /* if (hi != arg.hi) goto NOMATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ + BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ ++ /* if (lo != arg.lo) goto NOMATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \ +- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1), \ + jt, \ +- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ ++ BPF_STMT(BPF_LD+BPF_MEM, 1) + + #define JNE64(lo, hi, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \ +- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ ++ /* if (hi != arg.hi) goto MATCH; */ \ ++ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \ ++ BPF_STMT(BPF_LD+BPF_MEM, 0), \ ++ /* if (lo != arg.lo) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \ +- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1), \ + jt, \ +- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ +- +-#define JA32(value, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \ +- jt ++ BPF_STMT(BPF_LD+BPF_MEM, 1) + + #define JA64(lo, hi, jt) \ ++ /* if (hi & arg.hi) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \ +- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 0), \ ++ /* if (lo & arg.lo) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \ +- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1), \ + jt, \ +- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ +- +-#define JGE32(value, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \ +- jt ++ BPF_STMT(BPF_LD+BPF_MEM, 1) + +-#define JLT32(value, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \ +- jt +- +-/* Shortcut checking if hi > arg.hi. */ + #define JGE64(lo, hi, jt) \ ++ /* if (hi > arg.hi) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \ ++ /* if (hi != arg.hi) goto NOMATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ +- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 0), \ ++ /* if (lo >= arg.lo) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \ +- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1), \ + jt, \ +- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ +- +-#define JLT64(lo, hi, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ +- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ +- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ +- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \ +- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ +- jt, \ +- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ +- +-#define JGT32(value, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \ +- jt +- +-#define JLE32(value, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \ +- jt ++ BPF_STMT(BPF_LD+BPF_MEM, 1) + +-/* Check hi > args.hi first, then do the GE checking */ + #define JGT64(lo, hi, jt) \ ++ /* if (hi > arg.hi) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \ ++ /* if (hi != arg.hi) goto NOMATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ +- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 0), \ ++ /* if (lo > arg.lo) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \ +- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1), \ + jt, \ +- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ ++ BPF_STMT(BPF_LD+BPF_MEM, 1) + + #define JLE64(lo, hi, jt) \ +- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \ +- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \ +- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \ ++ /* if (hi < arg.hi) goto MATCH; */ \ ++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ ++ /* if (hi != arg.hi) goto NOMATCH; */ \ ++ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ ++ BPF_STMT(BPF_LD+BPF_MEM, 0), \ ++ /* if (lo <= arg.lo) goto MATCH; */ \ + BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \ +- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1), \ ++ jt, \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1) ++ ++#define JLT64(lo, hi, jt) \ ++ /* if (hi < arg.hi) goto MATCH; */ \ ++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \ ++ /* if (hi != arg.hi) goto NOMATCH; */ \ ++ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \ ++ BPF_STMT(BPF_LD+BPF_MEM, 0), \ ++ /* if (lo < arg.lo) goto MATCH; */ \ ++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \ ++ BPF_STMT(BPF_LD+BPF_MEM, 1), \ + jt, \ +- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */ ++ BPF_STMT(BPF_LD+BPF_MEM, 1) + + #define LOAD_SYSCALL_NR \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ diff --git a/queue-4.9/series b/queue-4.9/series index b4b6967aeaa..bb86a407c46 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -62,3 +62,16 @@ scsi-aacraid-reorder-adapter-status-check.patch scsi-use-scsi_device_from_queue-for-scsi_dh.patch power-reset-at91-poweroff-timely-shutdown-lpddr-memories.patch fix-disable-sys_membarrier-when-nohz_full-is-enabled.patch +jbd2-don-t-leak-modified-metadata-buffers-on-an-aborted-journal.patch +block-loop-fix-race-between-i-o-and-set_status.patch +loop-fix-lo_flags_partscan-hang.patch +ext4-include-forgotten-start-block-on-fallocate-insert-range.patch +ext4-do-not-polute-the-extents-cache-while-shifting-extents.patch +ext4-trim-allocation-requests-to-group-size.patch +ext4-fix-data-corruption-in-data-journal-mode.patch +ext4-fix-use-after-iput-when-fscrypt-contexts-are-inconsistent.patch +ext4-fix-inline-data-error-paths.patch +ext4-preserve-the-needs_recovery-flag-when-the-journal-is-aborted.patch +ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch +samples-seccomp-fix-64-bit-comparison-macros.patch +mei-remove-support-for-broken-parallel-read.patch