From: Greg Kroah-Hartman Date: Sun, 30 Apr 2017 12:26:53 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v4.4.66~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9ced99286ceb0419cf29468ffdc0e2df35db639c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: ext4-check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea.patch md-raid1-fix-a-dead-loop-when-read-from-a-writemostly-disk.patch mips-fix-crash-registers-on-non-crashing-cpus.patch rds-fix-the-atomicity-for-congestion-map-update.patch usb-gadget-f_midi-fixed-a-bug-when-buflen-was-smaller-than-wmaxpacketsize.patch xen-x86-don-t-lose-event-interrupts.patch --- diff --git a/queue-3.18/ext4-check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea.patch b/queue-3.18/ext4-check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea.patch new file mode 100644 index 00000000000..027336f9e68 --- /dev/null +++ b/queue-3.18/ext4-check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea.patch @@ -0,0 +1,92 @@ +From 9e92f48c34eb2b9af9d12f892e2fe1fce5e8ce35 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Tue, 22 Mar 2016 16:13:15 -0400 +Subject: ext4: check if in-inode xattr is corrupted in ext4_expand_extra_isize_ea() + +From: Theodore Ts'o + +commit 9e92f48c34eb2b9af9d12f892e2fe1fce5e8ce35 upstream. + +We aren't checking to see if the in-inode extended attribute is +corrupted before we try to expand the inode's extra isize fields. + +This can lead to potential crashes caused by the BUG_ON() check in +ext4_xattr_shift_entries(). + +Signed-off-by: Theodore Ts'o +Cc: Julia Lawall +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/xattr.c | 32 ++++++++++++++++++++++++++++---- + 1 file changed, 28 insertions(+), 4 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -233,6 +233,27 @@ ext4_xattr_check_block(struct inode *ino + return error; + } + ++static int ++__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header, ++ void *end, const char *function, unsigned int line) ++{ ++ struct ext4_xattr_entry *entry = IFIRST(header); ++ int error = -EFSCORRUPTED; ++ ++ if (((void *) header >= end) || ++ (header->h_magic != le32_to_cpu(EXT4_XATTR_MAGIC))) ++ goto errout; ++ error = ext4_xattr_check_names(entry, end, entry); ++errout: ++ if (error) ++ __ext4_error_inode(inode, function, line, 0, ++ "corrupted in-inode xattr"); ++ return error; ++} ++ ++#define xattr_check_inode(inode, header, end) \ ++ __xattr_check_inode((inode), (header), (end), __func__, __LINE__) ++ + static inline int + ext4_xattr_check_entry(struct ext4_xattr_entry *entry, size_t size) + { +@@ -344,7 +365,7 @@ ext4_xattr_ibody_get(struct inode *inode + header = IHDR(inode, raw_inode); + entry = IFIRST(header); + end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; +- error = ext4_xattr_check_names(entry, end, entry); ++ error = xattr_check_inode(inode, header, end); + if (error) + goto cleanup; + error = ext4_xattr_find_entry(&entry, name_index, name, +@@ -476,7 +497,7 @@ ext4_xattr_ibody_list(struct dentry *den + raw_inode = ext4_raw_inode(&iloc); + header = IHDR(inode, raw_inode); + end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; +- error = ext4_xattr_check_names(IFIRST(header), end, IFIRST(header)); ++ error = xattr_check_inode(inode, header, end); + if (error) + goto cleanup; + error = ext4_xattr_list_entries(dentry, IFIRST(header), +@@ -993,8 +1014,7 @@ int ext4_xattr_ibody_find(struct inode * + is->s.here = is->s.first; + is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size; + if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) { +- error = ext4_xattr_check_names(IFIRST(header), is->s.end, +- IFIRST(header)); ++ error = xattr_check_inode(inode, header, is->s.end); + if (error) + return error; + /* Find the named attribute. */ +@@ -1291,6 +1311,10 @@ retry: + last = entry; + total_ino = sizeof(struct ext4_xattr_ibody_header); + ++ error = xattr_check_inode(inode, header, end); ++ if (error) ++ goto cleanup; ++ + free = ext4_xattr_free_space(last, &min_offs, base, &total_ino); + if (free >= new_extra_isize) { + entry = IFIRST(header); diff --git a/queue-3.18/md-raid1-fix-a-dead-loop-when-read-from-a-writemostly-disk.patch b/queue-3.18/md-raid1-fix-a-dead-loop-when-read-from-a-writemostly-disk.patch new file mode 100644 index 00000000000..d4d21da7af6 --- /dev/null +++ b/queue-3.18/md-raid1-fix-a-dead-loop-when-read-from-a-writemostly-disk.patch @@ -0,0 +1,37 @@ +From 816b0acf3deb6d6be5d0519b286fdd4bafade905 Mon Sep 17 00:00:00 2001 +From: Wei Fang +Date: Mon, 21 Mar 2016 19:18:32 +0800 +Subject: md:raid1: fix a dead loop when read from a WriteMostly disk + +From: Wei Fang + +commit 816b0acf3deb6d6be5d0519b286fdd4bafade905 upstream. + +If first_bad == this_sector when we get the WriteMostly disk +in read_balance(), valid disk will be returned with zero +max_sectors. It'll lead to a dead loop in make_request(), and +OOM will happen because of endless allocation of struct bio. + +Since we can't get data from this disk in this case, so +continue for another disk. + +Signed-off-by: Wei Fang +Signed-off-by: Shaohua Li +Cc: Julia Lawall +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/raid1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -563,7 +563,7 @@ static int read_balance(struct r1conf *c + if (best_dist_disk < 0) { + if (is_badblock(rdev, this_sector, sectors, + &first_bad, &bad_sectors)) { +- if (first_bad < this_sector) ++ if (first_bad <= this_sector) + /* Cannot use this */ + continue; + best_good_sectors = first_bad - this_sector; diff --git a/queue-3.18/mips-fix-crash-registers-on-non-crashing-cpus.patch b/queue-3.18/mips-fix-crash-registers-on-non-crashing-cpus.patch new file mode 100644 index 00000000000..2db0aff21fe --- /dev/null +++ b/queue-3.18/mips-fix-crash-registers-on-non-crashing-cpus.patch @@ -0,0 +1,58 @@ +From c80e1b62ffca52e2d1d865ee58bc79c4c0c55005 Mon Sep 17 00:00:00 2001 +From: Corey Minyard +Date: Mon, 11 Apr 2016 09:10:19 -0500 +Subject: MIPS: Fix crash registers on non-crashing CPUs + +From: Corey Minyard + +commit c80e1b62ffca52e2d1d865ee58bc79c4c0c55005 upstream. + +As part of handling a crash on an SMP system, an IPI is send to +all other CPUs to save their current registers and stop. It was +using task_pt_regs(current) to get the registers, but that will +only be accurate if the CPU was interrupted running in userland. +Instead allow the architecture to pass in the registers (all +pass NULL now, but allow for the future) and then use get_irq_regs() +which should be accurate as we are in an interrupt. Fall back to +task_pt_regs(current) if nothing else is available. + +Signed-off-by: Corey Minyard +Cc: David Daney +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/13050/ +Signed-off-by: Ralf Baechle +Cc: Julia Lawall +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/kernel/crash.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/arch/mips/kernel/crash.c ++++ b/arch/mips/kernel/crash.c +@@ -14,12 +14,22 @@ static int crashing_cpu = -1; + static cpumask_t cpus_in_crash = CPU_MASK_NONE; + + #ifdef CONFIG_SMP +-static void crash_shutdown_secondary(void *ignore) ++static void crash_shutdown_secondary(void *passed_regs) + { +- struct pt_regs *regs; ++ struct pt_regs *regs = passed_regs; + int cpu = smp_processor_id(); + +- regs = task_pt_regs(current); ++ /* ++ * If we are passed registers, use those. Otherwise get the ++ * regs from the last interrupt, which should be correct, as ++ * we are in an interrupt. But if the regs are not there, ++ * pull them from the top of the stack. They are probably ++ * wrong, but we need something to keep from crashing again. ++ */ ++ if (!regs) ++ regs = get_irq_regs(); ++ if (!regs) ++ regs = task_pt_regs(current); + + if (!cpu_online(cpu)) + return; diff --git a/queue-3.18/rds-fix-the-atomicity-for-congestion-map-update.patch b/queue-3.18/rds-fix-the-atomicity-for-congestion-map-update.patch new file mode 100644 index 00000000000..f0d86765465 --- /dev/null +++ b/queue-3.18/rds-fix-the-atomicity-for-congestion-map-update.patch @@ -0,0 +1,50 @@ +From e47db94e10447fc467777a40302f2b393e9af2fa Mon Sep 17 00:00:00 2001 +From: "santosh.shilimkar@oracle.com" +Date: Thu, 14 Apr 2016 10:43:27 -0700 +Subject: RDS: Fix the atomicity for congestion map update + +From: santosh.shilimkar@oracle.com + +commit e47db94e10447fc467777a40302f2b393e9af2fa upstream. + +Two different threads with different rds sockets may be in +rds_recv_rcvbuf_delta() via receive path. If their ports +both map to the same word in the congestion map, then +using non-atomic ops to update it could cause the map to +be incorrect. Lets use atomics to avoid such an issue. + +Full credit to Wengang for +finding the issue, analysing it and also pointing out +to offending code with spin lock based fix. + +Reviewed-by: Leon Romanovsky +Signed-off-by: Wengang Wang +Signed-off-by: Santosh Shilimkar +Signed-off-by: David S. Miller +Cc: Julia Lawall +Signed-off-by: Greg Kroah-Hartman + +--- + net/rds/cong.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/rds/cong.c ++++ b/net/rds/cong.c +@@ -285,7 +285,7 @@ void rds_cong_set_bit(struct rds_cong_ma + i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; + off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; + +- __set_bit_le(off, (void *)map->m_page_addrs[i]); ++ set_bit_le(off, (void *)map->m_page_addrs[i]); + } + + void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) +@@ -299,7 +299,7 @@ void rds_cong_clear_bit(struct rds_cong_ + i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; + off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; + +- __clear_bit_le(off, (void *)map->m_page_addrs[i]); ++ clear_bit_le(off, (void *)map->m_page_addrs[i]); + } + + static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port) diff --git a/queue-3.18/series b/queue-3.18/series index d5dd8c2d477..eef098e68fb 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -1,2 +1,8 @@ f2fs-do-more-integrity-verification-for-superblock.patch xc2028-unlock-on-error-in-xc2028_set_config.patch +ext4-check-if-in-inode-xattr-is-corrupted-in-ext4_expand_extra_isize_ea.patch +md-raid1-fix-a-dead-loop-when-read-from-a-writemostly-disk.patch +mips-fix-crash-registers-on-non-crashing-cpus.patch +rds-fix-the-atomicity-for-congestion-map-update.patch +usb-gadget-f_midi-fixed-a-bug-when-buflen-was-smaller-than-wmaxpacketsize.patch +xen-x86-don-t-lose-event-interrupts.patch diff --git a/queue-3.18/usb-gadget-f_midi-fixed-a-bug-when-buflen-was-smaller-than-wmaxpacketsize.patch b/queue-3.18/usb-gadget-f_midi-fixed-a-bug-when-buflen-was-smaller-than-wmaxpacketsize.patch new file mode 100644 index 00000000000..c79d93a6fc2 --- /dev/null +++ b/queue-3.18/usb-gadget-f_midi-fixed-a-bug-when-buflen-was-smaller-than-wmaxpacketsize.patch @@ -0,0 +1,52 @@ +From 03d27ade4941076b34c823d63d91dc895731a595 Mon Sep 17 00:00:00 2001 +From: "Felipe F. Tonello" +Date: Wed, 9 Mar 2016 19:39:30 +0000 +Subject: usb: gadget: f_midi: Fixed a bug when buflen was smaller than wMaxPacketSize + +From: Felipe F. Tonello + +commit 03d27ade4941076b34c823d63d91dc895731a595 upstream. + +buflen by default (256) is smaller than wMaxPacketSize (512) in high-speed +devices. + +That caused the OUT endpoint to freeze if the host send any data packet of +length greater than 256 bytes. + +This is an example dump of what happended on that enpoint: +HOST: [DATA][Length=260][...] +DEVICE: [NAK] +HOST: [PING] +DEVICE: [NAK] +HOST: [PING] +DEVICE: [NAK] +... +HOST: [PING] +DEVICE: [NAK] + +This patch fixes this problem by setting the minimum usb_request's buffer size +for the OUT endpoint as its wMaxPacketSize. + +Acked-by: Michal Nazarewicz +Signed-off-by: Felipe F. Tonello +Signed-off-by: Felipe Balbi +Cc: Julia Lawall +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/function/f_midi.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/gadget/function/f_midi.c ++++ b/drivers/usb/gadget/function/f_midi.c +@@ -357,7 +357,9 @@ static int f_midi_set_alt(struct usb_fun + /* allocate a bunch of read buffers and queue them all at once. */ + for (i = 0; i < midi->qlen && err == 0; i++) { + struct usb_request *req = +- midi_alloc_ep_req(midi->out_ep, midi->buflen); ++ midi_alloc_ep_req(midi->out_ep, ++ max_t(unsigned, midi->buflen, ++ bulk_out_desc.wMaxPacketSize)); + if (req == NULL) + return -ENOMEM; + diff --git a/queue-3.18/xen-x86-don-t-lose-event-interrupts.patch b/queue-3.18/xen-x86-don-t-lose-event-interrupts.patch new file mode 100644 index 00000000000..d9542112245 --- /dev/null +++ b/queue-3.18/xen-x86-don-t-lose-event-interrupts.patch @@ -0,0 +1,47 @@ +From c06b6d70feb32d28f04ba37aa3df17973fd37b6b Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Fri, 15 Apr 2016 18:23:00 -0700 +Subject: xen/x86: don't lose event interrupts + +From: Stefano Stabellini + +commit c06b6d70feb32d28f04ba37aa3df17973fd37b6b upstream. + +On slow platforms with unreliable TSC, such as QEMU emulated machines, +it is possible for the kernel to request the next event in the past. In +that case, in the current implementation of xen_vcpuop_clockevent, we +simply return -ETIME. To be precise the Xen returns -ETIME and we pass +it on. However the result of this is a missed event, which simply causes +the kernel to hang. + +Instead it is better to always ask the hypervisor for a timer event, +even if the timeout is in the past. That way there are no lost +interrupts and the kernel survives. To do that, remove the +VCPU_SSHOTTMR_future flag. + +Signed-off-by: Stefano Stabellini +Acked-by: Juergen Gross +Cc: Julia Lawall +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/xen/time.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/x86/xen/time.c ++++ b/arch/x86/xen/time.c +@@ -362,11 +362,11 @@ static int xen_vcpuop_set_next_event(uns + WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT); + + single.timeout_abs_ns = get_abs_timeout(delta); +- single.flags = VCPU_SSHOTTMR_future; ++ /* Get an event anyway, even if the timeout is already expired */ ++ single.flags = 0; + + ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single); +- +- BUG_ON(ret != 0 && ret != -ETIME); ++ BUG_ON(ret != 0); + + return ret; + }