]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 28 Mar 2017 12:24:17 +0000 (14:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 28 Mar 2017 12:24:17 +0000 (14:24 +0200)
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

queue-4.10/crypto-algif_hash-avoid-zero-sized-array.patch [new file with mode: 0644]
queue-4.10/drm-reference-count-event-completion.patch [new file with mode: 0644]
queue-4.10/fbcon-fix-vc-attr-at-deinit.patch [new file with mode: 0644]
queue-4.10/series
queue-4.10/xen-do-not-re-use-pirq-number-cached-in-pci-device-msi-msg-data.patch [new file with mode: 0644]

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 (file)
index 0000000..59a739c
--- /dev/null
@@ -0,0 +1,71 @@
+From 6207119444595d287b1e9e83a2066c17209698f3 Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jslaby@suse.cz>
+Date: Thu, 15 Dec 2016 14:31:01 +0100
+Subject: crypto: algif_hash - avoid zero-sized array
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+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:
+...
+ [<ffffffff81d598fd>] ? __ubsan_handle_vla_bound_not_positive+0x13d/0x188
+ [<ffffffff81d597c0>] ? __ubsan_handle_out_of_bounds+0x1bc/0x1bc
+ [<ffffffffa0e2204d>] ? hash_accept+0x5bd/0x7d0 [algif_hash]
+ [<ffffffffa0e2293f>] ? hash_accept_nokey+0x3f/0x51 [algif_hash]
+ [<ffffffffa0e206b0>] ? hash_accept_parent_nokey+0x4a0/0x4a0 [algif_hash]
+ [<ffffffff8235c42b>] ? 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 <jslaby@suse.cz>
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: "David S. Miller" <davem@davemloft.net> (maintainer:CRYPTO API)
+Reported-by: Sasha Levin <sasha.levin@oracle.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..79cd8ea
--- /dev/null
@@ -0,0 +1,100 @@
+From 24835e442f289813aa568d142a755672a740503c Mon Sep 17 00:00:00 2001
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+Date: Wed, 21 Dec 2016 11:23:30 +0100
+Subject: drm: reference count event->completion
+
+From: Daniel Vetter <daniel.vetter@ffwll.ch>
+
+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 <rees@umich.edu>
+Cc: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Cc: Jani Nikula <jani.nikula@linux.intel.com>
+Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
+Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
+Link: http://patchwork.freedesktop.org/patch/msgid/20161221102331.31033-1-daniel.vetter@ffwll.ch
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..e9b4d43
--- /dev/null
@@ -0,0 +1,148 @@
+From 8aac7f34369726d1a158788ae8aff3002d5eb528 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 11 Jan 2017 17:09:50 +0100
+Subject: fbcon: Fix vc attr at deinit
+
+From: Takashi Iwai <tiwai@suse.de>
+
+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 <tiwai@suse.de>
+Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
index 9bfe37e82fc9b96672fe592d2ede24cfd80ec93b..73d330d6a26f289f3e834bc5a4d9faaa90a1d2e1 100644 (file)
@@ -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 (file)
index 0000000..be415a1
--- /dev/null
@@ -0,0 +1,82 @@
+From c74fd80f2f41d05f350bb478151021f88551afe8 Mon Sep 17 00:00:00 2001
+From: Dan Streetman <ddstreet@ieee.org>
+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 <ddstreet@ieee.org>
+
+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 <dan.streetman@canonical.com>
+Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
+Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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) ?