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

queue-4.9/crypto-algif_hash-avoid-zero-sized-array.patch [new file with mode: 0644]
queue-4.9/drm-reference-count-event-completion.patch [new file with mode: 0644]
queue-4.9/fbcon-fix-vc-attr-at-deinit.patch [new file with mode: 0644]
queue-4.9/series

diff --git a/queue-4.9/crypto-algif_hash-avoid-zero-sized-array.patch b/queue-4.9/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.9/drm-reference-count-event-completion.patch b/queue-4.9/drm-reference-count-event-completion.patch
new file mode 100644 (file)
index 0000000..f2968ee
--- /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
+@@ -1382,6 +1382,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
+@@ -1474,6 +1483,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
+@@ -686,8 +686,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
+@@ -361,6 +361,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 fence *fence;
+       struct list_head link;
diff --git a/queue-4.9/fbcon-fix-vc-attr-at-deinit.patch b/queue-4.9/fbcon-fix-vc-attr-at-deinit.patch
new file mode 100644 (file)
index 0000000..ae31c17
--- /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
+@@ -1167,6 +1167,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];
+@@ -1202,6 +1204,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();
+@@ -2438,32 +2443,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;
+@@ -2486,7 +2469,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;
+@@ -2518,8 +2501,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 79867b0a75b728435525d3ac656862f5b429023b..f6007a0b6804ab9818b8ccad7a073086c061cca5 100644 (file)
@@ -83,3 +83,6 @@ libceph-don-t-set-weight-to-in-when-osd-is-destroyed.patch
 device-dax-fix-pmd-pte-fault-fallback-handling.patch
 drm-bridge-analogix-dp-fix-runtime-pm-state-on-driver-bind.patch
 nl80211-fix-dumpit-error-path-rtnl-deadlocks.patch
+drm-reference-count-event-completion.patch
+fbcon-fix-vc-attr-at-deinit.patch
+crypto-algif_hash-avoid-zero-sized-array.patch