From: Greg Kroah-Hartman Date: Sun, 27 Jan 2019 15:51:13 +0000 (+0100) Subject: 4.20-stable patches X-Git-Tag: v4.9.154~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6fe7b9e4f97578193bb3d84190033bff1e4b5769;p=thirdparty%2Fkernel%2Fstable-queue.git 4.20-stable patches added patches: drivers-hv-vmbus-check-for-ring-when-getting-debug-info.patch hv_balloon-avoid-touching-uninitialized-struct-page-during-tail-onlining.patch tty-handle-problem-if-line-discipline-does-not-have-receive_buf.patch tty-n_hdlc-fix-__might_sleep-warning.patch uart-fix-crash-in-uart_write-and-uart_put_char.patch vgacon-unconfuse-vc_origin-when-using-soft-scrollback.patch --- diff --git a/queue-4.20/drivers-hv-vmbus-check-for-ring-when-getting-debug-info.patch b/queue-4.20/drivers-hv-vmbus-check-for-ring-when-getting-debug-info.patch new file mode 100644 index 00000000000..b302cafb999 --- /dev/null +++ b/queue-4.20/drivers-hv-vmbus-check-for-ring-when-getting-debug-info.patch @@ -0,0 +1,283 @@ +From ba50bf1ce9a51fc97db58b96d01306aa70bc3979 Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Mon, 17 Dec 2018 20:16:09 +0000 +Subject: Drivers: hv: vmbus: Check for ring when getting debug info + +From: Dexuan Cui + +commit ba50bf1ce9a51fc97db58b96d01306aa70bc3979 upstream. + +fc96df16a1ce is good and can already fix the "return stack garbage" issue, +but let's also improve hv_ringbuffer_get_debuginfo(), which would silently +return stack garbage, if people forget to check channel->state or +ring_info->ring_buffer, when using the function in the future. + +Having an error check in the function would eliminate the potential risk. + +Add a Fixes tag to indicate the patch depdendency. + +Fixes: fc96df16a1ce ("Drivers: hv: vmbus: Return -EINVAL for the sys files for unopened channels") +Cc: stable@vger.kernel.org +Cc: K. Y. Srinivasan +Cc: Haiyang Zhang +Signed-off-by: Stephen Hemminger +Signed-off-by: Dexuan Cui +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/ring_buffer.c | 29 +++++++------- + drivers/hv/vmbus_drv.c | 91 +++++++++++++++++++++++++++++++---------------- + include/linux/hyperv.h | 5 +- + 3 files changed, 78 insertions(+), 47 deletions(-) + +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struc + } + + /* Get various debug metrics for the specified ring buffer. */ +-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info, +- struct hv_ring_buffer_debug_info *debug_info) ++int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info, ++ struct hv_ring_buffer_debug_info *debug_info) + { + u32 bytes_avail_towrite; + u32 bytes_avail_toread; + +- if (ring_info->ring_buffer) { +- hv_get_ringbuffer_availbytes(ring_info, +- &bytes_avail_toread, +- &bytes_avail_towrite); ++ if (!ring_info->ring_buffer) ++ return -EINVAL; + +- debug_info->bytes_avail_toread = bytes_avail_toread; +- debug_info->bytes_avail_towrite = bytes_avail_towrite; +- debug_info->current_read_index = +- ring_info->ring_buffer->read_index; +- debug_info->current_write_index = +- ring_info->ring_buffer->write_index; +- debug_info->current_interrupt_mask = +- ring_info->ring_buffer->interrupt_mask; +- } ++ hv_get_ringbuffer_availbytes(ring_info, ++ &bytes_avail_toread, ++ &bytes_avail_towrite); ++ debug_info->bytes_avail_toread = bytes_avail_toread; ++ debug_info->bytes_avail_towrite = bytes_avail_towrite; ++ debug_info->current_read_index = ring_info->ring_buffer->read_index; ++ debug_info->current_write_index = ring_info->ring_buffer->write_index; ++ debug_info->current_interrupt_mask ++ = ring_info->ring_buffer->interrupt_mask; ++ return 0; + } + EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo); + +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info outbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, ++ &outbound); ++ if (ret < 0) ++ return ret; ++ + return sprintf(buf, "%d\n", outbound.current_interrupt_mask); + } + static DEVICE_ATTR_RO(out_intr_mask); +@@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struc + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info outbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, ++ &outbound); ++ if (ret < 0) ++ return ret; + return sprintf(buf, "%d\n", outbound.current_read_index); + } + static DEVICE_ATTR_RO(out_read_index); +@@ -344,12 +351,15 @@ static ssize_t out_write_index_show(stru + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info outbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, ++ &outbound); ++ if (ret < 0) ++ return ret; + return sprintf(buf, "%d\n", outbound.current_write_index); + } + static DEVICE_ATTR_RO(out_write_index); +@@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info outbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, ++ &outbound); ++ if (ret < 0) ++ return ret; + return sprintf(buf, "%d\n", outbound.bytes_avail_toread); + } + static DEVICE_ATTR_RO(out_read_bytes_avail); +@@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_sho + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info outbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, ++ &outbound); ++ if (ret < 0) ++ return ret; + return sprintf(buf, "%d\n", outbound.bytes_avail_towrite); + } + static DEVICE_ATTR_RO(out_write_bytes_avail); +@@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info inbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ if (ret < 0) ++ return ret; ++ + return sprintf(buf, "%d\n", inbound.current_interrupt_mask); + } + static DEVICE_ATTR_RO(in_intr_mask); +@@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info inbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ if (ret < 0) ++ return ret; ++ + return sprintf(buf, "%d\n", inbound.current_read_index); + } + static DEVICE_ATTR_RO(in_read_index); +@@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struc + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info inbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ if (ret < 0) ++ return ret; ++ + return sprintf(buf, "%d\n", inbound.current_write_index); + } + static DEVICE_ATTR_RO(in_write_index); +@@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show( + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info inbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ if (ret < 0) ++ return ret; ++ + return sprintf(buf, "%d\n", inbound.bytes_avail_toread); + } + static DEVICE_ATTR_RO(in_read_bytes_avail); +@@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show + { + struct hv_device *hv_dev = device_to_hv_device(dev); + struct hv_ring_buffer_debug_info inbound; ++ int ret; + + if (!hv_dev->channel) + return -ENODEV; +- if (hv_dev->channel->state != CHANNEL_OPENED_STATE) +- return -EINVAL; +- hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ ++ ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound); ++ if (ret < 0) ++ return ret; ++ + return sprintf(buf, "%d\n", inbound.bytes_avail_towrite); + } + static DEVICE_ATTR_RO(in_write_bytes_avail); +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1176,8 +1176,9 @@ struct hv_ring_buffer_debug_info { + u32 bytes_avail_towrite; + }; + +-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info, +- struct hv_ring_buffer_debug_info *debug_info); ++ ++int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info, ++ struct hv_ring_buffer_debug_info *debug_info); + + /* Vmbus interface */ + #define vmbus_driver_register(driver) \ diff --git a/queue-4.20/hv_balloon-avoid-touching-uninitialized-struct-page-during-tail-onlining.patch b/queue-4.20/hv_balloon-avoid-touching-uninitialized-struct-page-during-tail-onlining.patch new file mode 100644 index 00000000000..851039889f7 --- /dev/null +++ b/queue-4.20/hv_balloon-avoid-touching-uninitialized-struct-page-during-tail-onlining.patch @@ -0,0 +1,71 @@ +From da8ced360ca8ad72d8f41f5c8fcd5b0e63e1555f Mon Sep 17 00:00:00 2001 +From: Vitaly Kuznetsov +Date: Fri, 4 Jan 2019 15:19:42 +0100 +Subject: hv_balloon: avoid touching uninitialized struct page during tail onlining + +From: Vitaly Kuznetsov + +commit da8ced360ca8ad72d8f41f5c8fcd5b0e63e1555f upstream. + +Hyper-V memory hotplug protocol has 2M granularity and in Linux x86 we use +128M. To deal with it we implement partial section onlining by registering +custom page onlining callback (hv_online_page()). Later, when more memory +arrives we try to online the 'tail' (see hv_bring_pgs_online()). + +It was found that in some cases this 'tail' onlining causes issues: + + BUG: Bad page state in process kworker/0:2 pfn:109e3a + page:ffffe08344278e80 count:0 mapcount:1 mapping:0000000000000000 index:0x0 + flags: 0xfffff80000000() + raw: 000fffff80000000 dead000000000100 dead000000000200 0000000000000000 + raw: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 + page dumped because: nonzero mapcount + ... + Workqueue: events hot_add_req [hv_balloon] + Call Trace: + dump_stack+0x5c/0x80 + bad_page.cold.112+0x7f/0xb2 + free_pcppages_bulk+0x4b8/0x690 + free_unref_page+0x54/0x70 + hv_page_online_one+0x5c/0x80 [hv_balloon] + hot_add_req.cold.24+0x182/0x835 [hv_balloon] + ... + +Turns out that we now have deferred struct page initialization for memory +hotplug so e.g. memory_block_action() in drivers/base/memory.c does +pages_correctly_probed() check and in that check it avoids inspecting +struct pages and checks sections instead. But in Hyper-V balloon driver we +do PageReserved(pfn_to_page()) check and this is now wrong. + +Switch to checking online_section_nr() instead. + +Signed-off-by: Vitaly Kuznetsov +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hv/hv_balloon.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -888,12 +888,14 @@ static unsigned long handle_pg_range(uns + pfn_cnt -= pgs_ol; + /* + * Check if the corresponding memory block is already +- * online by checking its last previously backed page. +- * In case it is we need to bring rest (which was not +- * backed previously) online too. ++ * online. It is possible to observe struct pages still ++ * being uninitialized here so check section instead. ++ * In case the section is online we need to bring the ++ * rest of pfns (which were not backed previously) ++ * online too. + */ + if (start_pfn > has->start_pfn && +- !PageReserved(pfn_to_page(start_pfn - 1))) ++ online_section_nr(pfn_to_section_nr(start_pfn))) + hv_bring_pgs_online(has, start_pfn, pgs_ol); + + } diff --git a/queue-4.20/series b/queue-4.20/series index 81913ba4cc3..8d532ef073c 100644 --- a/queue-4.20/series +++ b/queue-4.20/series @@ -52,3 +52,9 @@ mmc-sdhci-iproc-handle-mmc_of_parse-errors-during-probe.patch mmc-dw_mmc-bluefield-fix-the-license-information.patch mmc-meson-gx-free-irq-in-release-callback.patch staging-rtl8188eu-add-device-code-for-d-link-dwa-121-rev-b1.patch +tty-handle-problem-if-line-discipline-does-not-have-receive_buf.patch +uart-fix-crash-in-uart_write-and-uart_put_char.patch +tty-n_hdlc-fix-__might_sleep-warning.patch +hv_balloon-avoid-touching-uninitialized-struct-page-during-tail-onlining.patch +drivers-hv-vmbus-check-for-ring-when-getting-debug-info.patch +vgacon-unconfuse-vc_origin-when-using-soft-scrollback.patch diff --git a/queue-4.20/tty-handle-problem-if-line-discipline-does-not-have-receive_buf.patch b/queue-4.20/tty-handle-problem-if-line-discipline-does-not-have-receive_buf.patch new file mode 100644 index 00000000000..5bbf6ffbe61 --- /dev/null +++ b/queue-4.20/tty-handle-problem-if-line-discipline-does-not-have-receive_buf.patch @@ -0,0 +1,33 @@ +From 27cfb3a53be46a54ec5e0bd04e51995b74c90343 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Sun, 20 Jan 2019 10:46:58 +0100 +Subject: tty: Handle problem if line discipline does not have receive_buf + +From: Greg Kroah-Hartman + +commit 27cfb3a53be46a54ec5e0bd04e51995b74c90343 upstream. + +Some tty line disciplines do not have a receive buf callback, so +properly check for that before calling it. If they do not have this +callback, just eat the character quietly, as we can't fail this call. + +Reported-by: Jann Horn +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/tty_io.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -2189,7 +2189,8 @@ static int tiocsti(struct tty_struct *tt + ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; +- ld->ops->receive_buf(tty, &ch, &mbz, 1); ++ if (ld->ops->receive_buf) ++ ld->ops->receive_buf(tty, &ch, &mbz, 1); + tty_ldisc_deref(ld); + return 0; + } diff --git a/queue-4.20/tty-n_hdlc-fix-__might_sleep-warning.patch b/queue-4.20/tty-n_hdlc-fix-__might_sleep-warning.patch new file mode 100644 index 00000000000..c12bb4aa3fa --- /dev/null +++ b/queue-4.20/tty-n_hdlc-fix-__might_sleep-warning.patch @@ -0,0 +1,42 @@ +From fc01d8c61ce02c034e67378cd3e645734bc18c8c Mon Sep 17 00:00:00 2001 +From: Paul Fulghum +Date: Tue, 1 Jan 2019 12:28:53 -0800 +Subject: tty/n_hdlc: fix __might_sleep warning + +From: Paul Fulghum + +commit fc01d8c61ce02c034e67378cd3e645734bc18c8c upstream. + +Fix __might_sleep warning[1] in tty/n_hdlc.c read due to copy_to_user +call while current is TASK_INTERRUPTIBLE. This is a false positive +since the code path does not depend on current state remaining +TASK_INTERRUPTIBLE. The loop breaks out and sets TASK_RUNNING after +calling copy_to_user. + +This patch supresses the warning by setting TASK_RUNNING before calling +copy_to_user. + +[1] https://syzkaller.appspot.com/bug?id=17d5de7f1fcab794cb8c40032f893f52de899324 + +Signed-off-by: Paul Fulghum +Reported-by: syzbot +Cc: Tetsuo Handa +Cc: Alan Cox +Cc: stable +Acked-by: Arnd Bergmann +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/n_hdlc.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/tty/n_hdlc.c ++++ b/drivers/tty/n_hdlc.c +@@ -597,6 +597,7 @@ static ssize_t n_hdlc_tty_read(struct tt + /* too large for caller's buffer */ + ret = -EOVERFLOW; + } else { ++ __set_current_state(TASK_RUNNING); + if (copy_to_user(buf, rbuf->buf, rbuf->count)) + ret = -EFAULT; + else diff --git a/queue-4.20/uart-fix-crash-in-uart_write-and-uart_put_char.patch b/queue-4.20/uart-fix-crash-in-uart_write-and-uart_put_char.patch new file mode 100644 index 00000000000..1e7a49ec9ea --- /dev/null +++ b/queue-4.20/uart-fix-crash-in-uart_write-and-uart_put_char.patch @@ -0,0 +1,98 @@ +From aff9cf5955185d1f183227e46c5f8673fa483813 Mon Sep 17 00:00:00 2001 +From: Samir Virmani +Date: Wed, 16 Jan 2019 10:28:07 -0800 +Subject: uart: Fix crash in uart_write and uart_put_char + +From: Samir Virmani + +commit aff9cf5955185d1f183227e46c5f8673fa483813 upstream. + +We were experiencing a crash similar to the one reported as part of +commit:a5ba1d95e46e ("uart: fix race between uart_put_char() and +uart_shutdown()") in our testbed as well. We continue to observe the same +crash after integrating the commit a5ba1d95e46e ("uart: fix race between +uart_put_char() and uart_shutdown()") + +On reviewing the change, the port lock should be taken prior to checking for +if (!circ->buf) in fn. __uart_put_char and other fns. that update the buffer +uart_state->xmit. + +Traceback: + +[11/27/2018 06:24:32.4870] Unable to handle kernel NULL pointer dereference + at virtual address 0000003b + +[11/27/2018 06:24:32.4950] PC is at memcpy+0x48/0x180 +[11/27/2018 06:24:32.4950] LR is at uart_write+0x74/0x120 +[11/27/2018 06:24:32.4950] pc : [] + lr : [] pstate: 000001c5 +[11/27/2018 06:24:32.4950] sp : ffffffc076433d30 +[11/27/2018 06:24:32.4950] x29: ffffffc076433d30 x28: 0000000000000140 +[11/27/2018 06:24:32.4950] x27: ffffffc0009b9d5e x26: ffffffc07ce36580 +[11/27/2018 06:24:32.4950] x25: 0000000000000000 x24: 0000000000000140 +[11/27/2018 06:24:32.4950] x23: ffffffc000891200 x22: ffffffc01fc34000 +[11/27/2018 06:24:32.4950] x21: 0000000000000fff x20: 0000000000000076 +[11/27/2018 06:24:32.4950] x19: 0000000000000076 x18: 0000000000000000 +[11/27/2018 06:24:32.4950] x17: 000000000047cf08 x16: ffffffc000099e68 +[11/27/2018 06:24:32.4950] x15: 0000000000000018 x14: 776d726966205948 +[11/27/2018 06:24:32.4950] x13: 50203a6c6974755f x12: 74647075205d3333 +[11/27/2018 06:24:32.4950] x11: 3a35323a36203831 x10: 30322f37322f3131 +[11/27/2018 06:24:32.4950] x9 : 5b205d303638342e x8 : 746164206f742070 +[11/27/2018 06:24:32.4950] x7 : 7520736920657261 x6 : 000000000000003b +[11/27/2018 06:24:32.4950] x5 : 000000000000817a x4 : 0000000000000008 +[11/27/2018 06:24:32.4950] x3 : 2f37322f31312a5b x2 : 000000000000006e +[11/27/2018 06:24:32.4950] x1 : ffffffc0009b9cf0 x0 : 000000000000003b + +[11/27/2018 06:24:32.4950] CPU2: stopping +[11/27/2018 06:24:32.4950] CPU: 2 PID: 0 Comm: swapper/2 Tainted: P D O 4.1.51 #3 +[11/27/2018 06:24:32.4950] Hardware name: Broadcom-v8A (DT) +[11/27/2018 06:24:32.4950] Call trace: +[11/27/2018 06:24:32.4950] [] dump_backtrace+0x0/0x150 +[11/27/2018 06:24:32.4950] [] show_stack+0x14/0x20 +[11/27/2018 06:24:32.4950] [] dump_stack+0x90/0xb0 +[11/27/2018 06:24:32.4950] [] handle_IPI+0x18c/0x1a0 +[11/27/2018 06:24:32.4950] [] gic_handle_irq+0x88/0x90 + +Fixes: a5ba1d95e46e ("uart: fix race between uart_put_char() and uart_shutdown()") +Cc: stable +Signed-off-by: Samir Virmani +Acked-by: Tycho Andersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/serial_core.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -550,10 +550,12 @@ static int uart_put_char(struct tty_stru + int ret = 0; + + circ = &state->xmit; +- if (!circ->buf) ++ port = uart_port_lock(state, flags); ++ if (!circ->buf) { ++ uart_port_unlock(port, flags); + return 0; ++ } + +- port = uart_port_lock(state, flags); + if (port && uart_circ_chars_free(circ) != 0) { + circ->buf[circ->head] = c; + circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1); +@@ -586,11 +588,13 @@ static int uart_write(struct tty_struct + return -EL3HLT; + } + ++ port = uart_port_lock(state, flags); + circ = &state->xmit; +- if (!circ->buf) ++ if (!circ->buf) { ++ uart_port_unlock(port, flags); + return 0; ++ } + +- port = uart_port_lock(state, flags); + while (port) { + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); + if (count < c) diff --git a/queue-4.20/vgacon-unconfuse-vc_origin-when-using-soft-scrollback.patch b/queue-4.20/vgacon-unconfuse-vc_origin-when-using-soft-scrollback.patch new file mode 100644 index 00000000000..a2c9880a023 --- /dev/null +++ b/queue-4.20/vgacon-unconfuse-vc_origin-when-using-soft-scrollback.patch @@ -0,0 +1,71 @@ +From bfd8d8fe98b8792f362cd210a7873969f8d2fc04 Mon Sep 17 00:00:00 2001 +From: Nicolas Pitre +Date: Thu, 10 Jan 2019 16:33:55 -0500 +Subject: vgacon: unconfuse vc_origin when using soft scrollback + +From: Nicolas Pitre + +commit bfd8d8fe98b8792f362cd210a7873969f8d2fc04 upstream. + +When CONFIG_VGACON_SOFT_SCROLLBACK is selected, the VGA display memory +index and vc_visible_origin don't change when scrollback is activated. +The actual screen content is saved away and the scrollbackdata is copied +over it. However the vt code, and /dev/vcs devices in particular, still +expect vc_origin to always point at the actual screen content not the +displayed scrollback content. + +So adjust vc_origin to point at the saved screen content when scrollback +is active and set it back to vc_visible_origin when restoring the screen. + +This fixes /dev/vcsa that return scrollback content when they +shouldn't (onli /dev/vcsa without a number should), and also fixes +/dev/vcsu that should return scrollback content when scrollback is +active but currently doesn't. + +An unnecessary call to vga_set_mem_top() is also removed. + +Signed-off-by: Nicolas Pitre +Cc: stable@vger.kernel.org # v4.19+ +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/video/console/vgacon.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/video/console/vgacon.c ++++ b/drivers/video/console/vgacon.c +@@ -271,6 +271,7 @@ static void vgacon_scrollback_update(str + + static void vgacon_restore_screen(struct vc_data *c) + { ++ c->vc_origin = c->vc_visible_origin; + vgacon_scrollback_cur->save = 0; + + if (!vga_is_gfx && !vgacon_scrollback_cur->restore) { +@@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc + int start, end, count, soff; + + if (!lines) { +- c->vc_visible_origin = c->vc_origin; +- vga_set_mem_top(c); ++ vgacon_restore_screen(c); + return; + } + +@@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc + if (!vgacon_scrollback_cur->save) { + vgacon_cursor(c, CM_ERASE); + vgacon_save_screen(c); ++ c->vc_origin = (unsigned long)c->vc_screenbuf; + vgacon_scrollback_cur->save = 1; + } + +@@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc + int copysize; + + int diff = c->vc_rows - count; +- void *d = (void *) c->vc_origin; ++ void *d = (void *) c->vc_visible_origin; + void *s = (void *) c->vc_screenbuf; + + count *= c->vc_size_row;