From 908d8c1f6fd6608ca43fdb4c5679d35844a5adc1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 1 Mar 2016 10:36:46 -0800 Subject: [PATCH] 4.4-stable patches added patches: s390-compat-correct-restore-of-high-gprs-on-signal-return.patch s390-dasd-fix-performance-drop.patch s390-dasd-fix-refcount-for-pav-reassignment.patch s390-dasd-prevent-incorrect-length-error-under-z-vm-after-pav-changes.patch s390-fix-normalization-bug-in-exception-table-sorting.patch s390-fpu-signals-vs.-floating-point-control-register.patch uml-fix-hostfs-mknod.patch uml-flush-stdout-before-forking.patch --- ...estore-of-high-gprs-on-signal-return.patch | 38 ++++++++ .../s390-dasd-fix-performance-drop.patch | 34 +++++++ ...sd-fix-refcount-for-pav-reassignment.patch | 89 +++++++++++++++++++ ...h-error-under-z-vm-after-pav-changes.patch | 34 +++++++ ...ation-bug-in-exception-table-sorting.patch | 57 ++++++++++++ ...-vs.-floating-point-control-register.patch | 42 +++++++++ queue-4.4/series | 8 ++ queue-4.4/uml-fix-hostfs-mknod.patch | 69 ++++++++++++++ .../uml-flush-stdout-before-forking.patch | 54 +++++++++++ 9 files changed, 425 insertions(+) create mode 100644 queue-4.4/s390-compat-correct-restore-of-high-gprs-on-signal-return.patch create mode 100644 queue-4.4/s390-dasd-fix-performance-drop.patch create mode 100644 queue-4.4/s390-dasd-fix-refcount-for-pav-reassignment.patch create mode 100644 queue-4.4/s390-dasd-prevent-incorrect-length-error-under-z-vm-after-pav-changes.patch create mode 100644 queue-4.4/s390-fix-normalization-bug-in-exception-table-sorting.patch create mode 100644 queue-4.4/s390-fpu-signals-vs.-floating-point-control-register.patch create mode 100644 queue-4.4/uml-fix-hostfs-mknod.patch create mode 100644 queue-4.4/uml-flush-stdout-before-forking.patch diff --git a/queue-4.4/s390-compat-correct-restore-of-high-gprs-on-signal-return.patch b/queue-4.4/s390-compat-correct-restore-of-high-gprs-on-signal-return.patch new file mode 100644 index 00000000000..acdba050372 --- /dev/null +++ b/queue-4.4/s390-compat-correct-restore-of-high-gprs-on-signal-return.patch @@ -0,0 +1,38 @@ +From 342300cc9cd3428bc6bfe5809bfcc1b9a0f06702 Mon Sep 17 00:00:00 2001 +From: Martin Schwidefsky +Date: Fri, 19 Feb 2016 14:44:14 +0100 +Subject: s390/compat: correct restore of high gprs on signal return + +From: Martin Schwidefsky + +commit 342300cc9cd3428bc6bfe5809bfcc1b9a0f06702 upstream. + +git commit 8070361799ae1e3f4ef347bd10f0a508ac10acfb +"s390: add support for vector extension" +broke 31-bit compat processes in regard to signal handling. + +The restore_sigregs_ext32() function is used to restore the additional +elements from the user space signal frame. Among the additional elements +are the upper registers halves for 64-bit register support for 31-bit +processes. The copy_from_user that is used to retrieve the high-gprs +array from the user stack uses an incorrect length, 8 bytes instead of +64 bytes. This causes incorrect upper register halves to get loaded. + +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/compat_signal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/s390/kernel/compat_signal.c ++++ b/arch/s390/kernel/compat_signal.c +@@ -271,7 +271,7 @@ static int restore_sigregs_ext32(struct + + /* Restore high gprs from signal stack */ + if (__copy_from_user(&gprs_high, &sregs_ext->gprs_high, +- sizeof(&sregs_ext->gprs_high))) ++ sizeof(sregs_ext->gprs_high))) + return -EFAULT; + for (i = 0; i < NUM_GPRS; i++) + *(__u32 *)®s->gprs[i] = gprs_high[i]; diff --git a/queue-4.4/s390-dasd-fix-performance-drop.patch b/queue-4.4/s390-dasd-fix-performance-drop.patch new file mode 100644 index 00000000000..dbe28f9598f --- /dev/null +++ b/queue-4.4/s390-dasd-fix-performance-drop.patch @@ -0,0 +1,34 @@ +From 12d319b920fa673a4d5e7c1785c5dc82dcd15257 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Fri, 12 Feb 2016 14:50:52 +0100 +Subject: s390/dasd: fix performance drop + +From: Stefan Haberland + +commit 12d319b920fa673a4d5e7c1785c5dc82dcd15257 upstream. + +Commit ca369d51b ("sd: Fix device-imposed transfer length limits") +introduced a new queue limit max_dev_sectors which limits the maximum +sectors for requests. The default value leads to small dasd requests +and therefor to a performance drop. +Set the max_dev_sectors value to the same value as the max_hw_sectors +to use the maximum available request size for DASD devices. + +Signed-off-by: Stefan Haberland +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/block/dasd.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/s390/block/dasd.c ++++ b/drivers/s390/block/dasd.c +@@ -3031,6 +3031,7 @@ static void dasd_setup_queue(struct dasd + max = block->base->discipline->max_blocks << block->s2b_shift; + } + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, block->request_queue); ++ block->request_queue->limits.max_dev_sectors = max; + blk_queue_logical_block_size(block->request_queue, + block->bp_block); + blk_queue_max_hw_sectors(block->request_queue, max); diff --git a/queue-4.4/s390-dasd-fix-refcount-for-pav-reassignment.patch b/queue-4.4/s390-dasd-fix-refcount-for-pav-reassignment.patch new file mode 100644 index 00000000000..eabf94b40c3 --- /dev/null +++ b/queue-4.4/s390-dasd-fix-refcount-for-pav-reassignment.patch @@ -0,0 +1,89 @@ +From 9d862ababb609439c5d6987f6d3ddd09e703aa0b Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Tue, 15 Dec 2015 10:45:05 +0100 +Subject: s390/dasd: fix refcount for PAV reassignment + +From: Stefan Haberland + +commit 9d862ababb609439c5d6987f6d3ddd09e703aa0b upstream. + +Add refcount to the DASD device when a summary unit check worker is +scheduled. This prevents that the device is set offline with worker +in place. + +Signed-off-by: Stefan Haberland +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/block/dasd_alias.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +--- a/drivers/s390/block/dasd_alias.c ++++ b/drivers/s390/block/dasd_alias.c +@@ -264,8 +264,10 @@ void dasd_alias_disconnect_device_from_l + spin_unlock_irqrestore(&lcu->lock, flags); + cancel_work_sync(&lcu->suc_data.worker); + spin_lock_irqsave(&lcu->lock, flags); +- if (device == lcu->suc_data.device) ++ if (device == lcu->suc_data.device) { ++ dasd_put_device(device); + lcu->suc_data.device = NULL; ++ } + } + was_pending = 0; + if (device == lcu->ruac_data.device) { +@@ -273,8 +275,10 @@ void dasd_alias_disconnect_device_from_l + was_pending = 1; + cancel_delayed_work_sync(&lcu->ruac_data.dwork); + spin_lock_irqsave(&lcu->lock, flags); +- if (device == lcu->ruac_data.device) ++ if (device == lcu->ruac_data.device) { ++ dasd_put_device(device); + lcu->ruac_data.device = NULL; ++ } + } + private->lcu = NULL; + spin_unlock_irqrestore(&lcu->lock, flags); +@@ -549,8 +553,10 @@ static void lcu_update_work(struct work_ + if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) { + DBF_DEV_EVENT(DBF_WARNING, device, "could not update" + " alias data in lcu (rc = %d), retry later", rc); +- schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ); ++ if (!schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ)) ++ dasd_put_device(device); + } else { ++ dasd_put_device(device); + lcu->ruac_data.device = NULL; + lcu->flags &= ~UPDATE_PENDING; + } +@@ -593,8 +599,10 @@ static int _schedule_lcu_update(struct a + */ + if (!usedev) + return -EINVAL; ++ dasd_get_device(usedev); + lcu->ruac_data.device = usedev; +- schedule_delayed_work(&lcu->ruac_data.dwork, 0); ++ if (!schedule_delayed_work(&lcu->ruac_data.dwork, 0)) ++ dasd_put_device(usedev); + return 0; + } + +@@ -930,6 +938,7 @@ static void summary_unit_check_handling_ + /* 3. read new alias configuration */ + _schedule_lcu_update(lcu, device); + lcu->suc_data.device = NULL; ++ dasd_put_device(device); + spin_unlock_irqrestore(&lcu->lock, flags); + } + +@@ -989,6 +998,8 @@ void dasd_alias_handle_summary_unit_chec + } + lcu->suc_data.reason = reason; + lcu->suc_data.device = device; ++ dasd_get_device(device); + spin_unlock(&lcu->lock); +- schedule_work(&lcu->suc_data.worker); ++ if (!schedule_work(&lcu->suc_data.worker)) ++ dasd_put_device(device); + }; diff --git a/queue-4.4/s390-dasd-prevent-incorrect-length-error-under-z-vm-after-pav-changes.patch b/queue-4.4/s390-dasd-prevent-incorrect-length-error-under-z-vm-after-pav-changes.patch new file mode 100644 index 00000000000..d361534c5f4 --- /dev/null +++ b/queue-4.4/s390-dasd-prevent-incorrect-length-error-under-z-vm-after-pav-changes.patch @@ -0,0 +1,34 @@ +From 020bf042e5b397479c1174081b935d0ff15d1a64 Mon Sep 17 00:00:00 2001 +From: Stefan Haberland +Date: Tue, 15 Dec 2015 10:16:43 +0100 +Subject: s390/dasd: prevent incorrect length error under z/VM after PAV changes + +From: Stefan Haberland + +commit 020bf042e5b397479c1174081b935d0ff15d1a64 upstream. + +The channel checks the specified length and the provided amount of +data for CCWs and provides an incorrect length error if the size does +not match. Under z/VM with simulation activated the length may get +changed. Having the suppress length indication bit set is stated as +good CCW coding practice and avoids errors under z/VM. + +Signed-off-by: Stefan Haberland +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/block/dasd_alias.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/s390/block/dasd_alias.c ++++ b/drivers/s390/block/dasd_alias.c +@@ -723,7 +723,7 @@ static int reset_summary_unit_check(stru + ASCEBC((char *) &cqr->magic, 4); + ccw = cqr->cpaddr; + ccw->cmd_code = DASD_ECKD_CCW_RSCK; +- ccw->flags = 0 ; ++ ccw->flags = CCW_FLAG_SLI; + ccw->count = 16; + ccw->cda = (__u32)(addr_t) cqr->data; + ((char *)cqr->data)[0] = reason; diff --git a/queue-4.4/s390-fix-normalization-bug-in-exception-table-sorting.patch b/queue-4.4/s390-fix-normalization-bug-in-exception-table-sorting.patch new file mode 100644 index 00000000000..f91b9ac3fee --- /dev/null +++ b/queue-4.4/s390-fix-normalization-bug-in-exception-table-sorting.patch @@ -0,0 +1,57 @@ +From bcb7825a77f41c7dd91da6f7ac10b928156a322e Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Fri, 1 Jan 2016 13:39:22 +0100 +Subject: s390: fix normalization bug in exception table sorting + +From: Ard Biesheuvel + +commit bcb7825a77f41c7dd91da6f7ac10b928156a322e upstream. + +The normalization pass in the sorting routine of the relative exception +table serves two purposes: +- it ensures that the address fields of the exception table entries are + fully ordered, so that no ambiguities arise between entries with + identical instruction offsets (i.e., when two instructions that are + exactly 8 bytes apart each have an exception table entry associated with + them) +- it ensures that the offsets of both the instruction and the fixup fields + of each entry are relative to their final location after sorting. + +Commit eb608fb366de ("s390/exceptions: switch to relative exception table +entries") ported the relative exception table format from x86, but modified +the sorting routine to only normalize the instruction offset field and not +the fixup offset field. The result is that the fixup offset of each entry +will be relative to the original location of the entry before sorting, +likely leading to crashes when those entries are dereferenced. + +Fixes: eb608fb366de ("s390/exceptions: switch to relative exception table entries") +Signed-off-by: Ard Biesheuvel +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/mm/extable.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/arch/s390/mm/extable.c ++++ b/arch/s390/mm/extable.c +@@ -52,12 +52,16 @@ void sort_extable(struct exception_table + int i; + + /* Normalize entries to being relative to the start of the section */ +- for (p = start, i = 0; p < finish; p++, i += 8) ++ for (p = start, i = 0; p < finish; p++, i += 8) { + p->insn += i; ++ p->fixup += i + 4; ++ } + sort(start, finish - start, sizeof(*start), cmp_ex, NULL); + /* Denormalize all entries */ +- for (p = start, i = 0; p < finish; p++, i += 8) ++ for (p = start, i = 0; p < finish; p++, i += 8) { + p->insn -= i; ++ p->fixup -= i + 4; ++ } + } + + #ifdef CONFIG_MODULES diff --git a/queue-4.4/s390-fpu-signals-vs.-floating-point-control-register.patch b/queue-4.4/s390-fpu-signals-vs.-floating-point-control-register.patch new file mode 100644 index 00000000000..850ebf142b7 --- /dev/null +++ b/queue-4.4/s390-fpu-signals-vs.-floating-point-control-register.patch @@ -0,0 +1,42 @@ +From 1b17cb796f5d40ffa239c6926385abd83a77a49b Mon Sep 17 00:00:00 2001 +From: Martin Schwidefsky +Date: Fri, 19 Feb 2016 15:29:05 +0100 +Subject: s390/fpu: signals vs. floating point control register + +From: Martin Schwidefsky + +commit 1b17cb796f5d40ffa239c6926385abd83a77a49b upstream. + +git commit 904818e2f229f3d94ec95f6932a6358c81e73d78 +"s390/kernel: introduce fpu-internal.h with fpu helper functions" +introduced the fpregs_store / fp_regs_load helper. These function +fail to save and restore the floating pointer control registers. + +The effect is that the FPC is not correctly handled on signal +delivery and signal return. + +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/include/asm/fpu/internal.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/s390/include/asm/fpu/internal.h ++++ b/arch/s390/include/asm/fpu/internal.h +@@ -48,6 +48,7 @@ static inline void convert_fp_to_vx(__ve + static inline void fpregs_store(_s390_fp_regs *fpregs, struct fpu *fpu) + { + fpregs->pad = 0; ++ fpregs->fpc = fpu->fpc; + if (MACHINE_HAS_VX) + convert_vx_to_fp((freg_t *)&fpregs->fprs, fpu->vxrs); + else +@@ -57,6 +58,7 @@ static inline void fpregs_store(_s390_fp + + static inline void fpregs_load(_s390_fp_regs *fpregs, struct fpu *fpu) + { ++ fpu->fpc = fpregs->fpc; + if (MACHINE_HAS_VX) + convert_fp_to_vx(fpu->vxrs, (freg_t *)&fpregs->fprs); + else diff --git a/queue-4.4/series b/queue-4.4/series index 9e3a58a40c5..a1c29884b47 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -92,3 +92,11 @@ btrfs-fix-number-of-transaction-units-required-to-create-symlink.patch btrfs-fix-transaction-handle-leak-on-failure-to-create-hard-link.patch btrfs-initialize-btrfs_root-highest_objectid-when-loading-tree-root-and-subvolume-roots.patch btrfs-initialize-the-seq-counter-in-struct-btrfs_device.patch +s390-fix-normalization-bug-in-exception-table-sorting.patch +s390-dasd-prevent-incorrect-length-error-under-z-vm-after-pav-changes.patch +s390-dasd-fix-refcount-for-pav-reassignment.patch +s390-dasd-fix-performance-drop.patch +s390-compat-correct-restore-of-high-gprs-on-signal-return.patch +s390-fpu-signals-vs.-floating-point-control-register.patch +uml-flush-stdout-before-forking.patch +uml-fix-hostfs-mknod.patch diff --git a/queue-4.4/uml-fix-hostfs-mknod.patch b/queue-4.4/uml-fix-hostfs-mknod.patch new file mode 100644 index 00000000000..846743f01b5 --- /dev/null +++ b/queue-4.4/uml-fix-hostfs-mknod.patch @@ -0,0 +1,69 @@ +From 9f2dfda2f2f1c6181c3732c16b85c59ab2d195e0 Mon Sep 17 00:00:00 2001 +From: Vegard Nossum +Date: Wed, 16 Dec 2015 21:59:56 +0100 +Subject: uml: fix hostfs mknod() + +From: Vegard Nossum + +commit 9f2dfda2f2f1c6181c3732c16b85c59ab2d195e0 upstream. + +An inverted return value check in hostfs_mknod() caused the function +to return success after handling it as an error (and cleaning up). + +It resulted in the following segfault when trying to bind() a named +unix socket: + + Pid: 198, comm: a.out Not tainted 4.4.0-rc4 + RIP: 0033:[<0000000061077df6>] + RSP: 00000000daae5d60 EFLAGS: 00010202 + RAX: 0000000000000000 RBX: 000000006092a460 RCX: 00000000dfc54208 + RDX: 0000000061073ef1 RSI: 0000000000000070 RDI: 00000000e027d600 + RBP: 00000000daae5de0 R08: 00000000da980ac0 R09: 0000000000000000 + R10: 0000000000000003 R11: 00007fb1ae08f72a R12: 0000000000000000 + R13: 000000006092a460 R14: 00000000daaa97c0 R15: 00000000daaa9a88 + Kernel panic - not syncing: Kernel mode fault at addr 0x40, ip 0x61077df6 + CPU: 0 PID: 198 Comm: a.out Not tainted 4.4.0-rc4 #1 + Stack: + e027d620 dfc54208 0000006f da981398 + 61bee000 0000c1ed daae5de0 0000006e + e027d620 dfcd4208 00000005 6092a460 + Call Trace: + [<60dedc67>] SyS_bind+0xf7/0x110 + [<600587be>] handle_syscall+0x7e/0x80 + [<60066ad7>] userspace+0x3e7/0x4e0 + [<6006321f>] ? save_registers+0x1f/0x40 + [<6006c88e>] ? arch_prctl+0x1be/0x1f0 + [<60054985>] fork_handler+0x85/0x90 + +Let's also get rid of the "cosmic ray protection" while we're at it. + +Fixes: e9193059b1b3 "hostfs: fix races in dentry_name() and inode_name()" +Signed-off-by: Vegard Nossum +Cc: Jeff Dike +Cc: Al Viro +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/hostfs/hostfs_kern.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/fs/hostfs/hostfs_kern.c ++++ b/fs/hostfs/hostfs_kern.c +@@ -730,15 +730,13 @@ static int hostfs_mknod(struct inode *di + + init_special_inode(inode, mode, dev); + err = do_mknod(name, mode, MAJOR(dev), MINOR(dev)); +- if (!err) ++ if (err) + goto out_free; + + err = read_name(inode, name); + __putname(name); + if (err) + goto out_put; +- if (err) +- goto out_put; + + d_instantiate(dentry, inode); + return 0; diff --git a/queue-4.4/uml-flush-stdout-before-forking.patch b/queue-4.4/uml-flush-stdout-before-forking.patch new file mode 100644 index 00000000000..c902ba7e0a7 --- /dev/null +++ b/queue-4.4/uml-flush-stdout-before-forking.patch @@ -0,0 +1,54 @@ +From 0754fb298f2f2719f0393491d010d46cfb25d043 Mon Sep 17 00:00:00 2001 +From: Vegard Nossum +Date: Fri, 18 Dec 2015 21:28:53 +0100 +Subject: uml: flush stdout before forking + +From: Vegard Nossum + +commit 0754fb298f2f2719f0393491d010d46cfb25d043 upstream. + +I was seeing some really weird behaviour where piping UML's output +somewhere would cause output to get duplicated: + + $ ./vmlinux | head -n 40 + Checking that ptrace can change system call numbers...Core dump limits : + soft - 0 + hard - NONE + OK + Checking syscall emulation patch for ptrace...Core dump limits : + soft - 0 + hard - NONE + OK + Checking advanced syscall emulation patch for ptrace...Core dump limits : + soft - 0 + hard - NONE + OK + Core dump limits : + soft - 0 + hard - NONE + +This is because these tests do a fork() which duplicates the non-empty +stdout buffer, then glibc flushes the duplicated buffer as each child +exits. + +A simple workaround is to flush before forking. + +Signed-off-by: Vegard Nossum +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + arch/um/os-Linux/start_up.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/um/os-Linux/start_up.c ++++ b/arch/um/os-Linux/start_up.c +@@ -94,6 +94,8 @@ static int start_ptraced_child(void) + { + int pid, n, status; + ++ fflush(stdout); ++ + pid = fork(); + if (pid == 0) + ptrace_child(); -- 2.47.3