From: Greg Kroah-Hartman Date: Tue, 28 Mar 2017 12:24:17 +0000 (+0200) Subject: 4.10-stable patches X-Git-Tag: v4.4.58~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a64ed160569f974f075702091c7476b628d26f24;p=thirdparty%2Fkernel%2Fstable-queue.git 4.10-stable patches added patches: crypto-algif_hash-avoid-zero-sized-array.patch drm-reference-count-event-completion.patch fbcon-fix-vc-attr-at-deinit.patch xen-do-not-re-use-pirq-number-cached-in-pci-device-msi-msg-data.patch --- diff --git a/queue-4.10/crypto-algif_hash-avoid-zero-sized-array.patch b/queue-4.10/crypto-algif_hash-avoid-zero-sized-array.patch new file mode 100644 index 00000000000..59a739c42a0 --- /dev/null +++ b/queue-4.10/crypto-algif_hash-avoid-zero-sized-array.patch @@ -0,0 +1,71 @@ +From 6207119444595d287b1e9e83a2066c17209698f3 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Thu, 15 Dec 2016 14:31:01 +0100 +Subject: crypto: algif_hash - avoid zero-sized array + +From: Jiri Slaby + +commit 6207119444595d287b1e9e83a2066c17209698f3 upstream. + +With this reproducer: + struct sockaddr_alg alg = { + .salg_family = 0x26, + .salg_type = "hash", + .salg_feat = 0xf, + .salg_mask = 0x5, + .salg_name = "digest_null", + }; + int sock, sock2; + + sock = socket(AF_ALG, SOCK_SEQPACKET, 0); + bind(sock, (struct sockaddr *)&alg, sizeof(alg)); + sock2 = accept(sock, NULL, NULL); + setsockopt(sock, SOL_ALG, ALG_SET_KEY, "\x9b\xca", 2); + accept(sock2, NULL, NULL); + +==== 8< ======== 8< ======== 8< ======== 8< ==== + +one can immediatelly see an UBSAN warning: +UBSAN: Undefined behaviour in crypto/algif_hash.c:187:7 +variable length array bound value 0 <= 0 +CPU: 0 PID: 15949 Comm: syz-executor Tainted: G E 4.4.30-0-default #1 +... +Call Trace: +... + [] ? __ubsan_handle_vla_bound_not_positive+0x13d/0x188 + [] ? __ubsan_handle_out_of_bounds+0x1bc/0x1bc + [] ? hash_accept+0x5bd/0x7d0 [algif_hash] + [] ? hash_accept_nokey+0x3f/0x51 [algif_hash] + [] ? hash_accept_parent_nokey+0x4a0/0x4a0 [algif_hash] + [] ? SyS_accept+0x2b/0x40 + +It is a correct warning, as hash state is propagated to accept as zero, +but creating a zero-length variable array is not allowed in C. + +Fix this as proposed by Herbert -- do "?: 1" on that site. No sizeof or +similar happens in the code there, so we just allocate one byte even +though we do not use the array. + +Signed-off-by: Jiri Slaby +Cc: Herbert Xu +Cc: "David S. Miller" (maintainer:CRYPTO API) +Reported-by: Sasha Levin +Signed-off-by: Herbert Xu +Cc: Arnd Bergmann +Signed-off-by: Greg Kroah-Hartman + +--- + crypto/algif_hash.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -245,7 +245,7 @@ static int hash_accept(struct socket *so + struct alg_sock *ask = alg_sk(sk); + struct hash_ctx *ctx = ask->private; + struct ahash_request *req = &ctx->req; +- char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))]; ++ char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req)) ? : 1]; + struct sock *sk2; + struct alg_sock *ask2; + struct hash_ctx *ctx2; diff --git a/queue-4.10/drm-reference-count-event-completion.patch b/queue-4.10/drm-reference-count-event-completion.patch new file mode 100644 index 00000000000..79cd8ea53ce --- /dev/null +++ b/queue-4.10/drm-reference-count-event-completion.patch @@ -0,0 +1,100 @@ +From 24835e442f289813aa568d142a755672a740503c Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Wed, 21 Dec 2016 11:23:30 +0100 +Subject: drm: reference count event->completion + +From: Daniel Vetter + +commit 24835e442f289813aa568d142a755672a740503c upstream. + +When writing the generic nonblocking commit code I assumed that +through clever lifetime management I can assure that the completion +(stored in drm_crtc_commit) only gets freed after it is completed. And +that worked. + +I also wanted to make nonblocking helpers resilient against driver +bugs, by having timeouts everywhere. And that worked too. + +Unfortunately taking boths things together results in oopses :( Well, +at least sometimes: What seems to happen is that the drm event hangs +around forever stuck in limbo land. The nonblocking helpers eventually +time out, move on and release it. Now the bug I tested all this +against is drivers that just entirely fail to deliver the vblank +events like they should, and in those cases the event is simply +leaked. But what seems to happen, at least sometimes, on i915 is that +the event is set up correctly, but somohow the vblank fails to fire in +time. Which means the event isn't leaked, it's still there waiting for +eventually a vblank to fire. That tends to happen when re-enabling the +pipe, and then the trap springs and the kernel oopses. + +The correct fix here is simply to refcount the crtc commit to make +sure that the event sticks around even for drivers which only +sometimes fail to deliver vblanks for some arbitrary reasons. Since +crtc commits are already refcounted that's easy to do. + +References: https://bugs.freedesktop.org/show_bug.cgi?id=96781 +Cc: Jim Rees +Cc: Chris Wilson +Cc: Maarten Lankhorst +Cc: Jani Nikula +Reviewed-by: Maarten Lankhorst +Signed-off-by: Daniel Vetter +Link: http://patchwork.freedesktop.org/patch/msgid/20161221102331.31033-1-daniel.vetter@ffwll.ch +Cc: Arnd Bergmann +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_atomic_helper.c | 11 +++++++++++ + drivers/gpu/drm/drm_fops.c | 2 +- + include/drm/drmP.h | 1 + + 3 files changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/drm_atomic_helper.c ++++ b/drivers/gpu/drm/drm_atomic_helper.c +@@ -1389,6 +1389,15 @@ static int stall_checks(struct drm_crtc + return ret < 0 ? ret : 0; + } + ++void release_crtc_commit(struct completion *completion) ++{ ++ struct drm_crtc_commit *commit = container_of(completion, ++ typeof(*commit), ++ flip_done); ++ ++ drm_crtc_commit_put(commit); ++} ++ + /** + * drm_atomic_helper_setup_commit - setup possibly nonblocking commit + * @state: new modeset state to be committed +@@ -1481,6 +1490,8 @@ int drm_atomic_helper_setup_commit(struc + } + + crtc_state->event->base.completion = &commit->flip_done; ++ crtc_state->event->base.completion_release = release_crtc_commit; ++ drm_crtc_commit_get(commit); + } + + return 0; +--- a/drivers/gpu/drm/drm_fops.c ++++ b/drivers/gpu/drm/drm_fops.c +@@ -689,8 +689,8 @@ void drm_send_event_locked(struct drm_de + assert_spin_locked(&dev->event_lock); + + if (e->completion) { +- /* ->completion might disappear as soon as it signalled. */ + complete_all(e->completion); ++ e->completion_release(e->completion); + e->completion = NULL; + } + +--- a/include/drm/drmP.h ++++ b/include/drm/drmP.h +@@ -360,6 +360,7 @@ struct drm_ioctl_desc { + /* Event queued up for userspace to read */ + struct drm_pending_event { + struct completion *completion; ++ void (*completion_release)(struct completion *completion); + struct drm_event *event; + struct dma_fence *fence; + struct list_head link; diff --git a/queue-4.10/fbcon-fix-vc-attr-at-deinit.patch b/queue-4.10/fbcon-fix-vc-attr-at-deinit.patch new file mode 100644 index 00000000000..e9b4d43c2a3 --- /dev/null +++ b/queue-4.10/fbcon-fix-vc-attr-at-deinit.patch @@ -0,0 +1,148 @@ +From 8aac7f34369726d1a158788ae8aff3002d5eb528 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Wed, 11 Jan 2017 17:09:50 +0100 +Subject: fbcon: Fix vc attr at deinit + +From: Takashi Iwai + +commit 8aac7f34369726d1a158788ae8aff3002d5eb528 upstream. + +fbcon can deal with vc_hi_font_mask (the upper 256 chars) and adjust +the vc attrs dynamically when vc_hi_font_mask is changed at +fbcon_init(). When the vc_hi_font_mask is set, it remaps the attrs in +the existing console buffer with one bit shift up (for 9 bits), while +it remaps with one bit shift down (for 8 bits) when the value is +cleared. It works fine as long as the font gets updated after fbcon +was initialized. + +However, we hit a bizarre problem when the console is switched to +another fb driver (typically from vesafb or efifb to drmfb). At +switching to the new fb driver, we temporarily rebind the console to +the dummy console, then rebind to the new driver. During the +switching, we leave the modified attrs as is. Thus, the new fbcon +takes over the old buffer as if it were to contain 8 bits chars +(although the attrs are still shifted for 9 bits), and effectively +this results in the yellow color texts instead of the original white +color, as found in the bugzilla entry below. + +An easy fix for this is to re-adjust the attrs before leaving the +fbcon at con_deinit callback. Since the code to adjust the attrs is +already present in the current fbcon code, in this patch, we simply +factor out the relevant code, and call it from fbcon_deinit(). + +Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1000619 +Signed-off-by: Takashi Iwai +Signed-off-by: Bartlomiej Zolnierkiewicz +Cc: Arnd Bergmann +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/video/console/fbcon.c | 67 +++++++++++++++++++++++++----------------- + 1 file changed, 40 insertions(+), 27 deletions(-) + +--- a/drivers/video/console/fbcon.c ++++ b/drivers/video/console/fbcon.c +@@ -1165,6 +1165,8 @@ static void fbcon_free_font(struct displ + p->userfont = 0; + } + ++static void set_vc_hi_font(struct vc_data *vc, bool set); ++ + static void fbcon_deinit(struct vc_data *vc) + { + struct display *p = &fb_display[vc->vc_num]; +@@ -1200,6 +1202,9 @@ finished: + if (free_font) + vc->vc_font.data = NULL; + ++ if (vc->vc_hi_font_mask) ++ set_vc_hi_font(vc, false); ++ + if (!con_is_bound(&fb_con)) + fbcon_exit(); + +@@ -2436,32 +2441,10 @@ static int fbcon_get_font(struct vc_data + return 0; + } + +-static int fbcon_do_set_font(struct vc_data *vc, int w, int h, +- const u8 * data, int userfont) ++/* set/clear vc_hi_font_mask and update vc attrs accordingly */ ++static void set_vc_hi_font(struct vc_data *vc, bool set) + { +- struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; +- struct fbcon_ops *ops = info->fbcon_par; +- struct display *p = &fb_display[vc->vc_num]; +- int resize; +- int cnt; +- char *old_data = NULL; +- +- if (con_is_visible(vc) && softback_lines) +- fbcon_set_origin(vc); +- +- resize = (w != vc->vc_font.width) || (h != vc->vc_font.height); +- if (p->userfont) +- old_data = vc->vc_font.data; +- if (userfont) +- cnt = FNTCHARCNT(data); +- else +- cnt = 256; +- vc->vc_font.data = (void *)(p->fontdata = data); +- if ((p->userfont = userfont)) +- REFCOUNT(data)++; +- vc->vc_font.width = w; +- vc->vc_font.height = h; +- if (vc->vc_hi_font_mask && cnt == 256) { ++ if (!set) { + vc->vc_hi_font_mask = 0; + if (vc->vc_can_do_color) { + vc->vc_complement_mask >>= 1; +@@ -2484,7 +2467,7 @@ static int fbcon_do_set_font(struct vc_d + ((c & 0xfe00) >> 1) | (c & 0xff); + vc->vc_attr >>= 1; + } +- } else if (!vc->vc_hi_font_mask && cnt == 512) { ++ } else { + vc->vc_hi_font_mask = 0x100; + if (vc->vc_can_do_color) { + vc->vc_complement_mask <<= 1; +@@ -2516,8 +2499,38 @@ static int fbcon_do_set_font(struct vc_d + } else + vc->vc_video_erase_char = c & ~0x100; + } +- + } ++} ++ ++static int fbcon_do_set_font(struct vc_data *vc, int w, int h, ++ const u8 * data, int userfont) ++{ ++ struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; ++ struct fbcon_ops *ops = info->fbcon_par; ++ struct display *p = &fb_display[vc->vc_num]; ++ int resize; ++ int cnt; ++ char *old_data = NULL; ++ ++ if (con_is_visible(vc) && softback_lines) ++ fbcon_set_origin(vc); ++ ++ resize = (w != vc->vc_font.width) || (h != vc->vc_font.height); ++ if (p->userfont) ++ old_data = vc->vc_font.data; ++ if (userfont) ++ cnt = FNTCHARCNT(data); ++ else ++ cnt = 256; ++ vc->vc_font.data = (void *)(p->fontdata = data); ++ if ((p->userfont = userfont)) ++ REFCOUNT(data)++; ++ vc->vc_font.width = w; ++ vc->vc_font.height = h; ++ if (vc->vc_hi_font_mask && cnt == 256) ++ set_vc_hi_font(vc, false); ++ else if (!vc->vc_hi_font_mask && cnt == 512) ++ set_vc_hi_font(vc, true); + + if (resize) { + int cols, rows; diff --git a/queue-4.10/series b/queue-4.10/series index 9bfe37e82fc..73d330d6a26 100644 --- a/queue-4.10/series +++ b/queue-4.10/series @@ -105,3 +105,7 @@ libceph-don-t-set-weight-to-in-when-osd-is-destroyed.patch device-dax-fix-pmd-pte-fault-fallback-handling.patch scsi-sd-check-for-unaligned-partial-completion.patch cpuidle-validate-cpu_dev-in-cpuidle_add_sysfs.patch +xen-do-not-re-use-pirq-number-cached-in-pci-device-msi-msg-data.patch +drm-reference-count-event-completion.patch +fbcon-fix-vc-attr-at-deinit.patch +crypto-algif_hash-avoid-zero-sized-array.patch diff --git a/queue-4.10/xen-do-not-re-use-pirq-number-cached-in-pci-device-msi-msg-data.patch b/queue-4.10/xen-do-not-re-use-pirq-number-cached-in-pci-device-msi-msg-data.patch new file mode 100644 index 00000000000..be415a1af61 --- /dev/null +++ b/queue-4.10/xen-do-not-re-use-pirq-number-cached-in-pci-device-msi-msg-data.patch @@ -0,0 +1,82 @@ +From c74fd80f2f41d05f350bb478151021f88551afe8 Mon Sep 17 00:00:00 2001 +From: Dan Streetman +Date: Fri, 13 Jan 2017 15:07:51 -0500 +Subject: xen: do not re-use pirq number cached in pci device msi msg data + +From: Dan Streetman + +commit c74fd80f2f41d05f350bb478151021f88551afe8 upstream. + +Revert the main part of commit: +af42b8d12f8a ("xen: fix MSI setup and teardown for PV on HVM guests") + +That commit introduced reading the pci device's msi message data to see +if a pirq was previously configured for the device's msi/msix, and re-use +that pirq. At the time, that was the correct behavior. However, a +later change to Qemu caused it to call into the Xen hypervisor to unmap +all pirqs for a pci device, when the pci device disables its MSI/MSIX +vectors; specifically the Qemu commit: +c976437c7dba9c7444fb41df45468968aaa326ad +("qemu-xen: free all the pirqs for msi/msix when driver unload") + +Once Qemu added this pirq unmapping, it was no longer correct for the +kernel to re-use the pirq number cached in the pci device msi message +data. All Qemu releases since 2.1.0 contain the patch that unmaps the +pirqs when the pci device disables its MSI/MSIX vectors. + +This bug is causing failures to initialize multiple NVMe controllers +under Xen, because the NVMe driver sets up a single MSIX vector for +each controller (concurrently), and then after using that to talk to +the controller for some configuration data, it disables the single MSIX +vector and re-configures all the MSIX vectors it needs. So the MSIX +setup code tries to re-use the cached pirq from the first vector +for each controller, but the hypervisor has already given away that +pirq to another controller, and its initialization fails. + +This is discussed in more detail at: +https://lists.xen.org/archives/html/xen-devel/2017-01/msg00447.html + +Fixes: af42b8d12f8a ("xen: fix MSI setup and teardown for PV on HVM guests") +Signed-off-by: Dan Streetman +Reviewed-by: Stefano Stabellini +Acked-by: Konrad Rzeszutek Wilk +Signed-off-by: Boris Ostrovsky +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/pci/xen.c | 23 +++++++---------------- + 1 file changed, 7 insertions(+), 16 deletions(-) + +--- a/arch/x86/pci/xen.c ++++ b/arch/x86/pci/xen.c +@@ -234,23 +234,14 @@ static int xen_hvm_setup_msi_irqs(struct + return 1; + + for_each_pci_msi_entry(msidesc, dev) { +- __pci_read_msi_msg(msidesc, &msg); +- pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | +- ((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff); +- if (msg.data != XEN_PIRQ_MSI_DATA || +- xen_irq_from_pirq(pirq) < 0) { +- pirq = xen_allocate_pirq_msi(dev, msidesc); +- if (pirq < 0) { +- irq = -ENODEV; +- goto error; +- } +- xen_msi_compose_msg(dev, pirq, &msg); +- __pci_write_msi_msg(msidesc, &msg); +- dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); +- } else { +- dev_dbg(&dev->dev, +- "xen: msi already bound to pirq=%d\n", pirq); ++ pirq = xen_allocate_pirq_msi(dev, msidesc); ++ if (pirq < 0) { ++ irq = -ENODEV; ++ goto error; + } ++ xen_msi_compose_msg(dev, pirq, &msg); ++ __pci_write_msi_msg(msidesc, &msg); ++ dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq); + irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, + (type == PCI_CAP_ID_MSI) ? nvec : 1, + (type == PCI_CAP_ID_MSIX) ?