]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 May 2017 12:22:09 +0000 (14:22 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 May 2017 12:22:09 +0000 (14:22 +0200)
added patches:
af_unix-guard-against-other-sk-in-unix_dgram_sendmsg.patch
alsa-seq-fix-race-at-timer-setup-and-close.patch
alsa-timer-fix-leak-in-events-via-snd_timer_user_ccallback.patch
alsa-timer-fix-leak-in-events-via-snd_timer_user_tinterrupt.patch
alsa-timer-fix-leak-in-sndrv_timer_ioctl_params.patch
alsa-timer-fix-race-among-timer-ioctls.patch
cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_bind.patch
hid-core-prevent-out-of-bound-readings.patch
ipv6-sctp-add-rcu-protection-around-np-opt.patch
ipv6-sctp-fix-lockdep-splat-in-sctp_v6_get_dst.patch
net-ipv6-add-sysctl-option-accept_ra_min_hop_limit.patch
ppp-defer-netns-reference-release-for-ppp-channel.patch
sched-panic-on-corrupted-stack-end.patch
sg-fix-double-free-when-drives-detach-during-sg_io.patch

15 files changed:
queue-3.18/af_unix-guard-against-other-sk-in-unix_dgram_sendmsg.patch [new file with mode: 0644]
queue-3.18/alsa-seq-fix-race-at-timer-setup-and-close.patch [new file with mode: 0644]
queue-3.18/alsa-timer-fix-leak-in-events-via-snd_timer_user_ccallback.patch [new file with mode: 0644]
queue-3.18/alsa-timer-fix-leak-in-events-via-snd_timer_user_tinterrupt.patch [new file with mode: 0644]
queue-3.18/alsa-timer-fix-leak-in-sndrv_timer_ioctl_params.patch [new file with mode: 0644]
queue-3.18/alsa-timer-fix-race-among-timer-ioctls.patch [new file with mode: 0644]
queue-3.18/cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_bind.patch [new file with mode: 0644]
queue-3.18/hid-core-prevent-out-of-bound-readings.patch [new file with mode: 0644]
queue-3.18/ipv6-sctp-add-rcu-protection-around-np-opt.patch [new file with mode: 0644]
queue-3.18/ipv6-sctp-fix-lockdep-splat-in-sctp_v6_get_dst.patch [new file with mode: 0644]
queue-3.18/net-ipv6-add-sysctl-option-accept_ra_min_hop_limit.patch [new file with mode: 0644]
queue-3.18/ppp-defer-netns-reference-release-for-ppp-channel.patch [new file with mode: 0644]
queue-3.18/sched-panic-on-corrupted-stack-end.patch [new file with mode: 0644]
queue-3.18/series
queue-3.18/sg-fix-double-free-when-drives-detach-during-sg_io.patch [new file with mode: 0644]

diff --git a/queue-3.18/af_unix-guard-against-other-sk-in-unix_dgram_sendmsg.patch b/queue-3.18/af_unix-guard-against-other-sk-in-unix_dgram_sendmsg.patch
new file mode 100644 (file)
index 0000000..f528ed9
--- /dev/null
@@ -0,0 +1,52 @@
+From a5527dda344fff0514b7989ef7a755729769daa1 Mon Sep 17 00:00:00 2001
+From: Rainer Weikusat <rweikusat@mobileactivedefense.com>
+Date: Thu, 11 Feb 2016 19:37:27 +0000
+Subject: af_unix: Guard against other == sk in unix_dgram_sendmsg
+
+From: Rainer Weikusat <rweikusat@mobileactivedefense.com>
+
+commit a5527dda344fff0514b7989ef7a755729769daa1 upstream.
+
+The unix_dgram_sendmsg routine use the following test
+
+if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
+
+to determine if sk and other are in an n:1 association (either
+established via connect or by using sendto to send messages to an
+unrelated socket identified by address). This isn't correct as the
+specified address could have been bound to the sending socket itself or
+because this socket could have been connected to itself by the time of
+the unix_peer_get but disconnected before the unix_state_lock(other). In
+both cases, the if-block would be entered despite other == sk which
+might either block the sender unintentionally or lead to trying to unlock
+the same spin lock twice for a non-blocking send. Add a other != sk
+check to guard against this.
+
+Fixes: 7d267278a9ec ("unix: avoid use-after-free in ep_remove_wait_queue")
+Reported-By: Philipp Hahn <pmhahn@pmhahn.de>
+Signed-off-by: Rainer Weikusat <rweikusat@mobileactivedefense.com>
+Tested-by: Philipp Hahn <pmhahn@pmhahn.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/unix/af_unix.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1722,7 +1722,12 @@ restart_locked:
+                       goto out_unlock;
+       }
+-      if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
++      /* other == sk && unix_peer(other) != sk if
++       * - unix_peer(sk) == NULL, destination address bound to sk
++       * - unix_peer(sk) == sk by time of get but disconnected before lock
++       */
++      if (other != sk &&
++          unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
+               if (timeo) {
+                       timeo = unix_wait_for_peer(other, timeo);
diff --git a/queue-3.18/alsa-seq-fix-race-at-timer-setup-and-close.patch b/queue-3.18/alsa-seq-fix-race-at-timer-setup-and-close.patch
new file mode 100644 (file)
index 0000000..7d8012f
--- /dev/null
@@ -0,0 +1,39 @@
+From 3567eb6af614dac436c4b16a8d426f9faed639b3 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 12 Jan 2016 15:36:27 +0100
+Subject: ALSA: seq: Fix race at timer setup and close
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 3567eb6af614dac436c4b16a8d426f9faed639b3 upstream.
+
+ALSA sequencer code has an open race between the timer setup ioctl and
+the close of the client.  This was triggered by syzkaller fuzzer, and
+a use-after-free was caught there as a result.
+
+This patch papers over it by adding a proper queue->timer_mutex lock
+around the timer-related calls in the relevant code path.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/seq/seq_queue.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/core/seq/seq_queue.c
++++ b/sound/core/seq/seq_queue.c
+@@ -142,8 +142,10 @@ static struct snd_seq_queue *queue_new(i
+ static void queue_delete(struct snd_seq_queue *q)
+ {
+       /* stop and release the timer */
++      mutex_lock(&q->timer_mutex);
+       snd_seq_timer_stop(q->timer);
+       snd_seq_timer_close(q);
++      mutex_unlock(&q->timer_mutex);
+       /* wait until access free */
+       snd_use_lock_sync(&q->use_lock);
+       /* release resources... */
diff --git a/queue-3.18/alsa-timer-fix-leak-in-events-via-snd_timer_user_ccallback.patch b/queue-3.18/alsa-timer-fix-leak-in-events-via-snd_timer_user_ccallback.patch
new file mode 100644 (file)
index 0000000..122dc85
--- /dev/null
@@ -0,0 +1,35 @@
+From 9a47e9cff994f37f7f0dbd9ae23740d0f64f9fe6 Mon Sep 17 00:00:00 2001
+From: Kangjie Lu <kangjielu@gmail.com>
+Date: Tue, 3 May 2016 16:44:20 -0400
+Subject: ALSA: timer: Fix leak in events via snd_timer_user_ccallback
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kangjie Lu <kangjielu@gmail.com>
+
+commit 9a47e9cff994f37f7f0dbd9ae23740d0f64f9fe6 upstream.
+
+The stack object “r1” has a total size of 32 bytes. Its field
+“event” and “val” both contain 4 bytes padding. These 8 bytes
+padding bytes are sent to user without being initialized.
+
+Signed-off-by: Kangjie Lu <kjlu@gatech.edu>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -1260,6 +1260,7 @@ static void snd_timer_user_ccallback(str
+               tu->tstamp = *tstamp;
+       if ((tu->filter & (1 << event)) == 0 || !tu->tread)
+               return;
++      memset(&r1, 0, sizeof(r1));
+       r1.event = event;
+       r1.tstamp = *tstamp;
+       r1.val = resolution;
diff --git a/queue-3.18/alsa-timer-fix-leak-in-events-via-snd_timer_user_tinterrupt.patch b/queue-3.18/alsa-timer-fix-leak-in-events-via-snd_timer_user_tinterrupt.patch
new file mode 100644 (file)
index 0000000..9ea6cb6
--- /dev/null
@@ -0,0 +1,35 @@
+From e4ec8cc8039a7063e24204299b462bd1383184a5 Mon Sep 17 00:00:00 2001
+From: Kangjie Lu <kangjielu@gmail.com>
+Date: Tue, 3 May 2016 16:44:32 -0400
+Subject: ALSA: timer: Fix leak in events via snd_timer_user_tinterrupt
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kangjie Lu <kangjielu@gmail.com>
+
+commit e4ec8cc8039a7063e24204299b462bd1383184a5 upstream.
+
+The stack object “r1” has a total size of 32 bytes. Its field
+“event” and “val” both contain 4 bytes padding. These 8 bytes
+padding bytes are sent to user without being initialized.
+
+Signed-off-by: Kangjie Lu <kjlu@gatech.edu>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -1295,6 +1295,7 @@ static void snd_timer_user_tinterrupt(st
+       }
+       if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
+           tu->last_resolution != resolution) {
++              memset(&r1, 0, sizeof(r1));
+               r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
+               r1.tstamp = tstamp;
+               r1.val = resolution;
diff --git a/queue-3.18/alsa-timer-fix-leak-in-sndrv_timer_ioctl_params.patch b/queue-3.18/alsa-timer-fix-leak-in-sndrv_timer_ioctl_params.patch
new file mode 100644 (file)
index 0000000..ceb1fee
--- /dev/null
@@ -0,0 +1,35 @@
+From cec8f96e49d9be372fdb0c3836dcf31ec71e457e Mon Sep 17 00:00:00 2001
+From: Kangjie Lu <kangjielu@gmail.com>
+Date: Tue, 3 May 2016 16:44:07 -0400
+Subject: ALSA: timer: Fix leak in SNDRV_TIMER_IOCTL_PARAMS
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kangjie Lu <kangjielu@gmail.com>
+
+commit cec8f96e49d9be372fdb0c3836dcf31ec71e457e upstream.
+
+The stack object “tread” has a total size of 32 bytes. Its field
+“event” and “val” both contain 4 bytes padding. These 8 bytes
+padding bytes are sent to user without being initialized.
+
+Signed-off-by: Kangjie Lu <kjlu@gatech.edu>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -1759,6 +1759,7 @@ static int snd_timer_user_params(struct
+       if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
+               if (tu->tread) {
+                       struct snd_timer_tread tread;
++                      memset(&tread, 0, sizeof(tread));
+                       tread.event = SNDRV_TIMER_EVENT_EARLY;
+                       tread.tstamp.tv_sec = 0;
+                       tread.tstamp.tv_nsec = 0;
diff --git a/queue-3.18/alsa-timer-fix-race-among-timer-ioctls.patch b/queue-3.18/alsa-timer-fix-race-among-timer-ioctls.patch
new file mode 100644 (file)
index 0000000..4338145
--- /dev/null
@@ -0,0 +1,123 @@
+From af368027a49a751d6ff4ee9e3f9961f35bb4fede Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 13 Jan 2016 17:48:01 +0100
+Subject: ALSA: timer: Fix race among timer ioctls
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit af368027a49a751d6ff4ee9e3f9961f35bb4fede upstream.
+
+ALSA timer ioctls have an open race and this may lead to a
+use-after-free of timer instance object.  A simplistic fix is to make
+each ioctl exclusive.  We have already tread_sem for controlling the
+tread, and extend this as a global mutex to be applied to each ioctl.
+
+The downside is, of course, the worse concurrency.  But these ioctls
+aren't to be parallel accessible, in anyway, so it should be fine to
+serialize there.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |   32 +++++++++++++++++++-------------
+ 1 file changed, 19 insertions(+), 13 deletions(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -77,7 +77,7 @@ struct snd_timer_user {
+       struct timespec tstamp;         /* trigger tstamp */
+       wait_queue_head_t qchange_sleep;
+       struct fasync_struct *fasync;
+-      struct mutex tread_sem;
++      struct mutex ioctl_lock;
+ };
+ /* list of timers */
+@@ -1342,7 +1342,7 @@ static int snd_timer_user_open(struct in
+               return -ENOMEM;
+       spin_lock_init(&tu->qlock);
+       init_waitqueue_head(&tu->qchange_sleep);
+-      mutex_init(&tu->tread_sem);
++      mutex_init(&tu->ioctl_lock);
+       tu->ticks = 1;
+       tu->queue_size = 128;
+       tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
+@@ -1362,8 +1362,10 @@ static int snd_timer_user_release(struct
+       if (file->private_data) {
+               tu = file->private_data;
+               file->private_data = NULL;
++              mutex_lock(&tu->ioctl_lock);
+               if (tu->timeri)
+                       snd_timer_close(tu->timeri);
++              mutex_unlock(&tu->ioctl_lock);
+               kfree(tu->queue);
+               kfree(tu->tqueue);
+               kfree(tu);
+@@ -1601,7 +1603,6 @@ static int snd_timer_user_tselect(struct
+       int err = 0;
+       tu = file->private_data;
+-      mutex_lock(&tu->tread_sem);
+       if (tu->timeri) {
+               snd_timer_close(tu->timeri);
+               tu->timeri = NULL;
+@@ -1645,7 +1646,6 @@ static int snd_timer_user_tselect(struct
+       }
+       __err:
+-              mutex_unlock(&tu->tread_sem);
+       return err;
+ }
+@@ -1861,7 +1861,7 @@ enum {
+       SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
+ };
+-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
++static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+                                unsigned long arg)
+ {
+       struct snd_timer_user *tu;
+@@ -1878,17 +1878,11 @@ static long snd_timer_user_ioctl(struct
+       {
+               int xarg;
+-              mutex_lock(&tu->tread_sem);
+-              if (tu->timeri) {       /* too late */
+-                      mutex_unlock(&tu->tread_sem);
++              if (tu->timeri) /* too late */
+                       return -EBUSY;
+-              }
+-              if (get_user(xarg, p)) {
+-                      mutex_unlock(&tu->tread_sem);
++              if (get_user(xarg, p))
+                       return -EFAULT;
+-              }
+               tu->tread = xarg ? 1 : 0;
+-              mutex_unlock(&tu->tread_sem);
+               return 0;
+       }
+       case SNDRV_TIMER_IOCTL_GINFO:
+@@ -1921,6 +1915,18 @@ static long snd_timer_user_ioctl(struct
+       return -ENOTTY;
+ }
++static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
++                               unsigned long arg)
++{
++      struct snd_timer_user *tu = file->private_data;
++      long ret;
++
++      mutex_lock(&tu->ioctl_lock);
++      ret = __snd_timer_user_ioctl(file, cmd, arg);
++      mutex_unlock(&tu->ioctl_lock);
++      return ret;
++}
++
+ static int snd_timer_user_fasync(int fd, struct file * file, int on)
+ {
+       struct snd_timer_user *tu;
diff --git a/queue-3.18/cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_bind.patch b/queue-3.18/cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_bind.patch
new file mode 100644 (file)
index 0000000..6ec7945
--- /dev/null
@@ -0,0 +1,86 @@
+From 4d06dd537f95683aba3651098ae288b7cbff8274 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Mon, 7 Mar 2016 21:15:36 +0100
+Subject: cdc_ncm: do not call usbnet_link_change from cdc_ncm_bind
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bjørn Mork <bjorn@mork.no>
+
+commit 4d06dd537f95683aba3651098ae288b7cbff8274 upstream.
+
+usbnet_link_change will call schedule_work and should be
+avoided if bind is failing. Otherwise we will end up with
+scheduled work referring to a netdev which has gone away.
+
+Instead of making the call conditional, we can just defer
+it to usbnet_probe, using the driver_info flag made for
+this purpose.
+
+Fixes: 8a34b0ae8778 ("usbnet: cdc_ncm: apply usbnet_link_change")
+Reported-by: Andrey Konovalov <andreyknvl@gmail.com>
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/cdc_ncm.c |   20 +++++---------------
+ 1 file changed, 5 insertions(+), 15 deletions(-)
+
+--- a/drivers/net/usb/cdc_ncm.c
++++ b/drivers/net/usb/cdc_ncm.c
+@@ -952,23 +952,12 @@ EXPORT_SYMBOL_GPL(cdc_ncm_select_altsett
+ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+ {
+-      int ret;
+-
+       /* MBIM backwards compatible function? */
+       if (cdc_ncm_select_altsetting(intf) != CDC_NCM_COMM_ALTSETTING_NCM)
+               return -ENODEV;
+       /* The NCM data altsetting is fixed */
+-      ret = cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM);
+-
+-      /*
+-       * We should get an event when network connection is "connected" or
+-       * "disconnected". Set network connection in "disconnected" state
+-       * (carrier is OFF) during attach, so the IP network stack does not
+-       * start IPv6 negotiation and more.
+-       */
+-      usbnet_link_change(dev, 0, 0);
+-      return ret;
++      return cdc_ncm_bind_common(dev, intf, CDC_NCM_DATA_ALTSETTING_NCM);
+ }
+ static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
+@@ -1510,7 +1499,8 @@ static void cdc_ncm_status(struct usbnet
+ static const struct driver_info cdc_ncm_info = {
+       .description = "CDC NCM",
+-      .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET,
++      .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
++                      | FLAG_LINK_INTR,
+       .bind = cdc_ncm_bind,
+       .unbind = cdc_ncm_unbind,
+       .manage_power = usbnet_manage_power,
+@@ -1523,7 +1513,7 @@ static const struct driver_info cdc_ncm_
+ static const struct driver_info wwan_info = {
+       .description = "Mobile Broadband Network Device",
+       .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
+-                      | FLAG_WWAN,
++                      | FLAG_LINK_INTR | FLAG_WWAN,
+       .bind = cdc_ncm_bind,
+       .unbind = cdc_ncm_unbind,
+       .manage_power = usbnet_manage_power,
+@@ -1536,7 +1526,7 @@ static const struct driver_info wwan_inf
+ static const struct driver_info wwan_noarp_info = {
+       .description = "Mobile Broadband Network Device (NO ARP)",
+       .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
+-                      | FLAG_WWAN | FLAG_NOARP,
++                      | FLAG_LINK_INTR | FLAG_WWAN | FLAG_NOARP,
+       .bind = cdc_ncm_bind,
+       .unbind = cdc_ncm_unbind,
+       .manage_power = usbnet_manage_power,
diff --git a/queue-3.18/hid-core-prevent-out-of-bound-readings.patch b/queue-3.18/hid-core-prevent-out-of-bound-readings.patch
new file mode 100644 (file)
index 0000000..de92f33
--- /dev/null
@@ -0,0 +1,49 @@
+From 50220dead1650609206efe91f0cc116132d59b3f Mon Sep 17 00:00:00 2001
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Date: Tue, 19 Jan 2016 12:34:58 +0100
+Subject: HID: core: prevent out-of-bound readings
+
+From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+
+commit 50220dead1650609206efe91f0cc116132d59b3f upstream.
+
+Plugging a Logitech DJ receiver with KASAN activated raises a bunch of
+out-of-bound readings.
+
+The fields are allocated up to MAX_USAGE, meaning that potentially, we do
+not have enough fields to fit the incoming values.
+Add checks and silence KASAN.
+
+Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-core.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1213,6 +1213,7 @@ static void hid_input_field(struct hid_d
+               /* Ignore report if ErrorRollOver */
+               if (!(field->flags & HID_MAIN_ITEM_VARIABLE) &&
+                   value[n] >= min && value[n] <= max &&
++                  value[n] - min < field->maxusage &&
+                   field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1)
+                       goto exit;
+       }
+@@ -1225,11 +1226,13 @@ static void hid_input_field(struct hid_d
+               }
+               if (field->value[n] >= min && field->value[n] <= max
++                      && field->value[n] - min < field->maxusage
+                       && field->usage[field->value[n] - min].hid
+                       && search(value, field->value[n], count))
+                               hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt);
+               if (value[n] >= min && value[n] <= max
++                      && value[n] - min < field->maxusage
+                       && field->usage[value[n] - min].hid
+                       && search(field->value, value[n], count))
+                               hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt);
diff --git a/queue-3.18/ipv6-sctp-add-rcu-protection-around-np-opt.patch b/queue-3.18/ipv6-sctp-add-rcu-protection-around-np-opt.patch
new file mode 100644 (file)
index 0000000..e1312aa
--- /dev/null
@@ -0,0 +1,68 @@
+From c836a8ba93869d6a0290a6ae0047fbef09066871 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 2 Dec 2015 21:48:14 -0800
+Subject: ipv6: sctp: add rcu protection around np->opt
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit c836a8ba93869d6a0290a6ae0047fbef09066871 upstream.
+
+This patch completes the work I did in commit 45f6fad84cc3
+("ipv6: add complete rcu protection around np->opt"), as I missed
+sctp part.
+
+This simply makes sure np->opt is used with proper RCU locking
+and accessors.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sctp/ipv6.c |   13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -209,6 +209,7 @@ static int sctp_v6_xmit(struct sk_buff *
+       struct sock *sk = skb->sk;
+       struct ipv6_pinfo *np = inet6_sk(sk);
+       struct flowi6 *fl6 = &transport->fl.u.ip6;
++      int res;
+       pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb,
+                skb->len, &fl6->saddr, &fl6->daddr);
+@@ -220,7 +221,10 @@ static int sctp_v6_xmit(struct sk_buff *
+       SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
+-      return ip6_xmit(sk, skb, fl6, np->opt, np->tclass);
++      rcu_read_lock();
++      res = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), np->tclass);
++      rcu_read_unlock();
++      return res;
+ }
+ /* Returns the dst cache entry for the given source and destination ip
+@@ -262,7 +266,10 @@ static void sctp_v6_get_dst(struct sctp_
+               pr_debug("src=%pI6 - ", &fl6->saddr);
+       }
+-      final_p = fl6_update_dst(fl6, np->opt, &final);
++      rcu_read_lock();
++      final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
++      rcu_read_unlock();
++
+       dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+       if (!asoc || saddr)
+               goto out;
+@@ -321,7 +328,7 @@ static void sctp_v6_get_dst(struct sctp_
+       if (baddr) {
+               fl6->saddr = baddr->v6.sin6_addr;
+               fl6->fl6_sport = baddr->v6.sin6_port;
+-              final_p = fl6_update_dst(fl6, np->opt, &final);
++              final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
+               dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+       }
diff --git a/queue-3.18/ipv6-sctp-fix-lockdep-splat-in-sctp_v6_get_dst.patch b/queue-3.18/ipv6-sctp-fix-lockdep-splat-in-sctp_v6_get_dst.patch
new file mode 100644 (file)
index 0000000..095082d
--- /dev/null
@@ -0,0 +1,44 @@
+From 69ce6487dcd364245a3d26322fc8f4ffd1e8d947 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 7 Dec 2015 08:25:21 -0800
+Subject: ipv6: sctp: fix lockdep splat in sctp_v6_get_dst()
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 69ce6487dcd364245a3d26322fc8f4ffd1e8d947 upstream.
+
+While cooking the sctp np->opt rcu fixes, I forgot to move
+one rcu_read_unlock() after the added rcu_dereference() in
+sctp_v6_get_dst()
+
+This gave lockdep warnings reported by Dave Jones.
+
+Fixes: c836a8ba9386 ("ipv6: sctp: add rcu protection around np->opt")
+Reported-by: Dave Jones <davej@codemonkey.org.uk>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/sctp/ipv6.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -323,14 +323,13 @@ static void sctp_v6_get_dst(struct sctp_
+                       }
+               }
+       }
+-      rcu_read_unlock();
+-
+       if (baddr) {
+               fl6->saddr = baddr->v6.sin6_addr;
+               fl6->fl6_sport = baddr->v6.sin6_port;
+               final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
+               dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+       }
++      rcu_read_unlock();
+ out:
+       if (!IS_ERR_OR_NULL(dst)) {
diff --git a/queue-3.18/net-ipv6-add-sysctl-option-accept_ra_min_hop_limit.patch b/queue-3.18/net-ipv6-add-sysctl-option-accept_ra_min_hop_limit.patch
new file mode 100644 (file)
index 0000000..b3108cf
--- /dev/null
@@ -0,0 +1,144 @@
+From 8013d1d7eafb0589ca766db6b74026f76b7f5cb4 Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <liuhangbin@gmail.com>
+Date: Thu, 30 Jul 2015 14:28:42 +0800
+Subject: net/ipv6: add sysctl option accept_ra_min_hop_limit
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+commit 8013d1d7eafb0589ca766db6b74026f76b7f5cb4 upstream.
+
+Commit 6fd99094de2b ("ipv6: Don't reduce hop limit for an interface")
+disabled accept hop limit from RA if it is smaller than the current hop
+limit for security stuff. But this behavior kind of break the RFC definition.
+
+RFC 4861, 6.3.4.  Processing Received Router Advertisements
+   A Router Advertisement field (e.g., Cur Hop Limit, Reachable Time,
+   and Retrans Timer) may contain a value denoting that it is
+   unspecified.  In such cases, the parameter should be ignored and the
+   host should continue using whatever value it is already using.
+
+   If the received Cur Hop Limit value is non-zero, the host SHOULD set
+   its CurHopLimit variable to the received value.
+
+So add sysctl option accept_ra_min_hop_limit to let user choose the minimum
+hop limit value they can accept from RA. And set default to 1 to meet RFC
+standards.
+
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Acked-by: YOSHIFUJI Hideaki <hideaki.yoshifuji@miraclelinux.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/networking/ip-sysctl.txt |    8 ++++++++
+ include/linux/ipv6.h                   |    1 +
+ include/uapi/linux/ipv6.h              |    1 +
+ net/ipv6/addrconf.c                    |   10 ++++++++++
+ net/ipv6/ndisc.c                       |   16 +++++++---------
+ 5 files changed, 27 insertions(+), 9 deletions(-)
+
+--- a/Documentation/networking/ip-sysctl.txt
++++ b/Documentation/networking/ip-sysctl.txt
+@@ -1256,6 +1256,14 @@ accept_ra_from_local - BOOLEAN
+          disabled if accept_ra_from_local is disabled
+                on a specific interface.
++accept_ra_min_hop_limit - INTEGER
++      Minimum hop limit Information in Router Advertisement.
++
++      Hop limit Information in Router Advertisement less than this
++      variable shall be ignored.
++
++      Default: 1
++
+ accept_ra_pinfo - BOOLEAN
+       Learn Prefix Information in Router Advertisement.
+--- a/include/linux/ipv6.h
++++ b/include/linux/ipv6.h
+@@ -29,6 +29,7 @@ struct ipv6_devconf {
+       __s32           max_desync_factor;
+       __s32           max_addresses;
+       __s32           accept_ra_defrtr;
++      __s32           accept_ra_min_hop_limit;
+       __s32           accept_ra_pinfo;
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+       __s32           accept_ra_rtr_pref;
+--- a/include/uapi/linux/ipv6.h
++++ b/include/uapi/linux/ipv6.h
+@@ -164,6 +164,7 @@ enum {
+       DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
+       DEVCONF_SUPPRESS_FRAG_NDISC,
+       DEVCONF_ACCEPT_RA_FROM_LOCAL,
++      DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT,
+       DEVCONF_MAX
+ };
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -188,6 +188,7 @@ static struct ipv6_devconf ipv6_devconf
+       .max_addresses          = IPV6_MAX_ADDRESSES,
+       .accept_ra_defrtr       = 1,
+       .accept_ra_from_local   = 0,
++      .accept_ra_min_hop_limit= 1,
+       .accept_ra_pinfo        = 1,
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+       .accept_ra_rtr_pref     = 1,
+@@ -225,6 +226,7 @@ static struct ipv6_devconf ipv6_devconf_
+       .max_addresses          = IPV6_MAX_ADDRESSES,
+       .accept_ra_defrtr       = 1,
+       .accept_ra_from_local   = 0,
++      .accept_ra_min_hop_limit= 1,
+       .accept_ra_pinfo        = 1,
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+       .accept_ra_rtr_pref     = 1,
+@@ -4321,6 +4323,7 @@ static inline void ipv6_store_devconf(st
+       array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
+       array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
+       array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
++      array[DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT] = cnf->accept_ra_min_hop_limit;
+       array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
+ #ifdef CONFIG_IPV6_ROUTER_PREF
+       array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
+@@ -5135,6 +5138,13 @@ static struct addrconf_sysctl_table
+                       .maxlen         = sizeof(int),
+                       .mode           = 0644,
+                       .proc_handler   = proc_dointvec,
++              },
++              {
++                      .procname       = "accept_ra_min_hop_limit",
++                      .data           = &ipv6_devconf.accept_ra_min_hop_limit,
++                      .maxlen         = sizeof(int),
++                      .mode           = 0644,
++                      .proc_handler   = proc_dointvec,
+               },
+               {
+                       .procname       = "accept_ra_pinfo",
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -1214,18 +1214,16 @@ static void ndisc_router_discovery(struc
+       if (rt)
+               rt6_set_expires(rt, jiffies + (HZ * lifetime));
+-      if (ra_msg->icmph.icmp6_hop_limit) {
+-              /* Only set hop_limit on the interface if it is higher than
+-               * the current hop_limit.
+-               */
+-              if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) {
++      if (in6_dev->cnf.accept_ra_min_hop_limit < 256 &&
++          ra_msg->icmph.icmp6_hop_limit) {
++              if (in6_dev->cnf.accept_ra_min_hop_limit <= ra_msg->icmph.icmp6_hop_limit) {
+                       in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
++                      if (rt)
++                              dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
++                                             ra_msg->icmph.icmp6_hop_limit);
+               } else {
+-                      ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n");
++                      ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than minimum\n");
+               }
+-              if (rt)
+-                      dst_metric_set(&rt->dst, RTAX_HOPLIMIT,
+-                                     ra_msg->icmph.icmp6_hop_limit);
+       }
+ skip_defrtr:
diff --git a/queue-3.18/ppp-defer-netns-reference-release-for-ppp-channel.patch b/queue-3.18/ppp-defer-netns-reference-release-for-ppp-channel.patch
new file mode 100644 (file)
index 0000000..2f503ac
--- /dev/null
@@ -0,0 +1,57 @@
+From 205e1e255c479f3fd77446415706463b282f94e4 Mon Sep 17 00:00:00 2001
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Tue, 5 Jul 2016 22:12:36 -0700
+Subject: ppp: defer netns reference release for ppp channel
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+commit 205e1e255c479f3fd77446415706463b282f94e4 upstream.
+
+Matt reported that we have a NULL pointer dereference
+in ppp_pernet() from ppp_connect_channel(),
+i.e. pch->chan_net is NULL.
+
+This is due to that a parallel ppp_unregister_channel()
+could happen while we are in ppp_connect_channel(), during
+which pch->chan_net set to NULL. Since we need a reference
+to net per channel, it makes sense to sync the refcnt
+with the life time of the channel, therefore we should
+release this reference when we destroy it.
+
+Fixes: 1f461dcdd296 ("ppp: take reference on channels netns")
+Reported-by: Matt Bennett <Matt.Bennett@alliedtelesis.co.nz>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: linux-ppp@vger.kernel.org
+Cc: Guillaume Nault <g.nault@alphalink.fr>
+Cc: Cyrill Gorcunov <gorcunov@openvz.org>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/ppp/ppp_generic.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ppp/ppp_generic.c
++++ b/drivers/net/ppp/ppp_generic.c
+@@ -2342,8 +2342,6 @@ ppp_unregister_channel(struct ppp_channe
+       spin_lock_bh(&pn->all_channels_lock);
+       list_del(&pch->list);
+       spin_unlock_bh(&pn->all_channels_lock);
+-      put_net(pch->chan_net);
+-      pch->chan_net = NULL;
+       pch->file.dead = 1;
+       wake_up_interruptible(&pch->file.rwait);
+@@ -2960,6 +2958,9 @@ ppp_disconnect_channel(struct channel *p
+  */
+ static void ppp_destroy_channel(struct channel *pch)
+ {
++      put_net(pch->chan_net);
++      pch->chan_net = NULL;
++
+       atomic_dec(&channel_count);
+       if (!pch->file.dead) {
diff --git a/queue-3.18/sched-panic-on-corrupted-stack-end.patch b/queue-3.18/sched-panic-on-corrupted-stack-end.patch
new file mode 100644 (file)
index 0000000..b522f04
--- /dev/null
@@ -0,0 +1,38 @@
+From 29d6455178a09e1dc340380c582b13356227e8df Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Wed, 1 Jun 2016 11:55:07 +0200
+Subject: sched: panic on corrupted stack end
+
+From: Jann Horn <jannh@google.com>
+
+commit 29d6455178a09e1dc340380c582b13356227e8df upstream.
+
+Until now, hitting this BUG_ON caused a recursive oops (because oops
+handling involves do_exit(), which calls into the scheduler, which in
+turn raises an oops), which caused stuff below the stack to be
+overwritten until a panic happened (e.g.  via an oops in interrupt
+context, caused by the overwritten CPU index in the thread_info).
+
+Just panic directly.
+
+Signed-off-by: Jann Horn <jannh@google.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+[AmitP: Minor refactoring of upstream changes for linux-3.18.y]
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/core.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -2709,7 +2709,8 @@ static noinline void __schedule_bug(stru
+ static inline void schedule_debug(struct task_struct *prev)
+ {
+ #ifdef CONFIG_SCHED_STACK_END_CHECK
+-      BUG_ON(unlikely(task_stack_end_corrupted(prev)));
++      if (task_stack_end_corrupted(prev))
++              panic("corrupted stack end detected inside scheduler\n");
+ #endif
+       /*
+        * Test if we are atomic. Since do_exit() needs to call into
index 399b28357b7d1cb1ef0e41a9791f5e615469f337..1092049fbbd352793a6931778fe9407ecf31a17c 100644 (file)
@@ -34,3 +34,17 @@ perf-fix-race-in-swevent-hash.patch
 asn.1-fix-non-match-detection-failure-on-data-overrun.patch
 keys-fix-asn.1-indefinite-length-object-parsing.patch
 ext4-fix-potential-use-after-free-in-__ext4_journal_stop.patch
+sg-fix-double-free-when-drives-detach-during-sg_io.patch
+net-ipv6-add-sysctl-option-accept_ra_min_hop_limit.patch
+ipv6-sctp-add-rcu-protection-around-np-opt.patch
+ipv6-sctp-fix-lockdep-splat-in-sctp_v6_get_dst.patch
+af_unix-guard-against-other-sk-in-unix_dgram_sendmsg.patch
+ppp-defer-netns-reference-release-for-ppp-channel.patch
+hid-core-prevent-out-of-bound-readings.patch
+cdc_ncm-do-not-call-usbnet_link_change-from-cdc_ncm_bind.patch
+sched-panic-on-corrupted-stack-end.patch
+alsa-seq-fix-race-at-timer-setup-and-close.patch
+alsa-timer-fix-race-among-timer-ioctls.patch
+alsa-timer-fix-leak-in-sndrv_timer_ioctl_params.patch
+alsa-timer-fix-leak-in-events-via-snd_timer_user_ccallback.patch
+alsa-timer-fix-leak-in-events-via-snd_timer_user_tinterrupt.patch
diff --git a/queue-3.18/sg-fix-double-free-when-drives-detach-during-sg_io.patch b/queue-3.18/sg-fix-double-free-when-drives-detach-during-sg_io.patch
new file mode 100644 (file)
index 0000000..499ece8
--- /dev/null
@@ -0,0 +1,72 @@
+From f3951a3709ff50990bf3e188c27d346792103432 Mon Sep 17 00:00:00 2001
+From: Calvin Owens <calvinowens@fb.com>
+Date: Fri, 30 Oct 2015 16:57:00 -0700
+Subject: sg: Fix double-free when drives detach during SG_IO
+
+From: Calvin Owens <calvinowens@fb.com>
+
+commit f3951a3709ff50990bf3e188c27d346792103432 upstream.
+
+In sg_common_write(), we free the block request and return -ENODEV if
+the device is detached in the middle of the SG_IO ioctl().
+
+Unfortunately, sg_finish_rem_req() also tries to free srp->rq, so we
+end up freeing rq->cmd in the already free rq object, and then free
+the object itself out from under the current user.
+
+This ends up corrupting random memory via the list_head on the rq
+object. The most common crash trace I saw is this:
+
+  ------------[ cut here ]------------
+  kernel BUG at block/blk-core.c:1420!
+  Call Trace:
+  [<ffffffff81281eab>] blk_put_request+0x5b/0x80
+  [<ffffffffa0069e5b>] sg_finish_rem_req+0x6b/0x120 [sg]
+  [<ffffffffa006bcb9>] sg_common_write.isra.14+0x459/0x5a0 [sg]
+  [<ffffffff8125b328>] ? selinux_file_alloc_security+0x48/0x70
+  [<ffffffffa006bf95>] sg_new_write.isra.17+0x195/0x2d0 [sg]
+  [<ffffffffa006cef4>] sg_ioctl+0x644/0xdb0 [sg]
+  [<ffffffff81170f80>] do_vfs_ioctl+0x90/0x520
+  [<ffffffff81258967>] ? file_has_perm+0x97/0xb0
+  [<ffffffff811714a1>] SyS_ioctl+0x91/0xb0
+  [<ffffffff81602afb>] tracesys+0xdd/0xe2
+    RIP [<ffffffff81281e04>] __blk_put_request+0x154/0x1a0
+
+The solution is straightforward: just set srp->rq to NULL in the
+failure branch so that sg_finish_rem_req() doesn't attempt to re-free
+it.
+
+Additionally, since sg_rq_end_io() will never be called on the object
+when this happens, we need to free memory backing ->cmd if it isn't
+embedded in the object itself.
+
+KASAN was extremely helpful in finding the root cause of this bug.
+
+Signed-off-by: Calvin Owens <calvinowens@fb.com>
+Acked-by: Douglas Gilbert <dgilbert@interlog.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/scsi/sg.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -791,8 +791,14 @@ sg_common_write(Sg_fd * sfp, Sg_request
+               return k;       /* probably out of space --> ENOMEM */
+       }
+       if (atomic_read(&sdp->detaching)) {
+-              if (srp->bio)
++              if (srp->bio) {
++                      if (srp->rq->cmd != srp->rq->__cmd)
++                              kfree(srp->rq->cmd);
++
+                       blk_end_request_all(srp->rq, -EIO);
++                      srp->rq = NULL;
++              }
++
+               sg_finish_rem_req(srp);
+               return -ENODEV;
+       }