From: Greg Kroah-Hartman Date: Tue, 8 Nov 2016 16:30:17 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v4.4.31~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=58ebff3c423f65b2d02f302b8310145d6e70a12d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: dm-mirror-fix-read-error-on-recovery-after-default-leg-failure.patch firewire-net-fix-fragmented-datagram_size-off-by-one.patch firewire-net-guard-against-rx-buffer-overflows.patch input-i8042-add-xmg-c504-to-keyboard-reset-table.patch kvm-mips-make-eret-handle-erl-before-exl.patch kvm-x86-fix-wbinvd_dirty_mask-use-after-free.patch ovl-fsync-after-copy-up.patch parisc-ensure-consistent-state-when-switching-to-kernel-stack-at-syscall-entry.patch virtio-console-unlock-vqs-while-freeing-buffers.patch virtio_ring-make-interrupt-suppression-spec-compliant.patch --- diff --git a/queue-4.4/dm-mirror-fix-read-error-on-recovery-after-default-leg-failure.patch b/queue-4.4/dm-mirror-fix-read-error-on-recovery-after-default-leg-failure.patch new file mode 100644 index 00000000000..bf30e144124 --- /dev/null +++ b/queue-4.4/dm-mirror-fix-read-error-on-recovery-after-default-leg-failure.patch @@ -0,0 +1,36 @@ +From dcb2ff56417362c31f6b430c3c531a84581e8721 Mon Sep 17 00:00:00 2001 +From: Heinz Mauelshagen +Date: Mon, 10 Oct 2016 17:58:32 +0200 +Subject: dm mirror: fix read error on recovery after default leg failure + +From: Heinz Mauelshagen + +commit dcb2ff56417362c31f6b430c3c531a84581e8721 upstream. + +If a default leg has failed, any read will cause a new operational +default leg to be selected and the read is resubmitted. But until now +the read will return failure even though it was successful due to +resubmission. The reason for this is bio->bi_error was not being +cleared before resubmitting the bio. + +Fix by clearing bio->bi_error before resubmission. + +Fixes: 4246a0b63bd8 ("block: add a bi_error field to struct bio") +Signed-off-by: Heinz Mauelshagen +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-raid1.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/md/dm-raid1.c ++++ b/drivers/md/dm-raid1.c +@@ -1288,6 +1288,7 @@ static int mirror_end_io(struct dm_targe + + dm_bio_restore(bd, bio); + bio_record->details.bi_bdev = NULL; ++ bio->bi_error = 0; + + queue_bio(ms, bio, rw); + return DM_ENDIO_INCOMPLETE; diff --git a/queue-4.4/firewire-net-fix-fragmented-datagram_size-off-by-one.patch b/queue-4.4/firewire-net-fix-fragmented-datagram_size-off-by-one.patch new file mode 100644 index 00000000000..5068a347916 --- /dev/null +++ b/queue-4.4/firewire-net-fix-fragmented-datagram_size-off-by-one.patch @@ -0,0 +1,86 @@ +From e9300a4b7bbae83af1f7703938c94cf6dc6d308f Mon Sep 17 00:00:00 2001 +From: Stefan Richter +Date: Sun, 30 Oct 2016 17:32:01 +0100 +Subject: firewire: net: fix fragmented datagram_size off-by-one + +From: Stefan Richter + +commit e9300a4b7bbae83af1f7703938c94cf6dc6d308f upstream. + +RFC 2734 defines the datagram_size field in fragment encapsulation +headers thus: + + datagram_size: The encoded size of the entire IP datagram. The + value of datagram_size [...] SHALL be one less than the value of + Total Length in the datagram's IP header (see STD 5, RFC 791). + +Accordingly, the eth1394 driver of Linux 2.6.36 and older set and got +this field with a -/+1 offset: + + ether1394_tx() /* transmit */ + ether1394_encapsulate_prep() + hdr->ff.dg_size = dg_size - 1; + + ether1394_data_handler() /* receive */ + if (hdr->common.lf == ETH1394_HDR_LF_FF) + dg_size = hdr->ff.dg_size + 1; + else + dg_size = hdr->sf.dg_size + 1; + +Likewise, I observe OS X 10.4 and Windows XP Pro SP3 to transmit 1500 +byte sized datagrams in fragments with datagram_size=1499 if link +fragmentation is required. + +Only firewire-net sets and gets datagram_size without this offset. The +result is lacking interoperability of firewire-net with OS X, Windows +XP, and presumably Linux' eth1394. (I did not test with the latter.) +For example, FTP data transfers to a Linux firewire-net box with max_rec +smaller than the 1500 bytes MTU + - from OS X fail entirely, + - from Win XP start out with a bunch of fragmented datagrams which + time out, then continue with unfragmented datagrams because Win XP + temporarily reduces the MTU to 576 bytes. + +So let's fix firewire-net's datagram_size accessors. + +Note that firewire-net thereby loses interoperability with unpatched +firewire-net, but only if link fragmentation is employed. (This happens +with large broadcast datagrams, and with large datagrams on several +FireWire CardBus cards with smaller max_rec than equivalent PCI cards, +and it can be worked around by setting a small enough MTU.) + +Signed-off-by: Stefan Richter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firewire/net.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -73,13 +73,13 @@ struct rfc2734_header { + + #define fwnet_get_hdr_lf(h) (((h)->w0 & 0xc0000000) >> 30) + #define fwnet_get_hdr_ether_type(h) (((h)->w0 & 0x0000ffff)) +-#define fwnet_get_hdr_dg_size(h) (((h)->w0 & 0x0fff0000) >> 16) ++#define fwnet_get_hdr_dg_size(h) ((((h)->w0 & 0x0fff0000) >> 16) + 1) + #define fwnet_get_hdr_fg_off(h) (((h)->w0 & 0x00000fff)) + #define fwnet_get_hdr_dgl(h) (((h)->w1 & 0xffff0000) >> 16) + +-#define fwnet_set_hdr_lf(lf) ((lf) << 30) ++#define fwnet_set_hdr_lf(lf) ((lf) << 30) + #define fwnet_set_hdr_ether_type(et) (et) +-#define fwnet_set_hdr_dg_size(dgs) ((dgs) << 16) ++#define fwnet_set_hdr_dg_size(dgs) (((dgs) - 1) << 16) + #define fwnet_set_hdr_fg_off(fgo) (fgo) + + #define fwnet_set_hdr_dgl(dgl) ((dgl) << 16) +@@ -622,7 +622,7 @@ static int fwnet_incoming_packet(struct + fg_off = fwnet_get_hdr_fg_off(&hdr); + } + datagram_label = fwnet_get_hdr_dgl(&hdr); +- dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ ++ dg_size = fwnet_get_hdr_dg_size(&hdr); + + if (fg_off + len > dg_size) + return 0; diff --git a/queue-4.4/firewire-net-guard-against-rx-buffer-overflows.patch b/queue-4.4/firewire-net-guard-against-rx-buffer-overflows.patch new file mode 100644 index 00000000000..c508c5cec84 --- /dev/null +++ b/queue-4.4/firewire-net-guard-against-rx-buffer-overflows.patch @@ -0,0 +1,131 @@ +From 667121ace9dbafb368618dbabcf07901c962ddac Mon Sep 17 00:00:00 2001 +From: Stefan Richter +Date: Sat, 29 Oct 2016 21:28:18 +0200 +Subject: firewire: net: guard against rx buffer overflows + +From: Stefan Richter + +commit 667121ace9dbafb368618dbabcf07901c962ddac upstream. + +The IP-over-1394 driver firewire-net lacked input validation when +handling incoming fragmented datagrams. A maliciously formed fragment +with a respectively large datagram_offset would cause a memcpy past the +datagram buffer. + +So, drop any packets carrying a fragment with offset + length larger +than datagram_size. + +In addition, ensure that + - GASP header, unfragmented encapsulation header, or fragment + encapsulation header actually exists before we access it, + - the encapsulated datagram or fragment is of nonzero size. + +Reported-by: Eyal Itkin +Reviewed-by: Eyal Itkin +Fixes: CVE 2016-8633 +Signed-off-by: Stefan Richter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firewire/net.c | 51 +++++++++++++++++++++++++++++++++---------------- + 1 file changed, 35 insertions(+), 16 deletions(-) + +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -578,6 +578,9 @@ static int fwnet_incoming_packet(struct + int retval; + u16 ether_type; + ++ if (len <= RFC2374_UNFRAG_HDR_SIZE) ++ return 0; ++ + hdr.w0 = be32_to_cpu(buf[0]); + lf = fwnet_get_hdr_lf(&hdr); + if (lf == RFC2374_HDR_UNFRAG) { +@@ -602,7 +605,12 @@ static int fwnet_incoming_packet(struct + return fwnet_finish_incoming_packet(net, skb, source_node_id, + is_broadcast, ether_type); + } ++ + /* A datagram fragment has been received, now the fun begins. */ ++ ++ if (len <= RFC2374_FRAG_HDR_SIZE) ++ return 0; ++ + hdr.w1 = ntohl(buf[1]); + buf += 2; + len -= RFC2374_FRAG_HDR_SIZE; +@@ -616,6 +624,9 @@ static int fwnet_incoming_packet(struct + datagram_label = fwnet_get_hdr_dgl(&hdr); + dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ + ++ if (fg_off + len > dg_size) ++ return 0; ++ + spin_lock_irqsave(&dev->lock, flags); + + peer = fwnet_peer_find_by_node_id(dev, source_node_id, generation); +@@ -722,6 +733,22 @@ static void fwnet_receive_packet(struct + fw_send_response(card, r, rcode); + } + ++static int gasp_source_id(__be32 *p) ++{ ++ return be32_to_cpu(p[0]) >> 16; ++} ++ ++static u32 gasp_specifier_id(__be32 *p) ++{ ++ return (be32_to_cpu(p[0]) & 0xffff) << 8 | ++ (be32_to_cpu(p[1]) & 0xff000000) >> 24; ++} ++ ++static u32 gasp_version(__be32 *p) ++{ ++ return be32_to_cpu(p[1]) & 0xffffff; ++} ++ + static void fwnet_receive_broadcast(struct fw_iso_context *context, + u32 cycle, size_t header_length, void *header, void *data) + { +@@ -731,9 +758,6 @@ static void fwnet_receive_broadcast(stru + __be32 *buf_ptr; + int retval; + u32 length; +- u16 source_node_id; +- u32 specifier_id; +- u32 ver; + unsigned long offset; + unsigned long flags; + +@@ -750,22 +774,17 @@ static void fwnet_receive_broadcast(stru + + spin_unlock_irqrestore(&dev->lock, flags); + +- specifier_id = (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8 +- | (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24; +- ver = be32_to_cpu(buf_ptr[1]) & 0xffffff; +- source_node_id = be32_to_cpu(buf_ptr[0]) >> 16; +- +- if (specifier_id == IANA_SPECIFIER_ID && +- (ver == RFC2734_SW_VERSION ++ if (length > IEEE1394_GASP_HDR_SIZE && ++ gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID && ++ (gasp_version(buf_ptr) == RFC2734_SW_VERSION + #if IS_ENABLED(CONFIG_IPV6) +- || ver == RFC3146_SW_VERSION ++ || gasp_version(buf_ptr) == RFC3146_SW_VERSION + #endif +- )) { +- buf_ptr += 2; +- length -= IEEE1394_GASP_HDR_SIZE; +- fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, ++ )) ++ fwnet_incoming_packet(dev, buf_ptr + 2, ++ length - IEEE1394_GASP_HDR_SIZE, ++ gasp_source_id(buf_ptr), + context->card->generation, true); +- } + + packet.payload_length = dev->rcv_buffer_size; + packet.interrupt = 1; diff --git a/queue-4.4/input-i8042-add-xmg-c504-to-keyboard-reset-table.patch b/queue-4.4/input-i8042-add-xmg-c504-to-keyboard-reset-table.patch new file mode 100644 index 00000000000..73ab8b95a77 --- /dev/null +++ b/queue-4.4/input-i8042-add-xmg-c504-to-keyboard-reset-table.patch @@ -0,0 +1,51 @@ +From da25311c7ca8b0254a686fc0d597075b9aa3b683 Mon Sep 17 00:00:00 2001 +From: Patrick Scheuring +Date: Wed, 19 Oct 2016 12:04:02 -0700 +Subject: Input: i8042 - add XMG C504 to keyboard reset table + +From: Patrick Scheuring + +commit da25311c7ca8b0254a686fc0d597075b9aa3b683 upstream. + +The Schenker XMG C504 is a rebranded Gigabyte P35 v2 laptop. +Therefore it also needs a keyboard reset to detect the Elantech touchpad. +Otherwise the touchpad appears to be dead. + +With this patch the touchpad is detected: + +$ dmesg | grep -E "(i8042|Elantech|elantech)" + +[ 2.675399] i8042: PNP: PS/2 Controller [PNP0303:PS2K,PNP0f13:PS2M] at 0x60,0x64 irq 1,12 +[ 2.680372] i8042: Attempting to reset device connected to KBD port +[ 2.789037] serio: i8042 KBD port at 0x60,0x64 irq 1 +[ 2.791586] serio: i8042 AUX port at 0x60,0x64 irq 12 +[ 2.813840] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input4 +[ 3.811431] psmouse serio1: elantech: assuming hardware version 4 (with firmware version 0x361f0e) +[ 3.825424] psmouse serio1: elantech: Synaptics capabilities query result 0x00, 0x15, 0x0f. +[ 3.839424] psmouse serio1: elantech: Elan sample query result 03, 58, 74 +[ 3.911349] input: ETPS/2 Elantech Touchpad as /devices/platform/i8042/serio1/input/input6 + +Signed-off-by: Patrick Scheuring +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -877,6 +877,13 @@ static const struct dmi_system_id __init + DMI_MATCH(DMI_PRODUCT_NAME, "P34"), + }, + }, ++ { ++ /* Schenker XMG C504 - Elantech touchpad */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "XMG"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "C504"), ++ }, ++ }, + { } + }; + diff --git a/queue-4.4/kvm-mips-make-eret-handle-erl-before-exl.patch b/queue-4.4/kvm-mips-make-eret-handle-erl-before-exl.patch new file mode 100644 index 00000000000..8a79ad7a58a --- /dev/null +++ b/queue-4.4/kvm-mips-make-eret-handle-erl-before-exl.patch @@ -0,0 +1,57 @@ +From ede5f3e7b54a4347be4d8525269eae50902bd7cd Mon Sep 17 00:00:00 2001 +From: James Hogan +Date: Tue, 25 Oct 2016 16:11:11 +0100 +Subject: KVM: MIPS: Make ERET handle ERL before EXL +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: James Hogan + +commit ede5f3e7b54a4347be4d8525269eae50902bd7cd upstream. + +The ERET instruction to return from exception is used for returning from +exception level (Status.EXL) and error level (Status.ERL). If both bits +are set however we should be returning from ERL first, as ERL can +interrupt EXL, for example when an NMI is taken. KVM however checks EXL +first. + +Fix the order of the checks to match the pseudocode in the instruction +set manual. + +Fixes: e685c689f3a8 ("KVM/MIPS32: Privileged instruction/target branch emulation.") +Signed-off-by: James Hogan +Cc: Paolo Bonzini +Cc: "Radim Krčmář +Cc: Ralf Baechle +Cc: linux-mips@linux-mips.org +Cc: kvm@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/kvm/emulate.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/mips/kvm/emulate.c ++++ b/arch/mips/kvm/emulate.c +@@ -752,15 +752,15 @@ enum emulation_result kvm_mips_emul_eret + struct mips_coproc *cop0 = vcpu->arch.cop0; + enum emulation_result er = EMULATE_DONE; + +- if (kvm_read_c0_guest_status(cop0) & ST0_EXL) { ++ if (kvm_read_c0_guest_status(cop0) & ST0_ERL) { ++ kvm_clear_c0_guest_status(cop0, ST0_ERL); ++ vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0); ++ } else if (kvm_read_c0_guest_status(cop0) & ST0_EXL) { + kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc, + kvm_read_c0_guest_epc(cop0)); + kvm_clear_c0_guest_status(cop0, ST0_EXL); + vcpu->arch.pc = kvm_read_c0_guest_epc(cop0); + +- } else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) { +- kvm_clear_c0_guest_status(cop0, ST0_ERL); +- vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0); + } else { + kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n", + vcpu->arch.pc); diff --git a/queue-4.4/kvm-x86-fix-wbinvd_dirty_mask-use-after-free.patch b/queue-4.4/kvm-x86-fix-wbinvd_dirty_mask-use-after-free.patch new file mode 100644 index 00000000000..f554081814b --- /dev/null +++ b/queue-4.4/kvm-x86-fix-wbinvd_dirty_mask-use-after-free.patch @@ -0,0 +1,48 @@ +From bd768e146624cbec7122ed15dead8daa137d909d Mon Sep 17 00:00:00 2001 +From: Ido Yariv +Date: Fri, 21 Oct 2016 12:39:57 -0400 +Subject: KVM: x86: fix wbinvd_dirty_mask use-after-free +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ido Yariv + +commit bd768e146624cbec7122ed15dead8daa137d909d upstream. + +vcpu->arch.wbinvd_dirty_mask may still be used after freeing it, +corrupting memory. For example, the following call trace may set a bit +in an already freed cpu mask: + kvm_arch_vcpu_load + vcpu_load + vmx_free_vcpu_nested + vmx_free_vcpu + kvm_arch_vcpu_free + +Fix this by deferring freeing of wbinvd_dirty_mask. + +Signed-off-by: Ido Yariv +Reviewed-by: Paolo Bonzini +Signed-off-by: Radim Krčmář +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/x86.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -7252,10 +7252,12 @@ void kvm_put_guest_fpu(struct kvm_vcpu * + + void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) + { ++ void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask; ++ + kvmclock_reset(vcpu); + +- free_cpumask_var(vcpu->arch.wbinvd_dirty_mask); + kvm_x86_ops->vcpu_free(vcpu); ++ free_cpumask_var(wbinvd_dirty_mask); + } + + struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, diff --git a/queue-4.4/ovl-fsync-after-copy-up.patch b/queue-4.4/ovl-fsync-after-copy-up.patch new file mode 100644 index 00000000000..f42b5cf130a --- /dev/null +++ b/queue-4.4/ovl-fsync-after-copy-up.patch @@ -0,0 +1,31 @@ +From 641089c1549d8d3df0b047b5de7e9a111362cdce Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Mon, 31 Oct 2016 14:42:14 +0100 +Subject: ovl: fsync after copy-up + +From: Miklos Szeredi + +commit 641089c1549d8d3df0b047b5de7e9a111362cdce upstream. + +Make sure the copied up file hits the disk before renaming to the final +destination. If this is not done then the copy-up may corrupt the data in +the file in case of a crash. + +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/overlayfs/copy_up.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -139,6 +139,8 @@ static int ovl_copy_up_data(struct path + len -= bytes; + } + ++ if (!error) ++ error = vfs_fsync(new_file, 0); + fput(new_file); + out_fput: + fput(old_file); diff --git a/queue-4.4/parisc-ensure-consistent-state-when-switching-to-kernel-stack-at-syscall-entry.patch b/queue-4.4/parisc-ensure-consistent-state-when-switching-to-kernel-stack-at-syscall-entry.patch new file mode 100644 index 00000000000..c8274ba8da1 --- /dev/null +++ b/queue-4.4/parisc-ensure-consistent-state-when-switching-to-kernel-stack-at-syscall-entry.patch @@ -0,0 +1,64 @@ +From 6ed518328d0189e0fdf1bb7c73290d546143ea66 Mon Sep 17 00:00:00 2001 +From: John David Anglin +Date: Fri, 28 Oct 2016 23:00:34 -0400 +Subject: parisc: Ensure consistent state when switching to kernel stack at syscall entry + +From: John David Anglin + +commit 6ed518328d0189e0fdf1bb7c73290d546143ea66 upstream. + +We have one critical section in the syscall entry path in which we switch from +the userspace stack to kernel stack. In the event of an external interrupt, the +interrupt code distinguishes between those two states by analyzing the value of +sr7. If sr7 is zero, it uses the kernel stack. Therefore it's important, that +the value of sr7 is in sync with the currently enabled stack. + +This patch now disables interrupts while executing the critical section. This +prevents the interrupt handler to possibly see an inconsistent state which in +the worst case can lead to crashes. + +Interestingly, in the syscall exit path interrupts were already disabled in the +critical section which switches back to the userspace stack. + +Signed-off-by: John David Anglin +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + arch/parisc/kernel/syscall.S | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/arch/parisc/kernel/syscall.S ++++ b/arch/parisc/kernel/syscall.S +@@ -106,8 +106,6 @@ linux_gateway_entry: + mtsp %r0,%sr4 /* get kernel space into sr4 */ + mtsp %r0,%sr5 /* get kernel space into sr5 */ + mtsp %r0,%sr6 /* get kernel space into sr6 */ +- mfsp %sr7,%r1 /* save user sr7 */ +- mtsp %r1,%sr3 /* and store it in sr3 */ + + #ifdef CONFIG_64BIT + /* for now we can *always* set the W bit on entry to the syscall +@@ -133,6 +131,14 @@ linux_gateway_entry: + depdi 0, 31, 32, %r21 + 1: + #endif ++ ++ /* We use a rsm/ssm pair to prevent sr3 from being clobbered ++ * by external interrupts. ++ */ ++ mfsp %sr7,%r1 /* save user sr7 */ ++ rsm PSW_SM_I, %r0 /* disable interrupts */ ++ mtsp %r1,%sr3 /* and store it in sr3 */ ++ + mfctl %cr30,%r1 + xor %r1,%r30,%r30 /* ye olde xor trick */ + xor %r1,%r30,%r1 +@@ -147,6 +153,7 @@ linux_gateway_entry: + */ + + mtsp %r0,%sr7 /* get kernel space into sr7 */ ++ ssm PSW_SM_I, %r0 /* enable interrupts */ + STREGM %r1,FRAME_SIZE(%r30) /* save r1 (usp) here for now */ + mfctl %cr30,%r1 /* get task ptr in %r1 */ + LDREG TI_TASK(%r1),%r1 diff --git a/queue-4.4/series b/queue-4.4/series index 43bf7db72d5..ac97cc4ab4f 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -32,3 +32,13 @@ xhci-add-restart-quirk-for-intel-wildcatpoint-pch.patch tty-limit-terminal-size-to-4m-chars.patch usb-serial-cp210x-fix-tiocmget-error-handling.patch dm-free-io_barrier-after-blk_cleanup_queue-call.patch +kvm-x86-fix-wbinvd_dirty_mask-use-after-free.patch +kvm-mips-make-eret-handle-erl-before-exl.patch +ovl-fsync-after-copy-up.patch +parisc-ensure-consistent-state-when-switching-to-kernel-stack-at-syscall-entry.patch +virtio_ring-make-interrupt-suppression-spec-compliant.patch +virtio-console-unlock-vqs-while-freeing-buffers.patch +dm-mirror-fix-read-error-on-recovery-after-default-leg-failure.patch +input-i8042-add-xmg-c504-to-keyboard-reset-table.patch +firewire-net-guard-against-rx-buffer-overflows.patch +firewire-net-fix-fragmented-datagram_size-off-by-one.patch diff --git a/queue-4.4/virtio-console-unlock-vqs-while-freeing-buffers.patch b/queue-4.4/virtio-console-unlock-vqs-while-freeing-buffers.patch new file mode 100644 index 00000000000..a07432ade20 --- /dev/null +++ b/queue-4.4/virtio-console-unlock-vqs-while-freeing-buffers.patch @@ -0,0 +1,86 @@ +From 34563769e438d2881f62cf4d9badc4e589ac0ec0 Mon Sep 17 00:00:00 2001 +From: Matt Redfearn +Date: Tue, 11 Oct 2016 12:05:15 +0100 +Subject: virtio: console: Unlock vqs while freeing buffers + +From: Matt Redfearn + +commit 34563769e438d2881f62cf4d9badc4e589ac0ec0 upstream. + +Commit c6017e793b93 ("virtio: console: add locks around buffer removal +in port unplug path") added locking around the freeing of buffers in the +vq. However, when free_buf() is called with can_sleep = true and rproc +is enabled, it calls dma_free_coherent() directly, requiring interrupts +to be enabled. Currently a WARNING is triggered due to the spin locking +around free_buf, with a call stack like this: + +WARNING: CPU: 3 PID: 121 at ./include/linux/dma-mapping.h:433 +free_buf+0x1a8/0x288 +Call Trace: +[<8040c538>] show_stack+0x74/0xc0 +[<80757240>] dump_stack+0xd0/0x110 +[<80430d98>] __warn+0xfc/0x130 +[<80430ee0>] warn_slowpath_null+0x2c/0x3c +[<807e7c6c>] free_buf+0x1a8/0x288 +[<807ea590>] remove_port_data+0x50/0xac +[<807ea6a0>] unplug_port+0xb4/0x1bc +[<807ea858>] virtcons_remove+0xb0/0xfc +[<807b6734>] virtio_dev_remove+0x58/0xc0 +[<807f918c>] __device_release_driver+0xac/0x134 +[<807f924c>] device_release_driver+0x38/0x50 +[<807f7edc>] bus_remove_device+0xfc/0x130 +[<807f4b74>] device_del+0x17c/0x21c +[<807f4c38>] device_unregister+0x24/0x38 +[<807b6b50>] unregister_virtio_device+0x28/0x44 + +Fix this by restructuring the loops to allow the locks to only be taken +where it is necessary to protect the vqs, and release it while the +buffer is being freed. + +Fixes: c6017e793b93 ("virtio: console: add locks around buffer removal in port unplug path") +Signed-off-by: Matt Redfearn +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/virtio_console.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -1533,19 +1533,29 @@ static void remove_port_data(struct port + spin_lock_irq(&port->inbuf_lock); + /* Remove unused data this port might have received. */ + discard_port_data(port); ++ spin_unlock_irq(&port->inbuf_lock); + + /* Remove buffers we queued up for the Host to send us data in. */ +- while ((buf = virtqueue_detach_unused_buf(port->in_vq))) +- free_buf(buf, true); +- spin_unlock_irq(&port->inbuf_lock); ++ do { ++ spin_lock_irq(&port->inbuf_lock); ++ buf = virtqueue_detach_unused_buf(port->in_vq); ++ spin_unlock_irq(&port->inbuf_lock); ++ if (buf) ++ free_buf(buf, true); ++ } while (buf); + + spin_lock_irq(&port->outvq_lock); + reclaim_consumed_buffers(port); ++ spin_unlock_irq(&port->outvq_lock); + + /* Free pending buffers from the out-queue. */ +- while ((buf = virtqueue_detach_unused_buf(port->out_vq))) +- free_buf(buf, true); +- spin_unlock_irq(&port->outvq_lock); ++ do { ++ spin_lock_irq(&port->outvq_lock); ++ buf = virtqueue_detach_unused_buf(port->out_vq); ++ spin_unlock_irq(&port->outvq_lock); ++ if (buf) ++ free_buf(buf, true); ++ } while (buf); + } + + /* diff --git a/queue-4.4/virtio_ring-make-interrupt-suppression-spec-compliant.patch b/queue-4.4/virtio_ring-make-interrupt-suppression-spec-compliant.patch new file mode 100644 index 00000000000..39bf07a0d5a --- /dev/null +++ b/queue-4.4/virtio_ring-make-interrupt-suppression-spec-compliant.patch @@ -0,0 +1,71 @@ +From 0ea1e4a6d9b62cf29e210d2b4ba9fd43917522e3 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 31 Aug 2016 14:00:04 +0200 +Subject: virtio_ring: Make interrupt suppression spec compliant + +From: Ladi Prosek + +commit 0ea1e4a6d9b62cf29e210d2b4ba9fd43917522e3 upstream. + +According to the spec, if the VIRTIO_RING_F_EVENT_IDX feature bit is +negotiated the driver MUST set flags to 0. Not dirtying the available +ring in virtqueue_disable_cb also has a minor positive performance +impact, improving L1 dcache load missed by ~0.5% in vring_bench. + +Writes to the used event field (vring_used_event) are still unconditional. + +Cc: Michael S. Tsirkin +Signed-off-by: Ladi Prosek +Signed-off-by: Michael S. Tsirkin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/virtio/virtio_ring.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/drivers/virtio/virtio_ring.c ++++ b/drivers/virtio/virtio_ring.c +@@ -548,7 +548,8 @@ void virtqueue_disable_cb(struct virtque + + if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { + vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; +- vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); ++ if (!vq->event) ++ vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); + } + + } +@@ -580,7 +581,8 @@ unsigned virtqueue_enable_cb_prepare(str + * entry. Always do both to keep code simple. */ + if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { + vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; +- vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); ++ if (!vq->event) ++ vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); + } + vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx); + END_USE(vq); +@@ -648,10 +650,11 @@ bool virtqueue_enable_cb_delayed(struct + * more to do. */ + /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to + * either clear the flags bit or point the event index at the next +- * entry. Always do both to keep code simple. */ ++ * entry. Always update the event index to keep code simple. */ + if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { + vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; +- vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); ++ if (!vq->event) ++ vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); + } + /* TODO: tune this threshold */ + bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; +@@ -770,7 +773,8 @@ struct virtqueue *vring_new_virtqueue(un + /* No callback? Tell other side not to bother us. */ + if (!callback) { + vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; +- vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); ++ if (!vq->event) ++ vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); + } + + /* Put everything in free lists. */