]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Jan 2017 13:12:50 +0000 (14:12 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Jan 2017 13:12:50 +0000 (14:12 +0100)
added patches:
asoc-hdmi-codec-use-unsigned-type-to-structure-members-with-bit-field.patch
btrfs-fix-crash-when-tracepoint-arguments-are-freed-by-wq-callbacks.patch
drivers-char-mem-fix-thinkos-in-kmem-address-checks.patch
fix-a-fencepost-error-in-pipe_advance.patch
i2c-fix-kernel-memory-disclosure-in-dev-interface.patch
i2c-print-correct-device-invalid-address.patch
input-elants_i2c-avoid-divide-by-0-errors-on-bad-touchscreen-data.patch
mnt-protect-the-mountpoint-hashtable-with-mount_lock.patch
pid-fix-lockdep-deadlock-warning-due-to-ucount_lock.patch
revert-tty-serial-8250-add-con_consdev-to-flags.patch
vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch
xhci-fix-deadlock-at-host-remove-by-running-watchdog-correctly.patch

13 files changed:
queue-4.9/asoc-hdmi-codec-use-unsigned-type-to-structure-members-with-bit-field.patch [new file with mode: 0644]
queue-4.9/btrfs-fix-crash-when-tracepoint-arguments-are-freed-by-wq-callbacks.patch [new file with mode: 0644]
queue-4.9/drivers-char-mem-fix-thinkos-in-kmem-address-checks.patch [new file with mode: 0644]
queue-4.9/fix-a-fencepost-error-in-pipe_advance.patch [new file with mode: 0644]
queue-4.9/i2c-fix-kernel-memory-disclosure-in-dev-interface.patch [new file with mode: 0644]
queue-4.9/i2c-print-correct-device-invalid-address.patch [new file with mode: 0644]
queue-4.9/input-elants_i2c-avoid-divide-by-0-errors-on-bad-touchscreen-data.patch [new file with mode: 0644]
queue-4.9/mnt-protect-the-mountpoint-hashtable-with-mount_lock.patch [new file with mode: 0644]
queue-4.9/pid-fix-lockdep-deadlock-warning-due-to-ucount_lock.patch [new file with mode: 0644]
queue-4.9/revert-tty-serial-8250-add-con_consdev-to-flags.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch [new file with mode: 0644]
queue-4.9/xhci-fix-deadlock-at-host-remove-by-running-watchdog-correctly.patch [new file with mode: 0644]

diff --git a/queue-4.9/asoc-hdmi-codec-use-unsigned-type-to-structure-members-with-bit-field.patch b/queue-4.9/asoc-hdmi-codec-use-unsigned-type-to-structure-members-with-bit-field.patch
new file mode 100644 (file)
index 0000000..01852f2
--- /dev/null
@@ -0,0 +1,72 @@
+From 9e4d59ada4d602e78eee9fb5f898ce61fdddb446 Mon Sep 17 00:00:00 2001
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Date: Fri, 16 Dec 2016 18:26:54 +0900
+Subject: ASoC: hdmi-codec: use unsigned type to structure members with bit-field
+
+From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+
+commit 9e4d59ada4d602e78eee9fb5f898ce61fdddb446 upstream.
+
+This is a fix for Linux 4.10-rc1.
+
+In C language specification, a bit-field is interpreted as a signed or
+unsigned integer type consisting of the specified number of bits.
+
+In GCC manual, the range of a signed bit field of N bits is from
+-(2^N) / 2 to ((2^N) / 2) - 1
+https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Bit-Fields
+
+Therefore, when defined as 1 bit-field with signed type, variables can
+represents -1 and 0.
+
+The snd-soc-hdmi-codec module includes a structure which has signed type
+members with bit-fields. Codes of this module assign 0 and 1 to the
+members. This seems to result in implementation-dependent behaviours.
+
+As of v4.10-rc1 merge window, outside of sound subsystem, this structure
+is referred by below GPU modules.
+ - tda998x
+ - sti-drm
+ - mediatek-drm-hdmi
+ - msm
+
+As long as I review their codes relevant to the structure, the structure
+members are used just for condition statements and printk formats.
+My proposal of change is a bit intrusive to the printk formats but this
+may be acceptable.
+
+Totally, it's reasonable to use unsigned type for the structure members.
+This bug is detected by Sparse, static code analyzer with below warnings.
+
+./include/sound/hdmi-codec.h:39:26: error: dubious one-bit signed bitfield
+./include/sound/hdmi-codec.h:40:28: error: dubious one-bit signed bitfield
+./include/sound/hdmi-codec.h:41:29: error: dubious one-bit signed bitfield
+./include/sound/hdmi-codec.h:42:31: error: dubious one-bit signed bitfield
+
+Fixes: 09184118a8ab ("ASoC: hdmi-codec: Add hdmi-codec for external HDMI-encoders")
+Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
+Acked-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/sound/hdmi-codec.h |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/include/sound/hdmi-codec.h
++++ b/include/sound/hdmi-codec.h
+@@ -36,10 +36,10 @@ struct hdmi_codec_daifmt {
+               HDMI_AC97,
+               HDMI_SPDIF,
+       } fmt;
+-      int bit_clk_inv:1;
+-      int frame_clk_inv:1;
+-      int bit_clk_master:1;
+-      int frame_clk_master:1;
++      unsigned int bit_clk_inv:1;
++      unsigned int frame_clk_inv:1;
++      unsigned int bit_clk_master:1;
++      unsigned int frame_clk_master:1;
+ };
+ /*
diff --git a/queue-4.9/btrfs-fix-crash-when-tracepoint-arguments-are-freed-by-wq-callbacks.patch b/queue-4.9/btrfs-fix-crash-when-tracepoint-arguments-are-freed-by-wq-callbacks.patch
new file mode 100644 (file)
index 0000000..b4fe217
--- /dev/null
@@ -0,0 +1,130 @@
+From ac0c7cf8be00f269f82964cf7b144ca3edc5dbc4 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Fri, 6 Jan 2017 14:12:51 +0100
+Subject: btrfs: fix crash when tracepoint arguments are freed by wq callbacks
+
+From: David Sterba <dsterba@suse.com>
+
+commit ac0c7cf8be00f269f82964cf7b144ca3edc5dbc4 upstream.
+
+Enabling btrfs tracepoints leads to instant crash, as reported. The wq
+callbacks could free the memory and the tracepoints started to
+dereference the members to get to fs_info.
+
+The proposed fix https://marc.info/?l=linux-btrfs&m=148172436722606&w=2
+removed the tracepoints but we could preserve them by passing only the
+required data in a safe way.
+
+Fixes: bc074524e123 ("btrfs: prefix fsid to all trace events")
+Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/async-thread.c      |   15 +++++++++++----
+ include/trace/events/btrfs.h |   22 +++++++++++++---------
+ 2 files changed, 24 insertions(+), 13 deletions(-)
+
+--- a/fs/btrfs/async-thread.c
++++ b/fs/btrfs/async-thread.c
+@@ -273,6 +273,8 @@ static void run_ordered_work(struct __bt
+       unsigned long flags;
+       while (1) {
++              void *wtag;
++
+               spin_lock_irqsave(lock, flags);
+               if (list_empty(list))
+                       break;
+@@ -299,11 +301,13 @@ static void run_ordered_work(struct __bt
+               spin_unlock_irqrestore(lock, flags);
+               /*
+-               * we don't want to call the ordered free functions
+-               * with the lock held though
++               * We don't want to call the ordered free functions with the
++               * lock held though. Save the work as tag for the trace event,
++               * because the callback could free the structure.
+                */
++              wtag = work;
+               work->ordered_free(work);
+-              trace_btrfs_all_work_done(work);
++              trace_btrfs_all_work_done(wq->fs_info, wtag);
+       }
+       spin_unlock_irqrestore(lock, flags);
+ }
+@@ -311,6 +315,7 @@ static void run_ordered_work(struct __bt
+ static void normal_work_helper(struct btrfs_work *work)
+ {
+       struct __btrfs_workqueue *wq;
++      void *wtag;
+       int need_order = 0;
+       /*
+@@ -324,6 +329,8 @@ static void normal_work_helper(struct bt
+       if (work->ordered_func)
+               need_order = 1;
+       wq = work->wq;
++      /* Safe for tracepoints in case work gets freed by the callback */
++      wtag = work;
+       trace_btrfs_work_sched(work);
+       thresh_exec_hook(wq);
+@@ -333,7 +340,7 @@ static void normal_work_helper(struct bt
+               run_ordered_work(wq);
+       }
+       if (!need_order)
+-              trace_btrfs_all_work_done(work);
++              trace_btrfs_all_work_done(wq->fs_info, wtag);
+ }
+ void btrfs_init_work(struct btrfs_work *work, btrfs_work_func_t uniq_func,
+--- a/include/trace/events/btrfs.h
++++ b/include/trace/events/btrfs.h
+@@ -1162,22 +1162,26 @@ DECLARE_EVENT_CLASS(btrfs__work,
+                  __entry->func, __entry->ordered_func, __entry->ordered_free)
+ );
+-/* For situiations that the work is freed */
++/*
++ * For situiations when the work is freed, we pass fs_info and a tag that that
++ * matches address of the work structure so it can be paired with the
++ * scheduling event.
++ */
+ DECLARE_EVENT_CLASS(btrfs__work__done,
+-      TP_PROTO(struct btrfs_work *work),
++      TP_PROTO(struct btrfs_fs_info *fs_info, void *wtag),
+-      TP_ARGS(work),
++      TP_ARGS(fs_info, wtag),
+       TP_STRUCT__entry_btrfs(
+-              __field(        void *, work                    )
++              __field(        void *, wtag                    )
+       ),
+-      TP_fast_assign_btrfs(btrfs_work_owner(work),
+-              __entry->work           = work;
++      TP_fast_assign_btrfs(fs_info,
++              __entry->wtag           = wtag;
+       ),
+-      TP_printk_btrfs("work->%p", __entry->work)
++      TP_printk_btrfs("work->%p", __entry->wtag)
+ );
+ DEFINE_EVENT(btrfs__work, btrfs_work_queued,
+@@ -1196,9 +1200,9 @@ DEFINE_EVENT(btrfs__work, btrfs_work_sch
+ DEFINE_EVENT(btrfs__work__done, btrfs_all_work_done,
+-      TP_PROTO(struct btrfs_work *work),
++      TP_PROTO(struct btrfs_fs_info *fs_info, void *wtag),
+-      TP_ARGS(work)
++      TP_ARGS(fs_info, wtag)
+ );
+ DEFINE_EVENT(btrfs__work, btrfs_ordered_sched,
diff --git a/queue-4.9/drivers-char-mem-fix-thinkos-in-kmem-address-checks.patch b/queue-4.9/drivers-char-mem-fix-thinkos-in-kmem-address-checks.patch
new file mode 100644 (file)
index 0000000..d402a22
--- /dev/null
@@ -0,0 +1,70 @@
+From 488debb9971bc7d0edd6d8080ba78ca02a04f6c4 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Thu, 5 Jan 2017 17:15:01 +0000
+Subject: drivers: char: mem: Fix thinkos in kmem address checks
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+commit 488debb9971bc7d0edd6d8080ba78ca02a04f6c4 upstream.
+
+When borrowing the pfn_valid() check from mmap_kmem(), somebody managed
+to get physical and virtual addresses spectacularly muddled up, such
+that we've ended up with checks for one being the other. Whilst this
+does indeed prevent out-of-bounds accesses crashing, on most systems
+it also prevents the more desirable use-case of working at all ever.
+
+Check the *virtual* offset correctly for what it is. Furthermore, do
+so in the right place - a read or write may span multiple pages, so a
+single up-front check is insufficient. High memory accesses already
+have a similar validity check just before the copy_to_user() call, so
+just make the low memory path fully consistent with that.
+
+Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Fixes: 148a1bc84398 ("drivers: char: mem: Check {read,write}_kmem() addresses")
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/mem.c |   10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+--- a/drivers/char/mem.c
++++ b/drivers/char/mem.c
+@@ -381,9 +381,6 @@ static ssize_t read_kmem(struct file *fi
+       char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
+       int err = 0;
+-      if (!pfn_valid(PFN_DOWN(p)))
+-              return -EIO;
+-
+       read = 0;
+       if (p < (unsigned long) high_memory) {
+               low_count = count;
+@@ -412,6 +409,8 @@ static ssize_t read_kmem(struct file *fi
+                        * by the kernel or data corruption may occur
+                        */
+                       kbuf = xlate_dev_kmem_ptr((void *)p);
++                      if (!virt_addr_valid(kbuf))
++                              return -ENXIO;
+                       if (copy_to_user(buf, kbuf, sz))
+                               return -EFAULT;
+@@ -482,6 +481,8 @@ static ssize_t do_write_kmem(unsigned lo
+                * corruption may occur.
+                */
+               ptr = xlate_dev_kmem_ptr((void *)p);
++              if (!virt_addr_valid(ptr))
++                      return -ENXIO;
+               copied = copy_from_user(ptr, buf, sz);
+               if (copied) {
+@@ -512,9 +513,6 @@ static ssize_t write_kmem(struct file *f
+       char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
+       int err = 0;
+-      if (!pfn_valid(PFN_DOWN(p)))
+-              return -EIO;
+-
+       if (p < (unsigned long) high_memory) {
+               unsigned long to_write = min_t(unsigned long, count,
+                                              (unsigned long)high_memory - p);
diff --git a/queue-4.9/fix-a-fencepost-error-in-pipe_advance.patch b/queue-4.9/fix-a-fencepost-error-in-pipe_advance.patch
new file mode 100644 (file)
index 0000000..3c36154
--- /dev/null
@@ -0,0 +1,108 @@
+From b9dc6f65bc5e232d1c05fe34b5daadc7e8bbf1fb Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sat, 14 Jan 2017 19:33:08 -0500
+Subject: fix a fencepost error in pipe_advance()
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit b9dc6f65bc5e232d1c05fe34b5daadc7e8bbf1fb upstream.
+
+The logics in pipe_advance() used to release all buffers past the new
+position failed in cases when the number of buffers to release was equal
+to pipe->buffers.  If that happened, none of them had been released,
+leaving pipe full.  Worse, it was trivial to trigger and we end up with
+pipe full of uninitialized pages.  IOW, it's an infoleak.
+
+Reported-by: "Alan J. Wylie" <alan@wylie.me.uk>
+Tested-by: "Alan J. Wylie" <alan@wylie.me.uk>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ lib/iov_iter.c |   54 +++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 31 insertions(+), 23 deletions(-)
+
+--- a/lib/iov_iter.c
++++ b/lib/iov_iter.c
+@@ -678,43 +678,50 @@ size_t iov_iter_copy_from_user_atomic(st
+ }
+ EXPORT_SYMBOL(iov_iter_copy_from_user_atomic);
++static inline void pipe_truncate(struct iov_iter *i)
++{
++      struct pipe_inode_info *pipe = i->pipe;
++      if (pipe->nrbufs) {
++              size_t off = i->iov_offset;
++              int idx = i->idx;
++              int nrbufs = (idx - pipe->curbuf) & (pipe->buffers - 1);
++              if (off) {
++                      pipe->bufs[idx].len = off - pipe->bufs[idx].offset;
++                      idx = next_idx(idx, pipe);
++                      nrbufs++;
++              }
++              while (pipe->nrbufs > nrbufs) {
++                      pipe_buf_release(pipe, &pipe->bufs[idx]);
++                      idx = next_idx(idx, pipe);
++                      pipe->nrbufs--;
++              }
++      }
++}
++
+ static void pipe_advance(struct iov_iter *i, size_t size)
+ {
+       struct pipe_inode_info *pipe = i->pipe;
+-      struct pipe_buffer *buf;
+-      int idx = i->idx;
+-      size_t off = i->iov_offset, orig_sz;
+-      
+       if (unlikely(i->count < size))
+               size = i->count;
+-      orig_sz = size;
+-
+       if (size) {
++              struct pipe_buffer *buf;
++              size_t off = i->iov_offset, left = size;
++              int idx = i->idx;
+               if (off) /* make it relative to the beginning of buffer */
+-                      size += off - pipe->bufs[idx].offset;
++                      left += off - pipe->bufs[idx].offset;
+               while (1) {
+                       buf = &pipe->bufs[idx];
+-                      if (size <= buf->len)
++                      if (left <= buf->len)
+                               break;
+-                      size -= buf->len;
++                      left -= buf->len;
+                       idx = next_idx(idx, pipe);
+               }
+-              buf->len = size;
+               i->idx = idx;
+-              off = i->iov_offset = buf->offset + size;
+-      }
+-      if (off)
+-              idx = next_idx(idx, pipe);
+-      if (pipe->nrbufs) {
+-              int unused = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
+-              /* [curbuf,unused) is in use.  Free [idx,unused) */
+-              while (idx != unused) {
+-                      pipe_buf_release(pipe, &pipe->bufs[idx]);
+-                      idx = next_idx(idx, pipe);
+-                      pipe->nrbufs--;
+-              }
++              i->iov_offset = buf->offset + left;
+       }
+-      i->count -= orig_sz;
++      i->count -= size;
++      /* ... and discard everything past that point */
++      pipe_truncate(i);
+ }
+ void iov_iter_advance(struct iov_iter *i, size_t size)
+@@ -774,6 +781,7 @@ void iov_iter_pipe(struct iov_iter *i, i
+                       size_t count)
+ {
+       BUG_ON(direction != ITER_PIPE);
++      WARN_ON(pipe->nrbufs == pipe->buffers);
+       i->type = direction;
+       i->pipe = pipe;
+       i->idx = (pipe->curbuf + pipe->nrbufs) & (pipe->buffers - 1);
diff --git a/queue-4.9/i2c-fix-kernel-memory-disclosure-in-dev-interface.patch b/queue-4.9/i2c-fix-kernel-memory-disclosure-in-dev-interface.patch
new file mode 100644 (file)
index 0000000..e6379a2
--- /dev/null
@@ -0,0 +1,32 @@
+From 30f939feaeee23e21391cfc7b484f012eb189c3c Mon Sep 17 00:00:00 2001
+From: Vlad Tsyrklevich <vlad@tsyrklevich.net>
+Date: Mon, 9 Jan 2017 22:53:36 +0700
+Subject: i2c: fix kernel memory disclosure in dev interface
+
+From: Vlad Tsyrklevich <vlad@tsyrklevich.net>
+
+commit 30f939feaeee23e21391cfc7b484f012eb189c3c upstream.
+
+i2c_smbus_xfer() does not always fill an entire block, allowing
+kernel stack memory disclosure through the temp variable. Clear
+it before it's read to.
+
+Signed-off-by: Vlad Tsyrklevich <vlad@tsyrklevich.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/i2c-dev.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -331,7 +331,7 @@ static noinline int i2cdev_ioctl_smbus(s
+               unsigned long arg)
+ {
+       struct i2c_smbus_ioctl_data data_arg;
+-      union i2c_smbus_data temp;
++      union i2c_smbus_data temp = {};
+       int datasize, res;
+       if (copy_from_user(&data_arg,
diff --git a/queue-4.9/i2c-print-correct-device-invalid-address.patch b/queue-4.9/i2c-print-correct-device-invalid-address.patch
new file mode 100644 (file)
index 0000000..403cf90
--- /dev/null
@@ -0,0 +1,36 @@
+From 6f724fb3039522486fce2e32e4c0fbe238a6ab02 Mon Sep 17 00:00:00 2001
+From: John Garry <john.garry@huawei.com>
+Date: Fri, 6 Jan 2017 19:02:57 +0800
+Subject: i2c: print correct device invalid address
+
+From: John Garry <john.garry@huawei.com>
+
+commit 6f724fb3039522486fce2e32e4c0fbe238a6ab02 upstream.
+
+In of_i2c_register_device(), when the check for
+device address validity fails we print the info.addr,
+which has not been assigned properly.
+
+Fix this by printing the actual invalid address.
+
+Signed-off-by: John Garry <john.garry@huawei.com>
+Reviewed-by: Vladimir Zapolskiy <vz@mleia.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Fixes: b4e2f6ac1281 ("i2c: apply DT flags when probing")
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/i2c-core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/i2c/i2c-core.c
++++ b/drivers/i2c/i2c-core.c
+@@ -1657,7 +1657,7 @@ static struct i2c_client *of_i2c_registe
+       if (i2c_check_addr_validity(addr, info.flags)) {
+               dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
+-                      info.addr, node->full_name);
++                      addr, node->full_name);
+               return ERR_PTR(-EINVAL);
+       }
diff --git a/queue-4.9/input-elants_i2c-avoid-divide-by-0-errors-on-bad-touchscreen-data.patch b/queue-4.9/input-elants_i2c-avoid-divide-by-0-errors-on-bad-touchscreen-data.patch
new file mode 100644 (file)
index 0000000..a7a0a6a
--- /dev/null
@@ -0,0 +1,91 @@
+From 1c3415a06b1016a596bfe59e0cfee56c773aa958 Mon Sep 17 00:00:00 2001
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Thu, 5 Jan 2017 14:14:54 -0800
+Subject: Input: elants_i2c - avoid divide by 0 errors on bad touchscreen data
+
+From: Guenter Roeck <linux@roeck-us.net>
+
+commit 1c3415a06b1016a596bfe59e0cfee56c773aa958 upstream.
+
+The following crash may be seen if bad data is received from the
+touchscreen.
+
+[ 2189.425150] elants_i2c i2c-ELAN0001:00: unknown packet ff ff ff ff
+[ 2189.430738] divide error: 0000 [#1] PREEMPT SMP
+[ 2189.434679] gsmi: Log Shutdown Reason 0x03
+[ 2189.434689] Modules linked in: ip6t_REJECT nf_reject_ipv6 rfcomm evdi
+uinput uvcvideo cmac videobuf2_vmalloc videobuf2_memops snd_hda_codec_hdmi
+i2c_dev videobuf2_core snd_soc_sst_cht_bsw_rt5645 snd_hda_intel
+snd_intel_sst_acpi btusb btrtl btbcm btintel bluetooth snd_soc_sst_acpi
+snd_hda_codec snd_intel_sst_core snd_hwdep snd_soc_sst_mfld_platform
+snd_hda_core snd_soc_rt5645 memconsole_x86_legacy memconsole zram snd_soc_rl6231
+fuse ip6table_filter iwlmvm iwlwifi iwl7000_mac80211 cfg80211 iio_trig_sysfs
+joydev cros_ec_sensors cros_ec_sensors_core industrialio_triggered_buffer
+kfifo_buf industrialio snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq
+snd_seq_device ppp_async ppp_generic slhc tun
+[ 2189.434866] CPU: 0 PID: 106 Comm: irq/184-ELAN000 Tainted: G        W
+3.18.0-13101-g57e8190 #1
+[ 2189.434883] Hardware name: GOOGLE Ultima, BIOS Google_Ultima.7287.131.43 07/20/2016
+[ 2189.434898] task: ffff88017a0b6d80 ti: ffff88017a2bc000 task.ti: ffff88017a2bc000
+[ 2189.434913] RIP: 0010:[<ffffffffbecc48d5>]  [<ffffffffbecc48d5>] elants_i2c_irq+0x190/0x200
+[ 2189.434937] RSP: 0018:ffff88017a2bfd98  EFLAGS: 00010293
+[ 2189.434948] RAX: 0000000000000000 RBX: ffff88017a967828 RCX: ffff88017a9678e8
+[ 2189.434962] RDX: 0000000000000000 RSI: 0000000000000246 RDI: 0000000000000000
+[ 2189.434975] RBP: ffff88017a2bfdd8 R08: 00000000000003e8 R09: 0000000000000000
+[ 2189.434989] R10: 0000000000000000 R11: 000000000044a2bd R12: ffff88017a991800
+[ 2189.435001] R13: ffffffffbe8a2a53 R14: ffff88017a0b6d80 R15: ffff88017a0b6d80
+[ 2189.435011] FS:  0000000000000000(0000) GS:ffff88017fc00000(0000) knlGS:0000000000000000
+[ 2189.435022] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+[ 2189.435030] CR2: 00007f678d94b000 CR3: 000000003f41a000 CR4: 00000000001007f0
+[ 2189.435039] Stack:
+[ 2189.435044]  ffff88017a2bfda8 ffff88017a9678e8 646464647a2bfdd8 0000000006e09574
+[ 2189.435060]  0000000000000000 ffff88017a088b80 ffff88017a921000 ffffffffbe8a2a53
+[ 2189.435074]  ffff88017a2bfe08 ffffffffbe8a2a73 ffff88017a0b6d80 0000000006e09574
+[ 2189.435089] Call Trace:
+[ 2189.435101]  [<ffffffffbe8a2a53>] ? irq_thread_dtor+0xa9/0xa9
+[ 2189.435112]  [<ffffffffbe8a2a73>] irq_thread_fn+0x20/0x40
+[ 2189.435123]  [<ffffffffbe8a2be1>] irq_thread+0x14e/0x222
+[ 2189.435135]  [<ffffffffbee8cbeb>] ? __schedule+0x3b3/0x57a
+[ 2189.435145]  [<ffffffffbe8a29aa>] ? wake_threads_waitq+0x2d/0x2d
+[ 2189.435156]  [<ffffffffbe8a2a93>] ? irq_thread_fn+0x40/0x40
+[ 2189.435168]  [<ffffffffbe87c385>] kthread+0x10e/0x116
+[ 2189.435178]  [<ffffffffbe87c277>] ? __kthread_parkme+0x67/0x67
+[ 2189.435189]  [<ffffffffbee900ac>] ret_from_fork+0x7c/0xb0
+[ 2189.435199]  [<ffffffffbe87c277>] ? __kthread_parkme+0x67/0x67
+[ 2189.435208] Code: ff ff eb 73 0f b6 bb c1 00 00 00 83 ff 03 7e 13 49 8d 7c
+24 20 ba 04 00 00 00 48 c7 c6 8a cd 21 bf eb 4d 0f b6 83 c2 00 00 00 99 <f7> ff
+83 f8 37 75 15 48 6b f7 37 4c 8d a3 c4 00 00 00 4c 8d ac
+[ 2189.435312] RIP  [<ffffffffbecc48d5>] elants_i2c_irq+0x190/0x200
+[ 2189.435323]  RSP <ffff88017a2bfd98>
+[ 2189.435350] ---[ end trace f4945345a75d96dd ]---
+[ 2189.443841] Kernel panic - not syncing: Fatal exception
+[ 2189.444307] Kernel Offset: 0x3d800000 from 0xffffffff81000000
+       (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
+[ 2189.444519] gsmi: Log Shutdown Reason 0x02
+
+The problem was seen with a 3.18 based kernel, but there is no reason
+to believe that the upstream code is safe.
+
+Fixes: 66aee90088da2 ("Input: add support for Elan eKTH I2C touchscreens")
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/input/touchscreen/elants_i2c.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/input/touchscreen/elants_i2c.c
++++ b/drivers/input/touchscreen/elants_i2c.c
+@@ -914,9 +914,9 @@ static irqreturn_t elants_i2c_irq(int ir
+               case QUEUE_HEADER_NORMAL:
+                       report_count = ts->buf[FW_HDR_COUNT];
+-                      if (report_count > 3) {
++                      if (report_count == 0 || report_count > 3) {
+                               dev_err(&client->dev,
+-                                      "too large report count: %*ph\n",
++                                      "bad report count: %*ph\n",
+                                       HEADER_SIZE, ts->buf);
+                               break;
+                       }
diff --git a/queue-4.9/mnt-protect-the-mountpoint-hashtable-with-mount_lock.patch b/queue-4.9/mnt-protect-the-mountpoint-hashtable-with-mount_lock.patch
new file mode 100644 (file)
index 0000000..87fbec3
--- /dev/null
@@ -0,0 +1,191 @@
+From 3895dbf8985f656675b5bde610723a29cbce3fa7 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 3 Jan 2017 14:18:43 +1300
+Subject: mnt: Protect the mountpoint hashtable with mount_lock
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 3895dbf8985f656675b5bde610723a29cbce3fa7 upstream.
+
+Protecting the mountpoint hashtable with namespace_sem was sufficient
+until a call to umount_mnt was added to mntput_no_expire.  At which
+point it became possible for multiple calls of put_mountpoint on
+the same hash chain to happen on the same time.
+
+Kristen Johansen <kjlx@templeofstupid.com> reported:
+> This can cause a panic when simultaneous callers of put_mountpoint
+> attempt to free the same mountpoint.  This occurs because some callers
+> hold the mount_hash_lock, while others hold the namespace lock.  Some
+> even hold both.
+>
+> In this submitter's case, the panic manifested itself as a GP fault in
+> put_mountpoint() when it called hlist_del() and attempted to dereference
+> a m_hash.pprev that had been poisioned by another thread.
+
+Al Viro observed that the simple fix is to switch from using the namespace_sem
+to the mount_lock to protect the mountpoint hash table.
+
+I have taken Al's suggested patch moved put_mountpoint in pivot_root
+(instead of taking mount_lock an additional time), and have replaced
+new_mountpoint with get_mountpoint a function that does the hash table
+lookup and addition under the mount_lock.   The introduction of get_mounptoint
+ensures that only the mount_lock is needed to manipulate the mountpoint
+hashtable.
+
+d_set_mounted is modified to only set DCACHE_MOUNTED if it is not
+already set.  This allows get_mountpoint to use the setting of
+DCACHE_MOUNTED to ensure adding a struct mountpoint for a dentry
+happens exactly once.
+
+Fixes: ce07d891a089 ("mnt: Honor MNT_LOCKED when detaching mounts")
+Reported-by: Krister Johansen <kjlx@templeofstupid.com>
+Suggested-by: Al Viro <viro@ZenIV.linux.org.uk>
+Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/dcache.c    |    7 ++++--
+ fs/namespace.c |   64 ++++++++++++++++++++++++++++++++++++++++-----------------
+ 2 files changed, 50 insertions(+), 21 deletions(-)
+
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1330,8 +1330,11 @@ int d_set_mounted(struct dentry *dentry)
+       }
+       spin_lock(&dentry->d_lock);
+       if (!d_unlinked(dentry)) {
+-              dentry->d_flags |= DCACHE_MOUNTED;
+-              ret = 0;
++              ret = -EBUSY;
++              if (!d_mountpoint(dentry)) {
++                      dentry->d_flags |= DCACHE_MOUNTED;
++                      ret = 0;
++              }
+       }
+       spin_unlock(&dentry->d_lock);
+ out:
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -746,26 +746,50 @@ static struct mountpoint *lookup_mountpo
+       return NULL;
+ }
+-static struct mountpoint *new_mountpoint(struct dentry *dentry)
++static struct mountpoint *get_mountpoint(struct dentry *dentry)
+ {
+-      struct hlist_head *chain = mp_hash(dentry);
+-      struct mountpoint *mp;
++      struct mountpoint *mp, *new = NULL;
+       int ret;
+-      mp = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
+-      if (!mp)
++      if (d_mountpoint(dentry)) {
++mountpoint:
++              read_seqlock_excl(&mount_lock);
++              mp = lookup_mountpoint(dentry);
++              read_sequnlock_excl(&mount_lock);
++              if (mp)
++                      goto done;
++      }
++
++      if (!new)
++              new = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
++      if (!new)
+               return ERR_PTR(-ENOMEM);
++
++      /* Exactly one processes may set d_mounted */
+       ret = d_set_mounted(dentry);
+-      if (ret) {
+-              kfree(mp);
+-              return ERR_PTR(ret);
+-      }
+-      mp->m_dentry = dentry;
+-      mp->m_count = 1;
+-      hlist_add_head(&mp->m_hash, chain);
+-      INIT_HLIST_HEAD(&mp->m_list);
++      /* Someone else set d_mounted? */
++      if (ret == -EBUSY)
++              goto mountpoint;
++
++      /* The dentry is not available as a mountpoint? */
++      mp = ERR_PTR(ret);
++      if (ret)
++              goto done;
++
++      /* Add the new mountpoint to the hash table */
++      read_seqlock_excl(&mount_lock);
++      new->m_dentry = dentry;
++      new->m_count = 1;
++      hlist_add_head(&new->m_hash, mp_hash(dentry));
++      INIT_HLIST_HEAD(&new->m_list);
++      read_sequnlock_excl(&mount_lock);
++
++      mp = new;
++      new = NULL;
++done:
++      kfree(new);
+       return mp;
+ }
+@@ -1568,11 +1592,11 @@ void __detach_mounts(struct dentry *dent
+       struct mount *mnt;
+       namespace_lock();
++      lock_mount_hash();
+       mp = lookup_mountpoint(dentry);
+       if (IS_ERR_OR_NULL(mp))
+               goto out_unlock;
+-      lock_mount_hash();
+       event++;
+       while (!hlist_empty(&mp->m_list)) {
+               mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
+@@ -1582,9 +1606,9 @@ void __detach_mounts(struct dentry *dent
+               }
+               else umount_tree(mnt, UMOUNT_CONNECTED);
+       }
+-      unlock_mount_hash();
+       put_mountpoint(mp);
+ out_unlock:
++      unlock_mount_hash();
+       namespace_unlock();
+ }
+@@ -2013,9 +2037,7 @@ retry:
+       namespace_lock();
+       mnt = lookup_mnt(path);
+       if (likely(!mnt)) {
+-              struct mountpoint *mp = lookup_mountpoint(dentry);
+-              if (!mp)
+-                      mp = new_mountpoint(dentry);
++              struct mountpoint *mp = get_mountpoint(dentry);
+               if (IS_ERR(mp)) {
+                       namespace_unlock();
+                       inode_unlock(dentry->d_inode);
+@@ -2034,7 +2056,11 @@ retry:
+ static void unlock_mount(struct mountpoint *where)
+ {
+       struct dentry *dentry = where->m_dentry;
++
++      read_seqlock_excl(&mount_lock);
+       put_mountpoint(where);
++      read_sequnlock_excl(&mount_lock);
++
+       namespace_unlock();
+       inode_unlock(dentry->d_inode);
+ }
+@@ -3110,9 +3136,9 @@ SYSCALL_DEFINE2(pivot_root, const char _
+       touch_mnt_namespace(current->nsproxy->mnt_ns);
+       /* A moved mount should not expire automatically */
+       list_del_init(&new_mnt->mnt_expire);
++      put_mountpoint(root_mp);
+       unlock_mount_hash();
+       chroot_fs_refs(&root, &new);
+-      put_mountpoint(root_mp);
+       error = 0;
+ out4:
+       unlock_mount(old_mp);
diff --git a/queue-4.9/pid-fix-lockdep-deadlock-warning-due-to-ucount_lock.patch b/queue-4.9/pid-fix-lockdep-deadlock-warning-due-to-ucount_lock.patch
new file mode 100644 (file)
index 0000000..8914703
--- /dev/null
@@ -0,0 +1,70 @@
+From add7c65ca426b7a37184dd3d2172394e23d585d6 Mon Sep 17 00:00:00 2001
+From: Andrei Vagin <avagin@openvz.org>
+Date: Wed, 4 Jan 2017 19:28:14 -0800
+Subject: pid: fix lockdep deadlock warning due to ucount_lock
+
+From: Andrei Vagin <avagin@openvz.org>
+
+commit add7c65ca426b7a37184dd3d2172394e23d585d6 upstream.
+
+=========================================================
+[ INFO: possible irq lock inversion dependency detected ]
+4.10.0-rc2-00024-g4aecec9-dirty #118 Tainted: G        W
+---------------------------------------------------------
+swapper/1/0 just changed the state of lock:
+ (&(&sighand->siglock)->rlock){-.....}, at: [<ffffffffbd0a1bc6>] __lock_task_sighand+0xb6/0x2c0
+but this lock took another, HARDIRQ-unsafe lock in the past:
+ (ucounts_lock){+.+...}
+and interrupts could create inverse lock ordering between them.
+other info that might help us debug this:
+Chain exists of:                 &(&sighand->siglock)->rlock --> &(&tty->ctrl_lock)->rlock --> ucounts_lock
+ Possible interrupt unsafe locking scenario:
+       CPU0                    CPU1
+       ----                    ----
+  lock(ucounts_lock);
+                               local_irq_disable();
+                               lock(&(&sighand->siglock)->rlock);
+                               lock(&(&tty->ctrl_lock)->rlock);
+  <Interrupt>
+    lock(&(&sighand->siglock)->rlock);
+
+ *** DEADLOCK ***
+
+This patch removes a dependency between rlock and ucount_lock.
+
+Fixes: f333c700c610 ("pidns: Add a limit on the number of pid namespaces")
+Signed-off-by: Andrei Vagin <avagin@openvz.org>
+Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/pid_namespace.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/kernel/pid_namespace.c
++++ b/kernel/pid_namespace.c
+@@ -151,8 +151,12 @@ out:
+ static void delayed_free_pidns(struct rcu_head *p)
+ {
+-      kmem_cache_free(pid_ns_cachep,
+-                      container_of(p, struct pid_namespace, rcu));
++      struct pid_namespace *ns = container_of(p, struct pid_namespace, rcu);
++
++      dec_pid_namespaces(ns->ucounts);
++      put_user_ns(ns->user_ns);
++
++      kmem_cache_free(pid_ns_cachep, ns);
+ }
+ static void destroy_pid_namespace(struct pid_namespace *ns)
+@@ -162,8 +166,6 @@ static void destroy_pid_namespace(struct
+       ns_free_inum(&ns->ns);
+       for (i = 0; i < PIDMAP_ENTRIES; i++)
+               kfree(ns->pidmap[i].page);
+-      dec_pid_namespaces(ns->ucounts);
+-      put_user_ns(ns->user_ns);
+       call_rcu(&ns->rcu, delayed_free_pidns);
+ }
diff --git a/queue-4.9/revert-tty-serial-8250-add-con_consdev-to-flags.patch b/queue-4.9/revert-tty-serial-8250-add-con_consdev-to-flags.patch
new file mode 100644 (file)
index 0000000..b5b21bf
--- /dev/null
@@ -0,0 +1,39 @@
+From 6741f551a0b26479de2532ffa43a366747e6dbf3 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Sun, 11 Dec 2016 10:05:49 +0800
+Subject: Revert "tty: serial: 8250: add CON_CONSDEV to flags"
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit 6741f551a0b26479de2532ffa43a366747e6dbf3 upstream.
+
+This commit needs to be reverted because it prevents people from
+using the serial console as a secondary console with input being
+directed to tty0.
+
+IOW, if you boot with console=ttyS0 console=tty0 then all kernels
+prior to this commit will produce output on both ttyS0 and tty0
+but input will only be taken from tty0.  With this patch the serial
+console will always be the primary console instead of tty0,
+potentially preventing people from getting into their machines in
+emergency situations.
+
+Fixes: d03516df8375 ("tty: serial: 8250: add CON_CONSDEV to flags")
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/serial/8250/8250_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/8250/8250_core.c
++++ b/drivers/tty/serial/8250/8250_core.c
+@@ -675,7 +675,7 @@ static struct console univ8250_console =
+       .device         = uart_console_device,
+       .setup          = univ8250_console_setup,
+       .match          = univ8250_console_match,
+-      .flags          = CON_PRINTBUFFER | CON_ANYTIME | CON_CONSDEV,
++      .flags          = CON_PRINTBUFFER | CON_ANYTIME,
+       .index          = -1,
+       .data           = &serial8250_reg,
+ };
index 64b1d60282f6c50b7aee6c928b5666b1c1cc8258..c548996f2d0bc43a8c19868633ab142e2ea92e8e 100644 (file)
@@ -47,3 +47,15 @@ usb-serial-ch341-fix-resume-after-reset.patch
 usb-serial-ch341-fix-open-error-handling.patch
 usb-serial-ch341-fix-control-message-error-handling.patch
 usb-serial-ch341-fix-open-and-resume-after-b0.patch
+input-elants_i2c-avoid-divide-by-0-errors-on-bad-touchscreen-data.patch
+i2c-print-correct-device-invalid-address.patch
+i2c-fix-kernel-memory-disclosure-in-dev-interface.patch
+fix-a-fencepost-error-in-pipe_advance.patch
+xhci-fix-deadlock-at-host-remove-by-running-watchdog-correctly.patch
+btrfs-fix-crash-when-tracepoint-arguments-are-freed-by-wq-callbacks.patch
+asoc-hdmi-codec-use-unsigned-type-to-structure-members-with-bit-field.patch
+revert-tty-serial-8250-add-con_consdev-to-flags.patch
+vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch
+pid-fix-lockdep-deadlock-warning-due-to-ucount_lock.patch
+mnt-protect-the-mountpoint-hashtable-with-mount_lock.patch
+drivers-char-mem-fix-thinkos-in-kmem-address-checks.patch
diff --git a/queue-4.9/vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch b/queue-4.9/vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch
new file mode 100644 (file)
index 0000000..7ee0e76
--- /dev/null
@@ -0,0 +1,46 @@
+From c8a6a09c1c617402cc9254b2bc8da359a0347d75 Mon Sep 17 00:00:00 2001
+From: Augusto Mecking Caringi <augustocaringi@gmail.com>
+Date: Tue, 10 Jan 2017 10:45:00 +0000
+Subject: vme: Fix wrong pointer utilization in ca91cx42_slave_get
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Augusto Mecking Caringi <augustocaringi@gmail.com>
+
+commit c8a6a09c1c617402cc9254b2bc8da359a0347d75 upstream.
+
+In ca91cx42_slave_get function, the value pointed by vme_base pointer is
+set through:
+
+*vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]);
+
+So it must be dereferenced to be used in calculation of pci_base:
+
+*pci_base = (dma_addr_t)*vme_base + pci_offset;
+
+This bug was caught thanks to the following gcc warning:
+
+drivers/vme/bridges/vme_ca91cx42.c: In function ‘ca91cx42_slave_get’:
+drivers/vme/bridges/vme_ca91cx42.c:467:14: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
+*pci_base = (dma_addr_t)vme_base + pci_offset;
+
+Signed-off-by: Augusto Mecking Caringi <augustocaringi@gmail.com>
+Acked-By: Martyn Welch <martyn@welchs.me.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/vme/bridges/vme_ca91cx42.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/vme/bridges/vme_ca91cx42.c
++++ b/drivers/vme/bridges/vme_ca91cx42.c
+@@ -464,7 +464,7 @@ static int ca91cx42_slave_get(struct vme
+       vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
+       pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
+-      *pci_base = (dma_addr_t)vme_base + pci_offset;
++      *pci_base = (dma_addr_t)*vme_base + pci_offset;
+       *size = (unsigned long long)((vme_bound - *vme_base) + granularity);
+       *enabled = 0;
diff --git a/queue-4.9/xhci-fix-deadlock-at-host-remove-by-running-watchdog-correctly.patch b/queue-4.9/xhci-fix-deadlock-at-host-remove-by-running-watchdog-correctly.patch
new file mode 100644 (file)
index 0000000..182efbf
--- /dev/null
@@ -0,0 +1,81 @@
+From d6169d04097fd9ddf811e63eae4e5cd71e6666e2 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Wed, 11 Jan 2017 17:10:34 +0200
+Subject: xhci: fix deadlock at host remove by running watchdog correctly
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit d6169d04097fd9ddf811e63eae4e5cd71e6666e2 upstream.
+
+If a URB is killed while the host is removed we can end up in a situation
+where the hub thread takes the roothub device lock, and waits for
+the URB to be given back by xhci-hcd, blocking the host remove code.
+
+xhci-hcd tries to stop the endpoint and give back the urb, but can't
+as the host is removed from PCI bus at the same time, preventing the normal
+way of giving back urb.
+
+Instead we need to rely on the stop command timeout function to give back
+the urb. This xhci_stop_endpoint_command_watchdog() timeout function
+used a XHCI_STATE_DYING flag to indicate if the timeout function is already
+running, but later this flag has been taking into use in other places to
+mark that xhci is dying.
+
+Remove checks for XHCI_STATE_DYING in xhci_urb_dequeue. We are still
+checking that reading from pci state does not return 0xffffffff or that
+host is not halted before trying to stop the endpoint.
+
+This whole area of stopping endpoints, giving back URBs, and the wathdog
+timeout need rework, this fix focuses on solving a specific deadlock
+issue that we can then send to stable before any major rework.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-ring.c |   11 -----------
+ drivers/usb/host/xhci.c      |   13 -------------
+ 2 files changed, 24 deletions(-)
+
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -917,17 +917,6 @@ void xhci_stop_endpoint_command_watchdog
+       spin_lock_irqsave(&xhci->lock, flags);
+       ep->stop_cmds_pending--;
+-      if (xhci->xhc_state & XHCI_STATE_REMOVING) {
+-              spin_unlock_irqrestore(&xhci->lock, flags);
+-              return;
+-      }
+-      if (xhci->xhc_state & XHCI_STATE_DYING) {
+-              xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+-                              "Stop EP timer ran, but another timer marked "
+-                              "xHCI as DYING, exiting.");
+-              spin_unlock_irqrestore(&xhci->lock, flags);
+-              return;
+-      }
+       if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
+               xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+                               "Stop EP timer ran, but no command pending, "
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1529,19 +1529,6 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+               xhci_urb_free_priv(urb_priv);
+               return ret;
+       }
+-      if ((xhci->xhc_state & XHCI_STATE_DYING) ||
+-                      (xhci->xhc_state & XHCI_STATE_HALTED)) {
+-              xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+-                              "Ep 0x%x: URB %p to be canceled on "
+-                              "non-responsive xHCI host.",
+-                              urb->ep->desc.bEndpointAddress, urb);
+-              /* Let the stop endpoint command watchdog timer (which set this
+-               * state) finish cleaning up the endpoint TD lists.  We must
+-               * have caught it in the middle of dropping a lock and giving
+-               * back an URB.
+-               */
+-              goto done;
+-      }
+       ep_index = xhci_get_endpoint_index(&urb->ep->desc);
+       ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index];