From: Greg Kroah-Hartman Date: Tue, 17 Jan 2017 13:12:50 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.9.5~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4893a81604b4d87c381c4dd8fe53ab4833f802d2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches 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 --- 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 index 00000000000..01852f275d2 --- /dev/null +++ b/queue-4.9/asoc-hdmi-codec-use-unsigned-type-to-structure-members-with-bit-field.patch @@ -0,0 +1,72 @@ +From 9e4d59ada4d602e78eee9fb5f898ce61fdddb446 Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +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 + +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 +Acked-by: Arnaud Pouliquen +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..b4fe21763ea --- /dev/null +++ b/queue-4.9/btrfs-fix-crash-when-tracepoint-arguments-are-freed-by-wq-callbacks.patch @@ -0,0 +1,130 @@ +From ac0c7cf8be00f269f82964cf7b144ca3edc5dbc4 Mon Sep 17 00:00:00 2001 +From: David Sterba +Date: Fri, 6 Jan 2017 14:12:51 +0100 +Subject: btrfs: fix crash when tracepoint arguments are freed by wq callbacks + +From: David Sterba + +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 +Reviewed-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d402a22d15f --- /dev/null +++ b/queue-4.9/drivers-char-mem-fix-thinkos-in-kmem-address-checks.patch @@ -0,0 +1,70 @@ +From 488debb9971bc7d0edd6d8080ba78ca02a04f6c4 Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Thu, 5 Jan 2017 17:15:01 +0000 +Subject: drivers: char: mem: Fix thinkos in kmem address checks + +From: Robin Murphy + +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 +Fixes: 148a1bc84398 ("drivers: char: mem: Check {read,write}_kmem() addresses") +Signed-off-by: Robin Murphy +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..3c36154d6c9 --- /dev/null +++ b/queue-4.9/fix-a-fencepost-error-in-pipe_advance.patch @@ -0,0 +1,108 @@ +From b9dc6f65bc5e232d1c05fe34b5daadc7e8bbf1fb Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sat, 14 Jan 2017 19:33:08 -0500 +Subject: fix a fencepost error in pipe_advance() + +From: Al Viro + +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" +Tested-by: "Alan J. Wylie" +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..e6379a207e3 --- /dev/null +++ b/queue-4.9/i2c-fix-kernel-memory-disclosure-in-dev-interface.patch @@ -0,0 +1,32 @@ +From 30f939feaeee23e21391cfc7b484f012eb189c3c Mon Sep 17 00:00:00 2001 +From: Vlad Tsyrklevich +Date: Mon, 9 Jan 2017 22:53:36 +0700 +Subject: i2c: fix kernel memory disclosure in dev interface + +From: Vlad Tsyrklevich + +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 +Signed-off-by: Wolfram Sang +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..403cf90e989 --- /dev/null +++ b/queue-4.9/i2c-print-correct-device-invalid-address.patch @@ -0,0 +1,36 @@ +From 6f724fb3039522486fce2e32e4c0fbe238a6ab02 Mon Sep 17 00:00:00 2001 +From: John Garry +Date: Fri, 6 Jan 2017 19:02:57 +0800 +Subject: i2c: print correct device invalid address + +From: John Garry + +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 +Reviewed-by: Vladimir Zapolskiy +Signed-off-by: Wolfram Sang +Fixes: b4e2f6ac1281 ("i2c: apply DT flags when probing") +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a7a0a6a120e --- /dev/null +++ b/queue-4.9/input-elants_i2c-avoid-divide-by-0-errors-on-bad-touchscreen-data.patch @@ -0,0 +1,91 @@ +From 1c3415a06b1016a596bfe59e0cfee56c773aa958 Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +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 + +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:[] [] 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] [] ? irq_thread_dtor+0xa9/0xa9 +[ 2189.435112] [] irq_thread_fn+0x20/0x40 +[ 2189.435123] [] irq_thread+0x14e/0x222 +[ 2189.435135] [] ? __schedule+0x3b3/0x57a +[ 2189.435145] [] ? wake_threads_waitq+0x2d/0x2d +[ 2189.435156] [] ? irq_thread_fn+0x40/0x40 +[ 2189.435168] [] kthread+0x10e/0x116 +[ 2189.435178] [] ? __kthread_parkme+0x67/0x67 +[ 2189.435189] [] ret_from_fork+0x7c/0xb0 +[ 2189.435199] [] ? __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 ff +83 f8 37 75 15 48 6b f7 37 4c 8d a3 c4 00 00 00 4c 8d ac +[ 2189.435312] RIP [] elants_i2c_irq+0x190/0x200 +[ 2189.435323] RSP +[ 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 +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..87fbec33a57 --- /dev/null +++ b/queue-4.9/mnt-protect-the-mountpoint-hashtable-with-mount_lock.patch @@ -0,0 +1,191 @@ +From 3895dbf8985f656675b5bde610723a29cbce3fa7 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Tue, 3 Jan 2017 14:18:43 +1300 +Subject: mnt: Protect the mountpoint hashtable with mount_lock + +From: Eric W. Biederman + +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 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 +Suggested-by: Al Viro +Acked-by: Al Viro +Signed-off-by: "Eric W. Biederman" +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..8914703a26f --- /dev/null +++ b/queue-4.9/pid-fix-lockdep-deadlock-warning-due-to-ucount_lock.patch @@ -0,0 +1,70 @@ +From add7c65ca426b7a37184dd3d2172394e23d585d6 Mon Sep 17 00:00:00 2001 +From: Andrei Vagin +Date: Wed, 4 Jan 2017 19:28:14 -0800 +Subject: pid: fix lockdep deadlock warning due to ucount_lock + +From: Andrei Vagin + +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: [] __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); + + 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 +Acked-by: Al Viro +Signed-off-by: Eric W. Biederman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..b5b21bfa10a --- /dev/null +++ b/queue-4.9/revert-tty-serial-8250-add-con_consdev-to-flags.patch @@ -0,0 +1,39 @@ +From 6741f551a0b26479de2532ffa43a366747e6dbf3 Mon Sep 17 00:00:00 2001 +From: Herbert Xu +Date: Sun, 11 Dec 2016 10:05:49 +0800 +Subject: Revert "tty: serial: 8250: add CON_CONSDEV to flags" + +From: Herbert Xu + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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, + }; diff --git a/queue-4.9/series b/queue-4.9/series index 64b1d60282f..c548996f2d0 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -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 index 00000000000..7ee0e76da40 --- /dev/null +++ b/queue-4.9/vme-fix-wrong-pointer-utilization-in-ca91cx42_slave_get.patch @@ -0,0 +1,46 @@ +From c8a6a09c1c617402cc9254b2bc8da359a0347d75 Mon Sep 17 00:00:00 2001 +From: Augusto Mecking Caringi +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 + +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 +Acked-By: Martyn Welch +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..182efbf8f0a --- /dev/null +++ b/queue-4.9/xhci-fix-deadlock-at-host-remove-by-running-watchdog-correctly.patch @@ -0,0 +1,81 @@ +From d6169d04097fd9ddf811e63eae4e5cd71e6666e2 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Wed, 11 Jan 2017 17:10:34 +0200 +Subject: xhci: fix deadlock at host remove by running watchdog correctly + +From: Mathias Nyman + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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];