From 70f4fc9b68297f37f0649a6c9d34d6f546543c05 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Mar 2015 16:13:51 +0100 Subject: [PATCH] 3.14-stable patches added patches: btrfs-__add_inode_ref-out-of-bounds-memory-read-when-looking-for-extended-ref.patch btrfs-fix-data-loss-in-the-fast-fsync-path.patch btrfs-fix-lost-return-value-due-to-variable-shadowing.patch kvm-emulate-fix-cmpxchg8b-on-32-bit-hosts.patch kvm-mips-fix-trace-event-to-save-pc-directly.patch mei-make-device-disabled-on-stop-unconditionally.patch --- ...y-read-when-looking-for-extended-ref.patch | 32 +++ ...fix-data-loss-in-the-fast-fsync-path.patch | 255 ++++++++++++++++++ ...turn-value-due-to-variable-shadowing.patch | 31 +++ ...mulate-fix-cmpxchg8b-on-32-bit-hosts.patch | 42 +++ ...-fix-trace-event-to-save-pc-directly.patch | 63 +++++ ...ice-disabled-on-stop-unconditionally.patch | 32 +++ queue-3.14/series | 6 + 7 files changed, 461 insertions(+) create mode 100644 queue-3.14/btrfs-__add_inode_ref-out-of-bounds-memory-read-when-looking-for-extended-ref.patch create mode 100644 queue-3.14/btrfs-fix-data-loss-in-the-fast-fsync-path.patch create mode 100644 queue-3.14/btrfs-fix-lost-return-value-due-to-variable-shadowing.patch create mode 100644 queue-3.14/kvm-emulate-fix-cmpxchg8b-on-32-bit-hosts.patch create mode 100644 queue-3.14/kvm-mips-fix-trace-event-to-save-pc-directly.patch create mode 100644 queue-3.14/mei-make-device-disabled-on-stop-unconditionally.patch diff --git a/queue-3.14/btrfs-__add_inode_ref-out-of-bounds-memory-read-when-looking-for-extended-ref.patch b/queue-3.14/btrfs-__add_inode_ref-out-of-bounds-memory-read-when-looking-for-extended-ref.patch new file mode 100644 index 00000000000..d65b1b2fd98 --- /dev/null +++ b/queue-3.14/btrfs-__add_inode_ref-out-of-bounds-memory-read-when-looking-for-extended-ref.patch @@ -0,0 +1,32 @@ +From dd9ef135e3542ffc621c4eb7f0091870ec7a1504 Mon Sep 17 00:00:00 2001 +From: Quentin Casasnovas +Date: Tue, 3 Mar 2015 16:31:38 +0100 +Subject: Btrfs:__add_inode_ref: out of bounds memory read when looking for extended ref. + +From: Quentin Casasnovas + +commit dd9ef135e3542ffc621c4eb7f0091870ec7a1504 upstream. + +Improper arithmetics when calculting the address of the extended ref could +lead to an out of bounds memory read and kernel panic. + +Signed-off-by: Quentin Casasnovas +Reviewed-by: David Sterba +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -979,7 +979,7 @@ again: + base = btrfs_item_ptr_offset(leaf, path->slots[0]); + + while (cur_offset < item_size) { +- extref = (struct btrfs_inode_extref *)base + cur_offset; ++ extref = (struct btrfs_inode_extref *)(base + cur_offset); + + victim_name_len = btrfs_inode_extref_name_len(leaf, extref); + diff --git a/queue-3.14/btrfs-fix-data-loss-in-the-fast-fsync-path.patch b/queue-3.14/btrfs-fix-data-loss-in-the-fast-fsync-path.patch new file mode 100644 index 00000000000..cfa3879f4c0 --- /dev/null +++ b/queue-3.14/btrfs-fix-data-loss-in-the-fast-fsync-path.patch @@ -0,0 +1,255 @@ +From 3a8b36f378060d20062a0918e99fae39ff077bf0 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Sun, 1 Mar 2015 20:36:00 +0000 +Subject: Btrfs: fix data loss in the fast fsync path + +From: Filipe Manana + +commit 3a8b36f378060d20062a0918e99fae39ff077bf0 upstream. + +When using the fast file fsync code path we can miss the fact that new +writes happened since the last file fsync and therefore return without +waiting for the IO to finish and write the new extents to the fsync log. + +Here's an example scenario where the fsync will miss the fact that new +file data exists that wasn't yet durably persisted: + +1. fs_info->last_trans_committed == N - 1 and current transaction is + transaction N (fs_info->generation == N); + +2. do a buffered write; + +3. fsync our inode, this clears our inode's full sync flag, starts + an ordered extent and waits for it to complete - when it completes + at btrfs_finish_ordered_io(), the inode's last_trans is set to the + value N (via btrfs_update_inode_fallback -> btrfs_update_inode -> + btrfs_set_inode_last_trans); + +4. transaction N is committed, so fs_info->last_trans_committed is now + set to the value N and fs_info->generation remains with the value N; + +5. do another buffered write, when this happens btrfs_file_write_iter + sets our inode's last_trans to the value N + 1 (that is + fs_info->generation + 1 == N + 1); + +6. transaction N + 1 is started and fs_info->generation now has the + value N + 1; + +7. transaction N + 1 is committed, so fs_info->last_trans_committed + is set to the value N + 1; + +8. fsync our inode - because it doesn't have the full sync flag set, + we only start the ordered extent, we don't wait for it to complete + (only in a later phase) therefore its last_trans field has the + value N + 1 set previously by btrfs_file_write_iter(), and so we + have: + + inode->last_trans <= fs_info->last_trans_committed + (N + 1) (N + 1) + + Which made us not log the last buffered write and exit the fsync + handler immediately, returning success (0) to user space and resulting + in data loss after a crash. + +This can actually be triggered deterministically and the following excerpt +from a testcase I made for xfstests triggers the issue. It moves a dummy +file across directories and then fsyncs the old parent directory - this +is just to trigger a transaction commit, so moving files around isn't +directly related to the issue but it was chosen because running 'sync' for +example does more than just committing the current transaction, as it +flushes/waits for all file data to be persisted. The issue can also happen +at random periods, since the transaction kthread periodicaly commits the +current transaction (about every 30 seconds by default). +The body of the test is: + + _scratch_mkfs >> $seqres.full 2>&1 + _init_flakey + _mount_flakey + + # Create our main test file 'foo', the one we check for data loss. + # By doing an fsync against our file, it makes btrfs clear the 'needs_full_sync' + # bit from its flags (btrfs inode specific flags). + $XFS_IO_PROG -f -c "pwrite -S 0xaa 0 8K" \ + -c "fsync" $SCRATCH_MNT/foo | _filter_xfs_io + + # Now create one other file and 2 directories. We will move this second file + # from one directory to the other later because it forces btrfs to commit its + # currently open transaction if we fsync the old parent directory. This is + # necessary to trigger the data loss bug that affected btrfs. + mkdir $SCRATCH_MNT/testdir_1 + touch $SCRATCH_MNT/testdir_1/bar + mkdir $SCRATCH_MNT/testdir_2 + + # Make sure everything is durably persisted. + sync + + # Write more 8Kb of data to our file. + $XFS_IO_PROG -c "pwrite -S 0xbb 8K 8K" $SCRATCH_MNT/foo | _filter_xfs_io + + # Move our 'bar' file into a new directory. + mv $SCRATCH_MNT/testdir_1/bar $SCRATCH_MNT/testdir_2/bar + + # Fsync our first directory. Because it had a file moved into some other + # directory, this made btrfs commit the currently open transaction. This is + # a condition necessary to trigger the data loss bug. + $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/testdir_1 + + # Now fsync our main test file. If the fsync succeeds, we expect the 8Kb of + # data we wrote previously to be persisted and available if a crash happens. + # This did not happen with btrfs, because of the transaction commit that + # happened when we fsynced the parent directory. + $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/foo + + # Simulate a crash/power loss. + _load_flakey_table $FLAKEY_DROP_WRITES + _unmount_flakey + + _load_flakey_table $FLAKEY_ALLOW_WRITES + _mount_flakey + + # Now check that all data we wrote before are available. + echo "File content after log replay:" + od -t x1 $SCRATCH_MNT/foo + + status=0 + exit + +The expected golden output for the test, which is what we get with this +fix applied (or when running against ext3/4 and xfs), is: + + wrote 8192/8192 bytes at offset 0 + XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 8192/8192 bytes at offset 8192 + XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + File content after log replay: + 0000000 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa + * + 0020000 bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb bb + * + 0040000 + +Without this fix applied, the output shows the test file does not have +the second 8Kb extent that we successfully fsynced: + + wrote 8192/8192 bytes at offset 0 + XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + wrote 8192/8192 bytes at offset 8192 + XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + File content after log replay: + 0000000 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa + * + 0020000 + +So fix this by skipping the fsync only if we're doing a full sync and +if the inode's last_trans is <= fs_info->last_trans_committed, or if +the inode is already in the log. Also remove setting the inode's +last_trans in btrfs_file_write_iter since it's useless/unreliable. + +Also because btrfs_file_write_iter no longer sets inode->last_trans to +fs_info->generation + 1, don't set last_trans to 0 if we bail out and don't +bail out if last_trans is 0, otherwise something as simple as the following +example wouldn't log the second write on the last fsync: + + 1. write to file + + 2. fsync file + + 3. fsync file + |--> btrfs_inode_in_log() returns true and it set last_trans to 0 + + 4. write to file + |--> btrfs_file_write_iter() no longers sets last_trans, so it + remained with a value of 0 + 5. fsync + |--> inode->last_trans == 0, so it bails out without logging the + second write + +A test case for xfstests will be sent soon. + +Signed-off-by: Filipe Manana +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/file.c | 56 ++++++++++++++++++++++++++++---------------------------- + 1 file changed, 28 insertions(+), 28 deletions(-) + +--- a/fs/btrfs/file.c ++++ b/fs/btrfs/file.c +@@ -1774,22 +1774,10 @@ static ssize_t btrfs_file_aio_write(stru + mutex_unlock(&inode->i_mutex); + + /* +- * we want to make sure fsync finds this change +- * but we haven't joined a transaction running right now. +- * +- * Later on, someone is sure to update the inode and get the +- * real transid recorded. +- * +- * We set last_trans now to the fs_info generation + 1, +- * this will either be one more than the running transaction +- * or the generation used for the next transaction if there isn't +- * one running right now. +- * + * We also have to set last_sub_trans to the current log transid, + * otherwise subsequent syncs to a file that's been synced in this + * transaction will appear to have already occured. + */ +- BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; + BTRFS_I(inode)->last_sub_trans = root->log_transid; + if (num_written > 0) { + err = generic_write_sync(file, pos, num_written); +@@ -1892,25 +1880,37 @@ int btrfs_sync_file(struct file *file, l + atomic_inc(&root->log_batch); + + /* +- * check the transaction that last modified this inode +- * and see if its already been committed +- */ +- if (!BTRFS_I(inode)->last_trans) { +- mutex_unlock(&inode->i_mutex); +- goto out; +- } +- +- /* +- * if the last transaction that changed this file was before +- * the current transaction, we can bail out now without any +- * syncing ++ * If the last transaction that changed this file was before the current ++ * transaction and we have the full sync flag set in our inode, we can ++ * bail out now without any syncing. ++ * ++ * Note that we can't bail out if the full sync flag isn't set. This is ++ * because when the full sync flag is set we start all ordered extents ++ * and wait for them to fully complete - when they complete they update ++ * the inode's last_trans field through: ++ * ++ * btrfs_finish_ordered_io() -> ++ * btrfs_update_inode_fallback() -> ++ * btrfs_update_inode() -> ++ * btrfs_set_inode_last_trans() ++ * ++ * So we are sure that last_trans is up to date and can do this check to ++ * bail out safely. For the fast path, when the full sync flag is not ++ * set in our inode, we can not do it because we start only our ordered ++ * extents and don't wait for them to complete (that is when ++ * btrfs_finish_ordered_io runs), so here at this point their last_trans ++ * value might be less than or equals to fs_info->last_trans_committed, ++ * and setting a speculative last_trans for an inode when a buffered ++ * write is made (such as fs_info->generation + 1 for example) would not ++ * be reliable since after setting the value and before fsync is called ++ * any number of transactions can start and commit (transaction kthread ++ * commits the current transaction periodically), and a transaction ++ * commit does not start nor waits for ordered extents to complete. + */ + smp_mb(); + if (btrfs_inode_in_log(inode, root->fs_info->generation) || +- BTRFS_I(inode)->last_trans <= +- root->fs_info->last_trans_committed) { +- BTRFS_I(inode)->last_trans = 0; +- ++ (full_sync && BTRFS_I(inode)->last_trans <= ++ root->fs_info->last_trans_committed)) { + /* + * We'v had everything committed since the last time we were + * modified so clear this flag in case it was set for whatever diff --git a/queue-3.14/btrfs-fix-lost-return-value-due-to-variable-shadowing.patch b/queue-3.14/btrfs-fix-lost-return-value-due-to-variable-shadowing.patch new file mode 100644 index 00000000000..d6417b747f8 --- /dev/null +++ b/queue-3.14/btrfs-fix-lost-return-value-due-to-variable-shadowing.patch @@ -0,0 +1,31 @@ +From 1932b7be973b554ffe20a5bba6ffaed6fa995cdc Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Tue, 24 Feb 2015 18:57:18 +0100 +Subject: btrfs: fix lost return value due to variable shadowing + +From: David Sterba + +commit 1932b7be973b554ffe20a5bba6ffaed6fa995cdc upstream. + +A block-local variable stores error code but btrfs_get_blocks_direct may +not return it in the end as there's a ret defined in the function scope. + +Fixes: d187663ef24c ("Btrfs: lock extents as we map them in DIO") +Signed-off-by: David Sterba +Signed-off-by: Chris Mason +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/inode.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -6870,7 +6870,6 @@ static int btrfs_get_blocks_direct(struc + ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) && + em->block_start != EXTENT_MAP_HOLE)) { + int type; +- int ret; + u64 block_start, orig_start, orig_block_len, ram_bytes; + + if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) diff --git a/queue-3.14/kvm-emulate-fix-cmpxchg8b-on-32-bit-hosts.patch b/queue-3.14/kvm-emulate-fix-cmpxchg8b-on-32-bit-hosts.patch new file mode 100644 index 00000000000..b1c7c04115b --- /dev/null +++ b/queue-3.14/kvm-emulate-fix-cmpxchg8b-on-32-bit-hosts.patch @@ -0,0 +1,42 @@ +From 4ff6f8e61eb7f96d3ca535c6d240f863ccd6fb7d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 12 Feb 2015 17:04:47 +0100 +Subject: KVM: emulate: fix CMPXCHG8B on 32-bit hosts + +From: Paolo Bonzini + +commit 4ff6f8e61eb7f96d3ca535c6d240f863ccd6fb7d upstream. + +This has been broken for a long time: it broke first in 2.6.35, then was +almost fixed in 2.6.36 but this one-liner slipped through the cracks. +The bug shows up as an infinite loop in Windows 7 (and newer) boot on +32-bit hosts without EPT. + +Windows uses CMPXCHG8B to write to page tables, which causes a +page fault if running without EPT; the emulator is then called from +kvm_mmu_page_fault. The loop then happens if the higher 4 bytes are +not 0; the common case for this is that the NX bit (bit 63) is 1. + +Fixes: 6550e1f165f384f3a46b60a1be9aba4bc3c2adad +Fixes: 16518d5ada690643453eb0aef3cc7841d3623c2d +Reported-by: Erik Rull +Tested-by: Erik Rull +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/emulate.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/x86/kvm/emulate.c ++++ b/arch/x86/kvm/emulate.c +@@ -4646,7 +4646,8 @@ int x86_emulate_insn(struct x86_emulate_ + if (rc != X86EMUL_CONTINUE) + goto done; + } +- ctxt->dst.orig_val = ctxt->dst.val; ++ /* Copy full 64-bit value for CMPXCHG8B. */ ++ ctxt->dst.orig_val64 = ctxt->dst.val64; + + special_insn: + diff --git a/queue-3.14/kvm-mips-fix-trace-event-to-save-pc-directly.patch b/queue-3.14/kvm-mips-fix-trace-event-to-save-pc-directly.patch new file mode 100644 index 00000000000..0864bee04d3 --- /dev/null +++ b/queue-3.14/kvm-mips-fix-trace-event-to-save-pc-directly.patch @@ -0,0 +1,63 @@ +From b3cffac04eca9af46e1e23560a8ee22b1bd36d43 Mon Sep 17 00:00:00 2001 +From: James Hogan +Date: Tue, 24 Feb 2015 11:46:20 +0000 +Subject: KVM: MIPS: Fix trace event to save PC directly + +From: James Hogan + +commit b3cffac04eca9af46e1e23560a8ee22b1bd36d43 upstream. + +Currently the guest exit trace event saves the VCPU pointer to the +structure, and the guest PC is retrieved by dereferencing it when the +event is printed rather than directly from the trace record. This isn't +safe as the printing may occur long afterwards, after the PC has changed +and potentially after the VCPU has been freed. Usually this results in +the same (wrong) PC being printed for multiple trace events. It also +isn't portable as userland has no way to access the VCPU data structure +when interpreting the trace record itself. + +Lets save the actual PC in the structure so that the correct value is +accessible later. + +Fixes: 669e846e6c4e ("KVM/MIPS32: MIPS arch specific APIs for KVM") +Signed-off-by: James Hogan +Cc: Paolo Bonzini +Cc: Ralf Baechle +Cc: Marcelo Tosatti +Cc: Gleb Natapov +Cc: Steven Rostedt +Cc: Ingo Molnar +Cc: linux-mips@linux-mips.org +Cc: kvm@vger.kernel.org +Acked-by: Steven Rostedt +Signed-off-by: Marcelo Tosatti +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/kvm/trace.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/mips/kvm/trace.h ++++ b/arch/mips/kvm/trace.h +@@ -26,18 +26,18 @@ TRACE_EVENT(kvm_exit, + TP_PROTO(struct kvm_vcpu *vcpu, unsigned int reason), + TP_ARGS(vcpu, reason), + TP_STRUCT__entry( +- __field(struct kvm_vcpu *, vcpu) ++ __field(unsigned long, pc) + __field(unsigned int, reason) + ), + + TP_fast_assign( +- __entry->vcpu = vcpu; ++ __entry->pc = vcpu->arch.pc; + __entry->reason = reason; + ), + + TP_printk("[%s]PC: 0x%08lx", + kvm_mips_exit_types_str[__entry->reason], +- __entry->vcpu->arch.pc) ++ __entry->pc) + ); + + #endif /* _TRACE_KVM_H */ diff --git a/queue-3.14/mei-make-device-disabled-on-stop-unconditionally.patch b/queue-3.14/mei-make-device-disabled-on-stop-unconditionally.patch new file mode 100644 index 00000000000..0c5dba31d86 --- /dev/null +++ b/queue-3.14/mei-make-device-disabled-on-stop-unconditionally.patch @@ -0,0 +1,32 @@ +From 6c15a8516b8118eb19a59fd0bd22df41b9101c32 Mon Sep 17 00:00:00 2001 +From: Alexander Usyskin +Date: Tue, 10 Feb 2015 10:36:36 +0200 +Subject: mei: make device disabled on stop unconditionally + +From: Alexander Usyskin + +commit 6c15a8516b8118eb19a59fd0bd22df41b9101c32 upstream. + +Set the internal device state to to disabled after hardware reset in stop flow. +This will cover cases when driver was not brought to disabled state because of +an error and in stop flow we wish not to retry the reset. + +Signed-off-by: Alexander Usyskin +Signed-off-by: Tomas Winkler +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/mei/init.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/misc/mei/init.c ++++ b/drivers/misc/mei/init.c +@@ -275,6 +275,8 @@ void mei_stop(struct mei_device *dev) + + dev->dev_state = MEI_DEV_POWER_DOWN; + mei_reset(dev); ++ /* move device to disabled state unconditionally */ ++ dev->dev_state = MEI_DEV_DISABLED; + + mutex_unlock(&dev->device_lock); + diff --git a/queue-3.14/series b/queue-3.14/series index 1e6cf08b1d9..60d581da6bd 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -37,3 +37,9 @@ iio-mxs-lradc-make-adc-reads-not-unschedule-touchscreen-conversions.patch iio-mxs-lradc-only-update-the-buffer-when-its-conversions-have-finished.patch iio-ad5686-fix-optional-reference-voltage-declaration.patch iio-adc-mcp3422-fix-incorrect-scales-table.patch +mei-make-device-disabled-on-stop-unconditionally.patch +btrfs-fix-lost-return-value-due-to-variable-shadowing.patch +btrfs-fix-data-loss-in-the-fast-fsync-path.patch +btrfs-__add_inode_ref-out-of-bounds-memory-read-when-looking-for-extended-ref.patch +kvm-emulate-fix-cmpxchg8b-on-32-bit-hosts.patch +kvm-mips-fix-trace-event-to-save-pc-directly.patch -- 2.47.3