summaryrefslogtreecommitdiffstats
path: root/releases
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2016-02-27 14:29:12 +0000
committerBen Hutchings <ben@decadent.org.uk>2016-02-27 14:29:50 +0000
commit84f094a447a3ffc3d5a4752d53527c397692381a (patch)
tree7e93316d40fc66570397635a7b3620588364914c /releases
parentd66b5deb1f692022ecb93a9c0ffe071ed10a3fe6 (diff)
downloadlinux-stable-queue-84f094a447a3ffc3d5a4752d53527c397692381a.tar.gz
Release 3.2.78
Diffstat (limited to 'releases')
-rw-r--r--releases/3.2.78/af_unix-fix-struct-pid-memory-leak.patch32
-rw-r--r--releases/3.2.78/ahci-intel-dnv-device-ids-sata.patch44
-rw-r--r--releases/3.2.78/alsa-dummy-disable-switching-timer-backend-via-sysfs.patch35
-rw-r--r--releases/3.2.78/alsa-dummy-implement-timer-backend-switching-more-safely.patch171
-rw-r--r--releases/3.2.78/alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch96
-rw-r--r--releases/3.2.78/alsa-rawmidi-fix-race-at-copying-updating-the-position.patch117
-rw-r--r--releases/3.2.78/alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch300
-rw-r--r--releases/3.2.78/alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch29
-rw-r--r--releases/3.2.78/alsa-seq-degrade-the-error-message-for-too-many-opens.patch31
-rw-r--r--releases/3.2.78/alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch31
-rw-r--r--releases/3.2.78/alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch373
-rw-r--r--releases/3.2.78/alsa-seq-fix-race-at-closing-in-virmidi-driver.patch39
-rw-r--r--releases/3.2.78/alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch224
-rw-r--r--releases/3.2.78/alsa-timer-fix-leftover-link-at-closing.patch42
-rw-r--r--releases/3.2.78/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch108
-rw-r--r--releases/3.2.78/alsa-timer-fix-race-at-concurrent-reads.patch85
-rw-r--r--releases/3.2.78/alsa-timer-fix-race-between-stop-and-interrupt.patch40
-rw-r--r--releases/3.2.78/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch32
-rw-r--r--releases/3.2.78/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch30
-rw-r--r--releases/3.2.78/arm-8517-1-icst-avoid-arithmetic-overflow-in-icst_hz.patch70
-rw-r--r--releases/3.2.78/arm-8519-1-icst-try-other-dividends-than-1.patch34
-rw-r--r--releases/3.2.78/btrfs-properly-set-the-termination-value-of-ctx-pos-in-readdir.patch155
-rw-r--r--releases/3.2.78/cdc-acm-exclude-samsung-phone-04e8-685d.patch30
-rw-r--r--releases/3.2.78/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch36
-rw-r--r--releases/3.2.78/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch38
-rw-r--r--releases/3.2.78/crypto-shash-fix-has_key-setting.patch36
-rw-r--r--releases/3.2.78/crypto-user-lock-crypto_alg_list-on-alg-dump.patch89
-rw-r--r--releases/3.2.78/drm-vmwgfx-respect-nomodeset.patch37
-rw-r--r--releases/3.2.78/hrtimer-handle-remaining-time-proper-for-time_low_res.patch224
-rw-r--r--releases/3.2.78/intel_scu_ipcutil-underflow-in-scu_reg_access.patch29
-rw-r--r--releases/3.2.78/itimers-handle-relative-timers-with-config_time_low_res-proper.patch36
-rw-r--r--releases/3.2.78/iw_cxgb3-fix-incorrectly-returning-error-on-success.patch38
-rw-r--r--releases/3.2.78/klist-fix-starting-point-removed-bug-in-klist-iterators.patch61
-rw-r--r--releases/3.2.78/kvm-vmx-fix-mpx-detection.patch36
-rw-r--r--releases/3.2.78/libata-disable-forced-ports_impl-for-ahci-1.3.patch36
-rw-r--r--releases/3.2.78/libata-fix-sff-host-state-machine-locking-while-polling.patch179
-rw-r--r--releases/3.2.78/mm-vmstat-fix-wrong-wq-sleep-when-memory-reclaim-doesn-t-make-any.patch49
-rw-r--r--releases/3.2.78/ocfs2-dlm-clear-refmap-bit-of-recovery-lock-while-doing-local.patch35
-rw-r--r--releases/3.2.78/pci-aer-flush-workqueue-on-device-remove-to-avoid-use-after-free.patch94
-rw-r--r--releases/3.2.78/perf-annotate-browser-fix-behaviour-of-shift-tab-with-nothing.patch39
-rw-r--r--releases/3.2.78/pipe-fix-buffer-offset-after-partially-failed-read.patch51
-rw-r--r--releases/3.2.78/pipe-limit-the-per-user-amount-of-pages-allocated-in-pipes.patch240
-rw-r--r--releases/3.2.78/posix-timers-handle-relative-timers-with-config_time_low_res-proper.patch36
-rw-r--r--releases/3.2.78/pptp-fix-illegal-memory-access-caused-by-multiple-bind-s.patch111
-rw-r--r--releases/3.2.78/revert-xhci-don-t-finish-a-td-if-we-get-a-short-transfer-event-mid.patch58
-rw-r--r--releases/3.2.78/rfkill-fix-rfkill_fop_read-wait_event-usage.patch59
-rw-r--r--releases/3.2.78/saa7134-alsa-only-frees-registered-sound-cards.patch66
-rw-r--r--releases/3.2.78/sched-fix-__sched_setscheduler-vs-load-balancing-race.patch50
-rw-r--r--releases/3.2.78/scsi-fix-crashes-in-sd-and-sr-runtime-pm.patch53
-rw-r--r--releases/3.2.78/scsi_dh_rdac-always-retry-mode-select-on-command-lock-violation.patch40
-rw-r--r--releases/3.2.78/sctp-allow-setting-sctp_sack_immediately-by-the-application.patch37
-rw-r--r--releases/3.2.78/sctp-translate-network-order-to-host-order-when-users-get-a-hmacid.patch47
-rw-r--r--releases/3.2.78/series67
-rw-r--r--releases/3.2.78/tda1004x-only-update-the-frontend-properties-if-locked.patch45
-rw-r--r--releases/3.2.78/timerfd-handle-relative-timers-with-config_time_low_res-proper.patch40
-rw-r--r--releases/3.2.78/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch65
-rw-r--r--releases/3.2.78/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch148
-rw-r--r--releases/3.2.78/unix-properly-account-for-fds-passed-over-unix-sockets.patch131
-rw-r--r--releases/3.2.78/usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch49
-rw-r--r--releases/3.2.78/usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch26
-rw-r--r--releases/3.2.78/usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch39
-rw-r--r--releases/3.2.78/usb-serial-option-adding-support-for-telit-le922.patch54
-rw-r--r--releases/3.2.78/usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch34
-rw-r--r--releases/3.2.78/usb-visor-fix-null-deref-at-probe.patch34
-rw-r--r--releases/3.2.78/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch36
-rw-r--r--releases/3.2.78/virtio_pci-fix-use-after-free-on-release.patch42
-rw-r--r--releases/3.2.78/x86-mm-pat-avoid-truncation-when-converting-cpa-numpages-to-address.patch83
-rw-r--r--releases/3.2.78/xhci-fix-list-corruption-in-urb-dequeue-at-host-removal.patch36
68 files changed, 5017 insertions, 0 deletions
diff --git a/releases/3.2.78/af_unix-fix-struct-pid-memory-leak.patch b/releases/3.2.78/af_unix-fix-struct-pid-memory-leak.patch
new file mode 100644
index 00000000..b5eeca55
--- /dev/null
+++ b/releases/3.2.78/af_unix-fix-struct-pid-memory-leak.patch
@@ -0,0 +1,32 @@
+From: Eric Dumazet <edumazet@google.com>
+Date: Sun, 24 Jan 2016 13:53:50 -0800
+Subject: af_unix: fix struct pid memory leak
+
+commit fa0dc04df259ba2df3ce1920e9690c7842f8fa4b upstream.
+
+Dmitry reported a struct pid leak detected by a syzkaller program.
+
+Bug happens in unix_stream_recvmsg() when we break the loop when a
+signal is pending, without properly releasing scm.
+
+Fixes: b3ca9b02b007 ("net: fix multithreaded signal handling in unix recv routines")
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Rainer Weikusat <rweikusat@mobileactivedefense.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: Backported to 3.2: cookie is *sicob->scm, not scm]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ net/unix/af_unix.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2100,6 +2100,7 @@ static int unix_stream_recvmsg(struct ki
+
+ if (signal_pending(current)) {
+ err = sock_intr_errno(timeo);
++ scm_destroy(siocb->scm);
+ goto out;
+ }
+
diff --git a/releases/3.2.78/ahci-intel-dnv-device-ids-sata.patch b/releases/3.2.78/ahci-intel-dnv-device-ids-sata.patch
new file mode 100644
index 00000000..35a94f90
--- /dev/null
+++ b/releases/3.2.78/ahci-intel-dnv-device-ids-sata.patch
@@ -0,0 +1,44 @@
+From: Alexandra Yates <alexandra.yates@linux.intel.com>
+Date: Fri, 5 Feb 2016 15:27:49 -0800
+Subject: ahci: Intel DNV device IDs SATA
+
+commit 342decff2b846b46fa61eb5ee40986fab79a9a32 upstream.
+
+Adding Intel codename DNV platform device IDs for SATA.
+
+Signed-off-by: Alexandra Yates <alexandra.yates@linux.intel.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/ata/ahci.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -274,6 +274,26 @@ static const struct pci_device_id ahci_p
+ { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
+ { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
++ { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
+ { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
diff --git a/releases/3.2.78/alsa-dummy-disable-switching-timer-backend-via-sysfs.patch b/releases/3.2.78/alsa-dummy-disable-switching-timer-backend-via-sysfs.patch
new file mode 100644
index 00000000..570da831
--- /dev/null
+++ b/releases/3.2.78/alsa-dummy-disable-switching-timer-backend-via-sysfs.patch
@@ -0,0 +1,35 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 28 Jan 2016 07:54:16 +0100
+Subject: ALSA: dummy: Disable switching timer backend via sysfs
+
+commit 7ee96216c31aabe1eb42fb91ff50dae9fcd014b2 upstream.
+
+ALSA dummy driver can switch the timer backend between system timer
+and hrtimer via its hrtimer module option. This can be also switched
+dynamically via sysfs, but it may lead to a memory corruption when
+switching is done while a PCM stream is running; the stream instance
+for the newly switched timer method tries to access the memory that
+was allocated by another timer method although the sizes differ.
+
+As the simplest fix, this patch just disables the switch via sysfs by
+dropping the writable bit.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+ZGEeEBntHW5WHn2GoeE0G_kRrCmUh6=dWyy-wfzvuJLg@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/drivers/dummy.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM su
+ module_param(fake_buffer, bool, 0444);
+ MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
+ #ifdef CONFIG_HIGH_RES_TIMERS
+-module_param(hrtimer, bool, 0644);
++module_param(hrtimer, bool, 0444);
+ MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
+ #endif
+
diff --git a/releases/3.2.78/alsa-dummy-implement-timer-backend-switching-more-safely.patch b/releases/3.2.78/alsa-dummy-implement-timer-backend-switching-more-safely.patch
new file mode 100644
index 00000000..bb162c5d
--- /dev/null
+++ b/releases/3.2.78/alsa-dummy-implement-timer-backend-switching-more-safely.patch
@@ -0,0 +1,171 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 2 Feb 2016 15:27:36 +0100
+Subject: ALSA: dummy: Implement timer backend switching more safely
+
+commit ddce57a6f0a2d8d1bfacfa77f06043bc760403c2 upstream.
+
+Currently the selected timer backend is referred at any moment from
+the running PCM callbacks. When the backend is switched, it's
+possible to lead to inconsistency from the running backend. This was
+pointed by syzkaller fuzzer, and the commit [7ee96216c31a: ALSA:
+dummy: Disable switching timer backend via sysfs] disabled the dynamic
+switching for avoiding the crash.
+
+This patch improves the handling of timer backend switching. It keeps
+the reference to the selected backend during the whole operation of an
+opened stream so that it won't be changed by other streams.
+
+Together with this change, the hrtimer parameter is reenabled as
+writable now.
+
+NOTE: this patch also turned out to fix the still remaining race.
+Namely, ops was still replaced dynamically at dummy_pcm_open:
+
+ static int dummy_pcm_open(struct snd_pcm_substream *substream)
+ {
+ ....
+ dummy->timer_ops = &dummy_systimer_ops;
+ if (hrtimer)
+ dummy->timer_ops = &dummy_hrtimer_ops;
+
+Since dummy->timer_ops is common among all streams, and when the
+replacement happens during accesses of other streams, it may lead to a
+crash. This was actually triggered by syzkaller fuzzer and KASAN.
+
+This patch rewrites the code not to use the ops shared by all streams
+any longer, too.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+aZ+xisrpuM6cOXbL21DuM0yVxPYXf4cD4Md9uw0C3dBQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/drivers/dummy.c | 37 +++++++++++++++++++------------------
+ 1 file changed, 19 insertions(+), 18 deletions(-)
+
+--- a/sound/drivers/dummy.c
++++ b/sound/drivers/dummy.c
+@@ -87,7 +87,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM su
+ module_param(fake_buffer, bool, 0444);
+ MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
+ #ifdef CONFIG_HIGH_RES_TIMERS
+-module_param(hrtimer, bool, 0444);
++module_param(hrtimer, bool, 0644);
+ MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
+ #endif
+
+@@ -109,6 +109,9 @@ struct dummy_timer_ops {
+ snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
+ };
+
++#define get_dummy_ops(substream) \
++ (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
++
+ struct dummy_model {
+ const char *name;
+ int (*playback_constraints)(struct snd_pcm_runtime *runtime);
+@@ -134,7 +137,6 @@ struct snd_dummy {
+ spinlock_t mixer_lock;
+ int mixer_volume[MIXER_ADDR_LAST+1][2];
+ int capture_source[MIXER_ADDR_LAST+1][2];
+- const struct dummy_timer_ops *timer_ops;
+ };
+
+ /*
+@@ -228,6 +230,8 @@ struct dummy_model *dummy_models[] = {
+ */
+
+ struct dummy_systimer_pcm {
++ /* ops must be the first item */
++ const struct dummy_timer_ops *timer_ops;
+ spinlock_t lock;
+ struct timer_list timer;
+ unsigned long base_time;
+@@ -365,6 +369,8 @@ static struct dummy_timer_ops dummy_syst
+ */
+
+ struct dummy_hrtimer_pcm {
++ /* ops must be the first item */
++ const struct dummy_timer_ops *timer_ops;
+ ktime_t base_time;
+ ktime_t period_time;
+ atomic_t running;
+@@ -491,31 +497,25 @@ static struct dummy_timer_ops dummy_hrti
+
+ static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+- return dummy->timer_ops->start(substream);
++ return get_dummy_ops(substream)->start(substream);
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+- return dummy->timer_ops->stop(substream);
++ return get_dummy_ops(substream)->stop(substream);
+ }
+ return -EINVAL;
+ }
+
+ static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+- return dummy->timer_ops->prepare(substream);
++ return get_dummy_ops(substream)->prepare(substream);
+ }
+
+ static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+-
+- return dummy->timer_ops->pointer(substream);
++ return get_dummy_ops(substream)->pointer(substream);
+ }
+
+ static struct snd_pcm_hardware dummy_pcm_hardware = {
+@@ -561,17 +561,19 @@ static int dummy_pcm_open(struct snd_pcm
+ struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+ struct dummy_model *model = dummy->model;
+ struct snd_pcm_runtime *runtime = substream->runtime;
++ const struct dummy_timer_ops *ops;
+ int err;
+
+- dummy->timer_ops = &dummy_systimer_ops;
++ ops = &dummy_systimer_ops;
+ #ifdef CONFIG_HIGH_RES_TIMERS
+ if (hrtimer)
+- dummy->timer_ops = &dummy_hrtimer_ops;
++ ops = &dummy_hrtimer_ops;
+ #endif
+
+- err = dummy->timer_ops->create(substream);
++ err = ops->create(substream);
+ if (err < 0)
+ return err;
++ get_dummy_ops(substream) = ops;
+
+ runtime->hw = dummy->pcm_hw;
+ if (substream->pcm->device & 1) {
+@@ -593,7 +595,7 @@ static int dummy_pcm_open(struct snd_pcm
+ err = model->capture_constraints(substream->runtime);
+ }
+ if (err < 0) {
+- dummy->timer_ops->free(substream);
++ get_dummy_ops(substream)->free(substream);
+ return err;
+ }
+ return 0;
+@@ -601,8 +603,7 @@ static int dummy_pcm_open(struct snd_pcm
+
+ static int dummy_pcm_close(struct snd_pcm_substream *substream)
+ {
+- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
+- dummy->timer_ops->free(substream);
++ get_dummy_ops(substream)->free(substream);
+ return 0;
+ }
+
diff --git a/releases/3.2.78/alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch b/releases/3.2.78/alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch
new file mode 100644
index 00000000..4e850e28
--- /dev/null
+++ b/releases/3.2.78/alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch
@@ -0,0 +1,96 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 31 Jan 2016 10:32:37 +0100
+Subject: ALSA: pcm: Fix potential deadlock in OSS emulation
+
+commit b248371628aad599a48540962f6b85a21a8a0c3f upstream.
+
+There are potential deadlocks in PCM OSS emulation code while
+accessing read/write and mmap concurrently. This comes from the
+infamous mmap_sem usage in copy_from/to_user(). Namely,
+
+ snd_pcm_oss_write() ->
+ &runtime->oss.params_lock ->
+ copy_to_user() ->
+ &mm->mmap_sem
+ mmap() ->
+ &mm->mmap_sem ->
+ snd_pcm_oss_mmap() ->
+ &runtime->oss.params_lock
+
+Since we can't avoid taking params_lock from mmap code path, use
+trylock variant and aborts with -EAGAIN as a workaround of this AB/BA
+deadlock.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+bVrBKDG0G2_AcUgUQa+X91VKTeS4v+wN7BSHwHtqn3kQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/oss/pcm_oss.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_su
+ return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
+ }
+
+-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
++static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
++ bool trylock)
+ {
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_pcm_hw_params *params, *sparams;
+@@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(str
+ struct snd_mask sformat_mask;
+ struct snd_mask mask;
+
+- if (mutex_lock_interruptible(&runtime->oss.params_lock))
++ if (trylock) {
++ if (!(mutex_trylock(&runtime->oss.params_lock)))
++ return -EAGAIN;
++ } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
+ return -EINTR;
+ sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+@@ -1091,7 +1095,7 @@ static int snd_pcm_oss_get_active_substr
+ if (asubstream == NULL)
+ asubstream = substream;
+ if (substream->runtime->oss.params) {
+- err = snd_pcm_oss_change_params(substream);
++ err = snd_pcm_oss_change_params(substream, false);
+ if (err < 0)
+ return err;
+ }
+@@ -1130,7 +1134,7 @@ static int snd_pcm_oss_make_ready(struct
+ return 0;
+ runtime = substream->runtime;
+ if (runtime->oss.params) {
+- err = snd_pcm_oss_change_params(substream);
++ err = snd_pcm_oss_change_params(substream, false);
+ if (err < 0)
+ return err;
+ }
+@@ -2168,7 +2172,7 @@ static int snd_pcm_oss_get_space(struct
+ runtime = substream->runtime;
+
+ if (runtime->oss.params &&
+- (err = snd_pcm_oss_change_params(substream)) < 0)
++ (err = snd_pcm_oss_change_params(substream, false)) < 0)
+ return err;
+
+ info.fragsize = runtime->oss.period_bytes;
+@@ -2804,7 +2808,12 @@ static int snd_pcm_oss_mmap(struct file
+ return -EIO;
+
+ if (runtime->oss.params) {
+- if ((err = snd_pcm_oss_change_params(substream)) < 0)
++ /* use mutex_trylock() for params_lock for avoiding a deadlock
++ * between mmap_sem and params_lock taken by
++ * copy_from/to_user() in snd_pcm_oss_write/read()
++ */
++ err = snd_pcm_oss_change_params(substream, true);
++ if (err < 0)
+ return err;
+ }
+ #ifdef CONFIG_SND_PCM_OSS_PLUGINS
diff --git a/releases/3.2.78/alsa-rawmidi-fix-race-at-copying-updating-the-position.patch b/releases/3.2.78/alsa-rawmidi-fix-race-at-copying-updating-the-position.patch
new file mode 100644
index 00000000..7cb47198
--- /dev/null
+++ b/releases/3.2.78/alsa-rawmidi-fix-race-at-copying-updating-the-position.patch
@@ -0,0 +1,117 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 3 Feb 2016 14:41:22 +0100
+Subject: ALSA: rawmidi: Fix race at copying & updating the position
+
+commit 81f577542af15640cbcb6ef68baa4caa610cbbfc upstream.
+
+The rawmidi read and write functions manage runtime stream status
+such as runtime->appl_ptr and runtime->avail. These point where to
+copy the new data and how many bytes have been copied (or to be
+read). The problem is that rawmidi read/write call copy_from_user()
+or copy_to_user(), and the runtime spinlock is temporarily unlocked
+and relocked while copying user-space. Since the current code
+advances and updates the runtime status after the spin unlock/relock,
+the copy and the update may be asynchronous, and eventually
+runtime->avail might go to a negative value when many concurrent
+accesses are done. This may lead to memory corruption in the end.
+
+For fixing this race, in this patch, the status update code is
+performed in the same lock before the temporary unlock. Also, the
+spinlock is now taken more widely in snd_rawmidi_kernel_read1() for
+protecting more properly during the whole operation.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+b-dCmNf1GpgPKfDO0ih+uZCL2JV4__j-r1kdhPLSgQCQ@mail.gmail.com
+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: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/rawmidi.c | 34 ++++++++++++++++++++++------------
+ 1 file changed, 22 insertions(+), 12 deletions(-)
+
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -934,31 +934,36 @@ static long snd_rawmidi_kernel_read1(str
+ unsigned long flags;
+ long result = 0, count1;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ unsigned long appl_ptr;
+
++ spin_lock_irqsave(&runtime->lock, flags);
+ while (count > 0 && runtime->avail) {
+ count1 = runtime->buffer_size - runtime->appl_ptr;
+ if (count1 > count)
+ count1 = count;
+- spin_lock_irqsave(&runtime->lock, flags);
+ if (count1 > (int)runtime->avail)
+ count1 = runtime->avail;
++
++ /* update runtime->appl_ptr before unlocking for userbuf */
++ appl_ptr = runtime->appl_ptr;
++ runtime->appl_ptr += count1;
++ runtime->appl_ptr %= runtime->buffer_size;
++ runtime->avail -= count1;
++
+ if (kernelbuf)
+- memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
++ memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
+ if (userbuf) {
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ if (copy_to_user(userbuf + result,
+- runtime->buffer + runtime->appl_ptr, count1)) {
++ runtime->buffer + appl_ptr, count1)) {
+ return result > 0 ? result : -EFAULT;
+ }
+ spin_lock_irqsave(&runtime->lock, flags);
+ }
+- runtime->appl_ptr += count1;
+- runtime->appl_ptr %= runtime->buffer_size;
+- runtime->avail -= count1;
+- spin_unlock_irqrestore(&runtime->lock, flags);
+ result += count1;
+ count -= count1;
+ }
++ spin_unlock_irqrestore(&runtime->lock, flags);
+ return result;
+ }
+
+@@ -1207,6 +1212,7 @@ static long snd_rawmidi_kernel_write1(st
+ unsigned long flags;
+ long count1, result;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ unsigned long appl_ptr;
+
+ if (!kernelbuf && !userbuf)
+ return -EINVAL;
+@@ -1227,12 +1233,19 @@ static long snd_rawmidi_kernel_write1(st
+ count1 = count;
+ if (count1 > (long)runtime->avail)
+ count1 = runtime->avail;
++
++ /* update runtime->appl_ptr before unlocking for userbuf */
++ appl_ptr = runtime->appl_ptr;
++ runtime->appl_ptr += count1;
++ runtime->appl_ptr %= runtime->buffer_size;
++ runtime->avail -= count1;
++
+ if (kernelbuf)
+- memcpy(runtime->buffer + runtime->appl_ptr,
++ memcpy(runtime->buffer + appl_ptr,
+ kernelbuf + result, count1);
+ else if (userbuf) {
+ spin_unlock_irqrestore(&runtime->lock, flags);
+- if (copy_from_user(runtime->buffer + runtime->appl_ptr,
++ if (copy_from_user(runtime->buffer + appl_ptr,
+ userbuf + result, count1)) {
+ spin_lock_irqsave(&runtime->lock, flags);
+ result = result > 0 ? result : -EFAULT;
+@@ -1240,9 +1253,6 @@ static long snd_rawmidi_kernel_write1(st
+ }
+ spin_lock_irqsave(&runtime->lock, flags);
+ }
+- runtime->appl_ptr += count1;
+- runtime->appl_ptr %= runtime->buffer_size;
+- runtime->avail -= count1;
+ result += count1;
+ count -= count1;
+ }
diff --git a/releases/3.2.78/alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch b/releases/3.2.78/alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch
new file mode 100644
index 00000000..d2711171
--- /dev/null
+++ b/releases/3.2.78/alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch
@@ -0,0 +1,300 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sun, 31 Jan 2016 11:57:41 +0100
+Subject: ALSA: rawmidi: Make snd_rawmidi_transmit() race-free
+
+commit 06ab30034ed9c200a570ab13c017bde248ddb2a6 upstream.
+
+A kernel WARNING in snd_rawmidi_transmit_ack() is triggered by
+syzkaller fuzzer:
+ WARNING: CPU: 1 PID: 20739 at sound/core/rawmidi.c:1136
+Call Trace:
+ [< inline >] __dump_stack lib/dump_stack.c:15
+ [<ffffffff82999e2d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
+ [<ffffffff81352089>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
+ [<ffffffff813522b9>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
+ [<ffffffff84f80bd5>] snd_rawmidi_transmit_ack+0x275/0x400 sound/core/rawmidi.c:1136
+ [<ffffffff84fdb3c1>] snd_virmidi_output_trigger+0x4b1/0x5a0 sound/core/seq/seq_virmidi.c:163
+ [< inline >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
+ [<ffffffff84f87ed9>] snd_rawmidi_kernel_write1+0x549/0x780 sound/core/rawmidi.c:1223
+ [<ffffffff84f89fd3>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1273
+ [<ffffffff817b0323>] __vfs_write+0x113/0x480 fs/read_write.c:528
+ [<ffffffff817b1db7>] vfs_write+0x167/0x4a0 fs/read_write.c:577
+ [< inline >] SYSC_write fs/read_write.c:624
+ [<ffffffff817b50a1>] SyS_write+0x111/0x220 fs/read_write.c:616
+ [<ffffffff86336c36>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185
+
+Also a similar warning is found but in another path:
+Call Trace:
+ [< inline >] __dump_stack lib/dump_stack.c:15
+ [<ffffffff82be2c0d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
+ [<ffffffff81355139>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
+ [<ffffffff81355369>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
+ [<ffffffff8527e69a>] rawmidi_transmit_ack+0x24a/0x3b0 sound/core/rawmidi.c:1133
+ [<ffffffff8527e851>] snd_rawmidi_transmit_ack+0x51/0x80 sound/core/rawmidi.c:1163
+ [<ffffffff852d9046>] snd_virmidi_output_trigger+0x2b6/0x570 sound/core/seq/seq_virmidi.c:185
+ [< inline >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
+ [<ffffffff85285a0b>] snd_rawmidi_kernel_write1+0x4bb/0x760 sound/core/rawmidi.c:1252
+ [<ffffffff85287b73>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1302
+ [<ffffffff817ba5f3>] __vfs_write+0x113/0x480 fs/read_write.c:528
+ [<ffffffff817bc087>] vfs_write+0x167/0x4a0 fs/read_write.c:577
+ [< inline >] SYSC_write fs/read_write.c:624
+ [<ffffffff817bf371>] SyS_write+0x111/0x220 fs/read_write.c:616
+ [<ffffffff86660276>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185
+
+In the former case, the reason is that virmidi has an open code
+calling snd_rawmidi_transmit_ack() with the value calculated outside
+the spinlock. We may use snd_rawmidi_transmit() in a loop just for
+consuming the input data, but even there, there is a race between
+snd_rawmidi_transmit_peek() and snd_rawmidi_tranmit_ack().
+
+Similarly in the latter case, it calls snd_rawmidi_transmit_peek() and
+snd_rawmidi_tranmit_ack() separately without protection, so they are
+racy as well.
+
+The patch tries to address these issues by the following ways:
+- Introduce the unlocked versions of snd_rawmidi_transmit_peek() and
+ snd_rawmidi_transmit_ack() to be called inside the explicit lock.
+- Rewrite snd_rawmidi_transmit() to be race-free (the former case).
+- Make the split calls (the latter case) protected in the rawmidi spin
+ lock.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+YPq1+cYLkadwjWa5XjzF1_Vki1eHnVn-Lm0hzhSpu5PA@mail.gmail.com
+BugLink: http://lkml.kernel.org/r/CACT4Y+acG4iyphdOZx47Nyq_VHGbpJQK-6xNpiqUjaZYqsXOGw@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ include/sound/rawmidi.h | 4 ++
+ sound/core/rawmidi.c | 98 ++++++++++++++++++++++++++++++++------------
+ sound/core/seq/seq_virmidi.c | 17 +++++---
+ 3 files changed, 88 insertions(+), 31 deletions(-)
+
+--- a/include/sound/rawmidi.h
++++ b/include/sound/rawmidi.h
+@@ -167,6 +167,10 @@ int snd_rawmidi_transmit_peek(struct snd
+ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
+ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count);
++int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++ unsigned char *buffer, int count);
++int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
++ int count);
+
+ /* main midi functions */
+
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -1044,23 +1044,16 @@ int snd_rawmidi_transmit_empty(struct sn
+ }
+
+ /**
+- * snd_rawmidi_transmit_peek - copy data from the internal buffer
++ * __snd_rawmidi_transmit_peek - copy data from the internal buffer
+ * @substream: the rawmidi substream
+ * @buffer: the buffer pointer
+ * @count: data size to transfer
+ *
+- * Copies data from the internal output buffer to the given buffer.
+- *
+- * Call this in the interrupt handler when the midi output is ready,
+- * and call snd_rawmidi_transmit_ack() after the transmission is
+- * finished.
+- *
+- * Returns the size of copied data, or a negative error code on failure.
++ * This is a variant of snd_rawmidi_transmit_peek() without spinlock.
+ */
+-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count)
+ {
+- unsigned long flags;
+ int result, count1;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
+@@ -1069,7 +1062,6 @@ int snd_rawmidi_transmit_peek(struct snd
+ return -EINVAL;
+ }
+ result = 0;
+- spin_lock_irqsave(&runtime->lock, flags);
+ if (runtime->avail >= runtime->buffer_size) {
+ /* warning: lowlevel layer MUST trigger down the hardware */
+ goto __skip;
+@@ -1094,31 +1086,52 @@ int snd_rawmidi_transmit_peek(struct snd
+ }
+ }
+ __skip:
+- spin_unlock_irqrestore(&runtime->lock, flags);
+ return result;
+ }
++EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
+
+ /**
+- * snd_rawmidi_transmit_ack - acknowledge the transmission
++ * snd_rawmidi_transmit_peek - copy data from the internal buffer
+ * @substream: the rawmidi substream
+- * @count: the tranferred count
++ * @buffer: the buffer pointer
++ * @count: data size to transfer
+ *
+- * Advances the hardware pointer for the internal output buffer with
+- * the given size and updates the condition.
+- * Call after the transmission is finished.
++ * Copies data from the internal output buffer to the given buffer.
+ *
+- * Returns the advanced size if successful, or a negative error code on failure.
++ * Call this in the interrupt handler when the midi output is ready,
++ * and call snd_rawmidi_transmit_ack() after the transmission is
++ * finished.
++ *
++ * Return: The size of copied data, or a negative error code on failure.
+ */
+-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
++int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
++ unsigned char *buffer, int count)
+ {
++ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ int result;
+ unsigned long flags;
++
++ spin_lock_irqsave(&runtime->lock, flags);
++ result = __snd_rawmidi_transmit_peek(substream, buffer, count);
++ spin_unlock_irqrestore(&runtime->lock, flags);
++ return result;
++}
++
++/**
++ * __snd_rawmidi_transmit_ack - acknowledge the transmission
++ * @substream: the rawmidi substream
++ * @count: the tranferred count
++ *
++ * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
++ */
++int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
++{
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
+ if (runtime->buffer == NULL) {
+ snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n");
+ return -EINVAL;
+ }
+- spin_lock_irqsave(&runtime->lock, flags);
+ snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
+ runtime->hw_ptr += count;
+ runtime->hw_ptr %= runtime->buffer_size;
+@@ -1128,9 +1141,32 @@ int snd_rawmidi_transmit_ack(struct snd_
+ if (runtime->drain || snd_rawmidi_ready(substream))
+ wake_up(&runtime->sleep);
+ }
+- spin_unlock_irqrestore(&runtime->lock, flags);
+ return count;
+ }
++EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
++
++/**
++ * snd_rawmidi_transmit_ack - acknowledge the transmission
++ * @substream: the rawmidi substream
++ * @count: the transferred count
++ *
++ * Advances the hardware pointer for the internal output buffer with
++ * the given size and updates the condition.
++ * Call after the transmission is finished.
++ *
++ * Return: The advanced size if successful, or a negative error code on failure.
++ */
++int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
++{
++ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ int result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&runtime->lock, flags);
++ result = __snd_rawmidi_transmit_ack(substream, count);
++ spin_unlock_irqrestore(&runtime->lock, flags);
++ return result;
++}
+
+ /**
+ * snd_rawmidi_transmit - copy from the buffer to the device
+@@ -1145,12 +1181,22 @@ int snd_rawmidi_transmit_ack(struct snd_
+ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count)
+ {
++ struct snd_rawmidi_runtime *runtime = substream->runtime;
++ int result;
++ unsigned long flags;
++
++ spin_lock_irqsave(&runtime->lock, flags);
+ if (!substream->opened)
+- return -EBADFD;
+- count = snd_rawmidi_transmit_peek(substream, buffer, count);
+- if (count < 0)
+- return count;
+- return snd_rawmidi_transmit_ack(substream, count);
++ result = -EBADFD;
++ else {
++ count = __snd_rawmidi_transmit_peek(substream, buffer, count);
++ if (count <= 0)
++ result = count;
++ else
++ result = __snd_rawmidi_transmit_ack(substream, count);
++ }
++ spin_unlock_irqrestore(&runtime->lock, flags);
++ return result;
+ }
+
+ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
+--- a/sound/core/seq/seq_virmidi.c
++++ b/sound/core/seq/seq_virmidi.c
+@@ -155,21 +155,26 @@ static void snd_virmidi_output_trigger(s
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
+ int count, res;
+ unsigned char buf[32], *pbuf;
++ unsigned long flags;
+
+ if (up) {
+ vmidi->trigger = 1;
+ if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
+ !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
+- snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail);
+- return; /* ignored */
++ while (snd_rawmidi_transmit(substream, buf,
++ sizeof(buf)) > 0) {
++ /* ignored */
++ }
++ return;
+ }
+ if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+ return;
+ vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+ }
++ spin_lock_irqsave(&substream->runtime->lock, flags);
+ while (1) {
+- count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
++ count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
+ if (count <= 0)
+ break;
+ pbuf = buf;
+@@ -179,16 +184,18 @@ static void snd_virmidi_output_trigger(s
+ snd_midi_event_reset_encode(vmidi->parser);
+ continue;
+ }
+- snd_rawmidi_transmit_ack(substream, res);
++ __snd_rawmidi_transmit_ack(substream, res);
+ pbuf += res;
+ count -= res;
+ if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
+ if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
+- return;
++ goto out;
+ vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
+ }
+ }
+ }
++ out:
++ spin_unlock_irqrestore(&substream->runtime->lock, flags);
+ } else {
+ vmidi->trigger = 0;
+ }
diff --git a/releases/3.2.78/alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch b/releases/3.2.78/alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch
new file mode 100644
index 00000000..47b13c4b
--- /dev/null
+++ b/releases/3.2.78/alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch
@@ -0,0 +1,29 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 1 Feb 2016 12:04:55 +0100
+Subject: ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check
+
+commit cc85f7a634cfaf9f0713c6aa06d08817424db37a upstream.
+
+NULL user-space buffer can be passed even in a normal path, thus it's
+not good to spew a kernel warning with stack trace at each time.
+Just drop snd_BUG_ON() macro usage there.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+YfVJ3L+q0i-4vyQVyyPD7V=OMX0PWPi29x9Bo3QaBLdw@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/rawmidi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/rawmidi.c
++++ b/sound/core/rawmidi.c
+@@ -1162,7 +1162,7 @@ static long snd_rawmidi_kernel_write1(st
+ long count1, result;
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+
+- if (snd_BUG_ON(!kernelbuf && !userbuf))
++ if (!kernelbuf && !userbuf)
+ return -EINVAL;
+ if (snd_BUG_ON(!runtime->buffer))
+ return -EINVAL;
diff --git a/releases/3.2.78/alsa-seq-degrade-the-error-message-for-too-many-opens.patch b/releases/3.2.78/alsa-seq-degrade-the-error-message-for-too-many-opens.patch
new file mode 100644
index 00000000..b7a4e715
--- /dev/null
+++ b/releases/3.2.78/alsa-seq-degrade-the-error-message-for-too-many-opens.patch
@@ -0,0 +1,31 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 25 Jan 2016 11:24:56 +0100
+Subject: ALSA: seq: Degrade the error message for too many opens
+
+commit da10816e3d923565b470fec78a674baba794ed33 upstream.
+
+ALSA OSS sequencer spews a kernel error message ("ALSA: seq_oss: too
+many applications") when user-space tries to open more than the
+limit. This means that it can easily fill the log buffer.
+
+Since it's merely a normal error, it's safe to suppress it via
+pr_debug() instead.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[bwh: Backported to 3.2: this was still using snd_printk()]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/seq/oss/seq_oss_init.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/seq/oss/seq_oss_init.c
++++ b/sound/core/seq/oss/seq_oss_init.c
+@@ -196,7 +196,7 @@ snd_seq_oss_open(struct file *file, int
+
+ dp->index = i;
+ if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
+- snd_printk(KERN_ERR "too many applications\n");
++ pr_debug("ALSA: seq_oss: too many applications\n");
+ rc = -ENOMEM;
+ goto _error;
+ }
diff --git a/releases/3.2.78/alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch b/releases/3.2.78/alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch
new file mode 100644
index 00000000..44bb49f4
--- /dev/null
+++ b/releases/3.2.78/alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch
@@ -0,0 +1,31 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 25 Jan 2016 11:01:47 +0100
+Subject: ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup()
+
+commit 599151336638d57b98d92338aa59c048e3a3e97d upstream.
+
+ALSA sequencer OSS emulation code has a sanity check for currently
+opened devices, but there is a thinko there, eventually it spews
+warnings and skips the operation wrongly like:
+ WARNING: CPU: 1 PID: 7573 at sound/core/seq/oss/seq_oss_synth.c:311
+
+Fix this off-by-one error.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/seq/oss/seq_oss_synth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/seq/oss/seq_oss_synth.c
++++ b/sound/core/seq/oss/seq_oss_synth.c
+@@ -310,7 +310,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss
+ struct seq_oss_synth *rec;
+ struct seq_oss_synthinfo *info;
+
+- if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
++ if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
+ return;
+ for (i = 0; i < dp->max_synthdev; i++) {
+ info = &dp->synths[i];
diff --git a/releases/3.2.78/alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch b/releases/3.2.78/alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch
new file mode 100644
index 00000000..4853896e
--- /dev/null
+++ b/releases/3.2.78/alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch
@@ -0,0 +1,373 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 3 Feb 2016 08:32:44 +0100
+Subject: ALSA: seq: Fix lockdep warnings due to double mutex locks
+
+commit 7f0973e973cd74aa40747c9d38844560cd184ee8 upstream.
+
+The port subscription code uses double mutex locks for source and
+destination ports, and this may become racy once when wrongly set up.
+It leads to lockdep warning splat, typically triggered by fuzzer like
+syzkaller, although the actual deadlock hasn't been seen, so far.
+
+This patch simplifies the handling by reducing to two single locks, so
+that no lockdep warning will be trigger any longer.
+
+By splitting to two actions, a still-in-progress element shall be
+added in one list while handling another. For ignoring this element,
+a new check is added in deliver_to_subscribers().
+
+Along with it, the code to add/remove the subscribers list element was
+cleaned up and refactored.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+aKQXV7xkBW9hpQbzaDO7LrUvohxWh-UwMxXjDy-yBD=A@mail.gmail.com
+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: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/seq/seq_clientmgr.c | 3 +
+ sound/core/seq/seq_ports.c | 233 +++++++++++++++++++++++------------------
+ 2 files changed, 133 insertions(+), 103 deletions(-)
+
+--- a/sound/core/seq/seq_clientmgr.c
++++ b/sound/core/seq/seq_clientmgr.c
+@@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct
+ else
+ down_read(&grp->list_mutex);
+ list_for_each_entry(subs, &grp->list_head, src_list) {
++ /* both ports ready? */
++ if (atomic_read(&subs->ref_count) != 2)
++ continue;
+ event->dest = subs->info.dest;
+ if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
+ /* convert time according to flag with subscription */
+--- a/sound/core/seq/seq_ports.c
++++ b/sound/core/seq/seq_ports.c
+@@ -175,10 +175,6 @@ struct snd_seq_client_port *snd_seq_crea
+ }
+
+ /* */
+-enum group_type {
+- SRC_LIST, DEST_LIST
+-};
+-
+ static int subscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+@@ -205,6 +201,20 @@ static struct snd_seq_client_port *get_c
+ return NULL;
+ }
+
++static void delete_and_unsubscribe_port(struct snd_seq_client *client,
++ struct snd_seq_client_port *port,
++ struct snd_seq_subscribers *subs,
++ bool is_src, bool ack);
++
++static inline struct snd_seq_subscribers *
++get_subscriber(struct list_head *p, bool is_src)
++{
++ if (is_src)
++ return list_entry(p, struct snd_seq_subscribers, src_list);
++ else
++ return list_entry(p, struct snd_seq_subscribers, dest_list);
++}
++
+ /*
+ * remove all subscribers on the list
+ * this is called from port_delete, for each src and dest list.
+@@ -212,7 +222,7 @@ static struct snd_seq_client_port *get_c
+ static void clear_subscriber_list(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_port_subs_info *grp,
+- int grptype)
++ int is_src)
+ {
+ struct list_head *p, *n;
+
+@@ -221,15 +231,13 @@ static void clear_subscriber_list(struct
+ struct snd_seq_client *c;
+ struct snd_seq_client_port *aport;
+
+- if (grptype == SRC_LIST) {
+- subs = list_entry(p, struct snd_seq_subscribers, src_list);
++ subs = get_subscriber(p, is_src);
++ if (is_src)
+ aport = get_client_port(&subs->info.dest, &c);
+- } else {
+- subs = list_entry(p, struct snd_seq_subscribers, dest_list);
++ else
+ aport = get_client_port(&subs->info.sender, &c);
+- }
+- list_del(p);
+- unsubscribe_port(client, port, grp, &subs->info, 0);
++ delete_and_unsubscribe_port(client, port, subs, is_src, false);
++
+ if (!aport) {
+ /* looks like the connected port is being deleted.
+ * we decrease the counter, and when both ports are deleted
+@@ -237,21 +245,14 @@ static void clear_subscriber_list(struct
+ */
+ if (atomic_dec_and_test(&subs->ref_count))
+ kfree(subs);
+- } else {
+- /* ok we got the connected port */
+- struct snd_seq_port_subs_info *agrp;
+- agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
+- down_write(&agrp->list_mutex);
+- if (grptype == SRC_LIST)
+- list_del(&subs->dest_list);
+- else
+- list_del(&subs->src_list);
+- up_write(&agrp->list_mutex);
+- unsubscribe_port(c, aport, agrp, &subs->info, 1);
+- kfree(subs);
+- snd_seq_port_unlock(aport);
+- snd_seq_client_unlock(c);
++ continue;
+ }
++
++ /* ok we got the connected port */
++ delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
++ kfree(subs);
++ snd_seq_port_unlock(aport);
++ snd_seq_client_unlock(c);
+ }
+ }
+
+@@ -264,8 +265,8 @@ static int port_delete(struct snd_seq_cl
+ snd_use_lock_sync(&port->use_lock);
+
+ /* clear subscribers info */
+- clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
+- clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
++ clear_subscriber_list(client, port, &port->c_src, true);
++ clear_subscriber_list(client, port, &port->c_dest, false);
+
+ if (port->private_free)
+ port->private_free(port->private_data);
+@@ -484,85 +485,120 @@ static int match_subs_info(struct snd_se
+ return 0;
+ }
+
++static int check_and_subscribe_port(struct snd_seq_client *client,
++ struct snd_seq_client_port *port,
++ struct snd_seq_subscribers *subs,
++ bool is_src, bool exclusive, bool ack)
++{
++ struct snd_seq_port_subs_info *grp;
++ struct list_head *p;
++ struct snd_seq_subscribers *s;
++ int err;
+
+-/* connect two ports */
+-int snd_seq_port_connect(struct snd_seq_client *connector,
+- struct snd_seq_client *src_client,
+- struct snd_seq_client_port *src_port,
+- struct snd_seq_client *dest_client,
+- struct snd_seq_client_port *dest_port,
+- struct snd_seq_port_subscribe *info)
+-{
+- struct snd_seq_port_subs_info *src = &src_port->c_src;
+- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+- struct snd_seq_subscribers *subs, *s;
+- int err, src_called = 0;
+- unsigned long flags;
+- int exclusive;
+-
+- subs = kzalloc(sizeof(*subs), GFP_KERNEL);
+- if (! subs)
+- return -ENOMEM;
+-
+- subs->info = *info;
+- atomic_set(&subs->ref_count, 2);
+-
+- down_write(&src->list_mutex);
+- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
+-
+- exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
++ grp = is_src ? &port->c_src : &port->c_dest;
+ err = -EBUSY;
++ down_write(&grp->list_mutex);
+ if (exclusive) {
+- if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
++ if (!list_empty(&grp->list_head))
+ goto __error;
+ } else {
+- if (src->exclusive || dest->exclusive)
++ if (grp->exclusive)
+ goto __error;
+ /* check whether already exists */
+- list_for_each_entry(s, &src->list_head, src_list) {
+- if (match_subs_info(info, &s->info))
+- goto __error;
+- }
+- list_for_each_entry(s, &dest->list_head, dest_list) {
+- if (match_subs_info(info, &s->info))
++ list_for_each(p, &grp->list_head) {
++ s = get_subscriber(p, is_src);
++ if (match_subs_info(&subs->info, &s->info))
+ goto __error;
+ }
+ }
+
+- if ((err = subscribe_port(src_client, src_port, src, info,
+- connector->number != src_client->number)) < 0)
+- goto __error;
+- src_called = 1;
+-
+- if ((err = subscribe_port(dest_client, dest_port, dest, info,
+- connector->number != dest_client->number)) < 0)
++ err = subscribe_port(client, port, grp, &subs->info, ack);
++ if (err < 0) {
++ grp->exclusive = 0;
+ goto __error;
++ }
+
+ /* add to list */
+- write_lock_irqsave(&src->list_lock, flags);
+- // write_lock(&dest->list_lock); // no other lock yet
+- list_add_tail(&subs->src_list, &src->list_head);
+- list_add_tail(&subs->dest_list, &dest->list_head);
+- // write_unlock(&dest->list_lock); // no other lock yet
+- write_unlock_irqrestore(&src->list_lock, flags);
++ write_lock_irq(&grp->list_lock);
++ if (is_src)
++ list_add_tail(&subs->src_list, &grp->list_head);
++ else
++ list_add_tail(&subs->dest_list, &grp->list_head);
++ grp->exclusive = exclusive;
++ atomic_inc(&subs->ref_count);
++ write_unlock_irq(&grp->list_lock);
++ err = 0;
+
+- src->exclusive = dest->exclusive = exclusive;
++ __error:
++ up_write(&grp->list_mutex);
++ return err;
++}
++
++static void delete_and_unsubscribe_port(struct snd_seq_client *client,
++ struct snd_seq_client_port *port,
++ struct snd_seq_subscribers *subs,
++ bool is_src, bool ack)
++{
++ struct snd_seq_port_subs_info *grp;
++
++ grp = is_src ? &port->c_src : &port->c_dest;
++ down_write(&grp->list_mutex);
++ write_lock_irq(&grp->list_lock);
++ if (is_src)
++ list_del(&subs->src_list);
++ else
++ list_del(&subs->dest_list);
++ grp->exclusive = 0;
++ write_unlock_irq(&grp->list_lock);
++ up_write(&grp->list_mutex);
++
++ unsubscribe_port(client, port, grp, &subs->info, ack);
++}
++
++/* connect two ports */
++int snd_seq_port_connect(struct snd_seq_client *connector,
++ struct snd_seq_client *src_client,
++ struct snd_seq_client_port *src_port,
++ struct snd_seq_client *dest_client,
++ struct snd_seq_client_port *dest_port,
++ struct snd_seq_port_subscribe *info)
++{
++ struct snd_seq_subscribers *subs;
++ bool exclusive;
++ int err;
++
++ subs = kzalloc(sizeof(*subs), GFP_KERNEL);
++ if (!subs)
++ return -ENOMEM;
++
++ subs->info = *info;
++ atomic_set(&subs->ref_count, 0);
++ INIT_LIST_HEAD(&subs->src_list);
++ INIT_LIST_HEAD(&subs->dest_list);
++
++ exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
++
++ err = check_and_subscribe_port(src_client, src_port, subs, true,
++ exclusive,
++ connector->number != src_client->number);
++ if (err < 0)
++ goto error;
++ err = check_and_subscribe_port(dest_client, dest_port, subs, false,
++ exclusive,
++ connector->number != dest_client->number);
++ if (err < 0)
++ goto error_dest;
+
+- up_write(&dest->list_mutex);
+- up_write(&src->list_mutex);
+ return 0;
+
+- __error:
+- if (src_called)
+- unsubscribe_port(src_client, src_port, src, info,
+- connector->number != src_client->number);
++ error_dest:
++ delete_and_unsubscribe_port(src_client, src_port, subs, true,
++ connector->number != src_client->number);
++ error:
+ kfree(subs);
+- up_write(&dest->list_mutex);
+- up_write(&src->list_mutex);
+ return err;
+ }
+
+-
+ /* remove the connection */
+ int snd_seq_port_disconnect(struct snd_seq_client *connector,
+ struct snd_seq_client *src_client,
+@@ -572,37 +608,28 @@ int snd_seq_port_disconnect(struct snd_s
+ struct snd_seq_port_subscribe *info)
+ {
+ struct snd_seq_port_subs_info *src = &src_port->c_src;
+- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
+ struct snd_seq_subscribers *subs;
+ int err = -ENOENT;
+- unsigned long flags;
+
+ down_write(&src->list_mutex);
+- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
+-
+ /* look for the connection */
+ list_for_each_entry(subs, &src->list_head, src_list) {
+ if (match_subs_info(info, &subs->info)) {
+- write_lock_irqsave(&src->list_lock, flags);
+- // write_lock(&dest->list_lock); // no lock yet
+- list_del(&subs->src_list);
+- list_del(&subs->dest_list);
+- // write_unlock(&dest->list_lock);
+- write_unlock_irqrestore(&src->list_lock, flags);
+- src->exclusive = dest->exclusive = 0;
+- unsubscribe_port(src_client, src_port, src, info,
+- connector->number != src_client->number);
+- unsubscribe_port(dest_client, dest_port, dest, info,
+- connector->number != dest_client->number);
+- kfree(subs);
++ atomic_dec(&subs->ref_count); /* mark as not ready */
+ err = 0;
+ break;
+ }
+ }
+-
+- up_write(&dest->list_mutex);
+ up_write(&src->list_mutex);
+- return err;
++ if (err < 0)
++ return err;
++
++ delete_and_unsubscribe_port(src_client, src_port, subs, true,
++ connector->number != src_client->number);
++ delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
++ connector->number != dest_client->number);
++ kfree(subs);
++ return 0;
+ }
+
+
diff --git a/releases/3.2.78/alsa-seq-fix-race-at-closing-in-virmidi-driver.patch b/releases/3.2.78/alsa-seq-fix-race-at-closing-in-virmidi-driver.patch
new file mode 100644
index 00000000..72d39581
--- /dev/null
+++ b/releases/3.2.78/alsa-seq-fix-race-at-closing-in-virmidi-driver.patch
@@ -0,0 +1,39 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 1 Feb 2016 12:06:42 +0100
+Subject: ALSA: seq: Fix race at closing in virmidi driver
+
+commit 2d1b5c08366acd46c35a2e9aba5d650cb5bf5c19 upstream.
+
+The virmidi driver has an open race at closing its assigned rawmidi
+device, and this may lead to use-after-free in
+snd_seq_deliver_single_event().
+
+Plug the hole by properly protecting the linked list deletion and
+calling in the right order in snd_virmidi_input_close().
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Zd66+w12fNN85-425cVQT=K23kWbhnCEcMB8s3us-Frw@mail.gmail.com
+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: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/seq/seq_virmidi.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/sound/core/seq/seq_virmidi.c
++++ b/sound/core/seq/seq_virmidi.c
+@@ -254,9 +254,13 @@ static int snd_virmidi_output_open(struc
+ */
+ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
+ {
++ struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
+ struct snd_virmidi *vmidi = substream->runtime->private_data;
+- snd_midi_event_free(vmidi->parser);
++
++ write_lock_irq(&rdev->filelist_lock);
+ list_del(&vmidi->list);
++ write_unlock_irq(&rdev->filelist_lock);
++ snd_midi_event_free(vmidi->parser);
+ substream->runtime->private_data = NULL;
+ kfree(vmidi);
+ return 0;
diff --git a/releases/3.2.78/alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch b/releases/3.2.78/alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch
new file mode 100644
index 00000000..f2eb99df
--- /dev/null
+++ b/releases/3.2.78/alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch
@@ -0,0 +1,224 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 30 Jan 2016 23:30:25 +0100
+Subject: ALSA: seq: Fix yet another races among ALSA timer accesses
+
+commit 2cdc7b636d55cbcf42e1e6c8accd85e62d3e9ae8 upstream.
+
+ALSA sequencer may open/close and control ALSA timer instance
+dynamically either via sequencer events or direct ioctls. These are
+done mostly asynchronously, and it may call still some timer action
+like snd_timer_start() while another is calling snd_timer_close().
+Since the instance gets removed by snd_timer_close(), it may lead to
+a use-after-free.
+
+This patch tries to address such a race by protecting each
+snd_timer_*() call via the existing spinlock and also by avoiding the
+access to timer during close call.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Z6RzW5MBr-HUdV-8zwg71WQfKTdPpYGvOeS7v4cyurNQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/seq/seq_timer.c | 87 +++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 67 insertions(+), 20 deletions(-)
+
+--- a/sound/core/seq/seq_timer.c
++++ b/sound/core/seq/seq_timer.c
+@@ -92,6 +92,9 @@ void snd_seq_timer_delete(struct snd_seq
+
+ void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&tmr->lock, flags);
+ /* setup defaults */
+ tmr->ppq = 96; /* 96 PPQ */
+ tmr->tempo = 500000; /* 120 BPM */
+@@ -107,21 +110,25 @@ void snd_seq_timer_defaults(struct snd_s
+ tmr->preferred_resolution = seq_default_timer_resolution;
+
+ tmr->skew = tmr->skew_base = SKEW_BASE;
++ spin_unlock_irqrestore(&tmr->lock, flags);
+ }
+
+-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
++static void seq_timer_reset(struct snd_seq_timer *tmr)
+ {
+- unsigned long flags;
+-
+- spin_lock_irqsave(&tmr->lock, flags);
+-
+ /* reset time & songposition */
+ tmr->cur_time.tv_sec = 0;
+ tmr->cur_time.tv_nsec = 0;
+
+ tmr->tick.cur_tick = 0;
+ tmr->tick.fraction = 0;
++}
++
++void snd_seq_timer_reset(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
+
++ spin_lock_irqsave(&tmr->lock, flags);
++ seq_timer_reset(tmr);
+ spin_unlock_irqrestore(&tmr->lock, flags);
+ }
+
+@@ -140,8 +147,11 @@ static void snd_seq_timer_interrupt(stru
+ tmr = q->timer;
+ if (tmr == NULL)
+ return;
+- if (!tmr->running)
++ spin_lock_irqsave(&tmr->lock, flags);
++ if (!tmr->running) {
++ spin_unlock_irqrestore(&tmr->lock, flags);
+ return;
++ }
+
+ resolution *= ticks;
+ if (tmr->skew != tmr->skew_base) {
+@@ -150,8 +160,6 @@ static void snd_seq_timer_interrupt(stru
+ (((resolution & 0xffff) * tmr->skew) >> 16);
+ }
+
+- spin_lock_irqsave(&tmr->lock, flags);
+-
+ /* update timer */
+ snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
+
+@@ -298,26 +306,30 @@ int snd_seq_timer_open(struct snd_seq_qu
+ t->callback = snd_seq_timer_interrupt;
+ t->callback_data = q;
+ t->flags |= SNDRV_TIMER_IFLG_AUTO;
++ spin_lock_irq(&tmr->lock);
+ tmr->timeri = t;
++ spin_unlock_irq(&tmr->lock);
+ return 0;
+ }
+
+ int snd_seq_timer_close(struct snd_seq_queue *q)
+ {
+ struct snd_seq_timer *tmr;
++ struct snd_timer_instance *t;
+
+ tmr = q->timer;
+ if (snd_BUG_ON(!tmr))
+ return -EINVAL;
+- if (tmr->timeri) {
+- snd_timer_stop(tmr->timeri);
+- snd_timer_close(tmr->timeri);
+- tmr->timeri = NULL;
+- }
++ spin_lock_irq(&tmr->lock);
++ t = tmr->timeri;
++ tmr->timeri = NULL;
++ spin_unlock_irq(&tmr->lock);
++ if (t)
++ snd_timer_close(t);
+ return 0;
+ }
+
+-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
++static int seq_timer_stop(struct snd_seq_timer *tmr)
+ {
+ if (! tmr->timeri)
+ return -EINVAL;
+@@ -328,6 +340,17 @@ int snd_seq_timer_stop(struct snd_seq_ti
+ return 0;
+ }
+
++int snd_seq_timer_stop(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&tmr->lock, flags);
++ err = seq_timer_stop(tmr);
++ spin_unlock_irqrestore(&tmr->lock, flags);
++ return err;
++}
++
+ static int initialize_timer(struct snd_seq_timer *tmr)
+ {
+ struct snd_timer *t;
+@@ -360,13 +383,13 @@ static int initialize_timer(struct snd_s
+ return 0;
+ }
+
+-int snd_seq_timer_start(struct snd_seq_timer * tmr)
++static int seq_timer_start(struct snd_seq_timer *tmr)
+ {
+ if (! tmr->timeri)
+ return -EINVAL;
+ if (tmr->running)
+- snd_seq_timer_stop(tmr);
+- snd_seq_timer_reset(tmr);
++ seq_timer_stop(tmr);
++ seq_timer_reset(tmr);
+ if (initialize_timer(tmr) < 0)
+ return -EINVAL;
+ snd_timer_start(tmr->timeri, tmr->ticks);
+@@ -375,14 +398,25 @@ int snd_seq_timer_start(struct snd_seq_t
+ return 0;
+ }
+
+-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
++int snd_seq_timer_start(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&tmr->lock, flags);
++ err = seq_timer_start(tmr);
++ spin_unlock_irqrestore(&tmr->lock, flags);
++ return err;
++}
++
++static int seq_timer_continue(struct snd_seq_timer *tmr)
+ {
+ if (! tmr->timeri)
+ return -EINVAL;
+ if (tmr->running)
+ return -EBUSY;
+ if (! tmr->initialized) {
+- snd_seq_timer_reset(tmr);
++ seq_timer_reset(tmr);
+ if (initialize_timer(tmr) < 0)
+ return -EINVAL;
+ }
+@@ -392,11 +426,24 @@ int snd_seq_timer_continue(struct snd_se
+ return 0;
+ }
+
++int snd_seq_timer_continue(struct snd_seq_timer *tmr)
++{
++ unsigned long flags;
++ int err;
++
++ spin_lock_irqsave(&tmr->lock, flags);
++ err = seq_timer_continue(tmr);
++ spin_unlock_irqrestore(&tmr->lock, flags);
++ return err;
++}
++
+ /* return current 'real' time. use timeofday() to get better granularity. */
+ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
+ {
+ snd_seq_real_time_t cur_time;
++ unsigned long flags;
+
++ spin_lock_irqsave(&tmr->lock, flags);
+ cur_time = tmr->cur_time;
+ if (tmr->running) {
+ struct timeval tm;
+@@ -412,7 +459,7 @@ snd_seq_real_time_t snd_seq_timer_get_cu
+ }
+ snd_seq_sanity_real_time(&cur_time);
+ }
+-
++ spin_unlock_irqrestore(&tmr->lock, flags);
+ return cur_time;
+ }
+
diff --git a/releases/3.2.78/alsa-timer-fix-leftover-link-at-closing.patch b/releases/3.2.78/alsa-timer-fix-leftover-link-at-closing.patch
new file mode 100644
index 00000000..bb0459d3
--- /dev/null
+++ b/releases/3.2.78/alsa-timer-fix-leftover-link-at-closing.patch
@@ -0,0 +1,42 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 4 Feb 2016 17:06:13 +0100
+Subject: ALSA: timer: Fix leftover link at closing
+
+commit 094fd3be87b0f102589e2d5c3fa5d06b7e20496d upstream.
+
+In ALSA timer core, the active timer instance is managed in
+active_list linked list. Each element is added / removed dynamically
+at timer start, stop and in timer interrupt. The problem is that
+snd_timer_interrupt() has a thinko and leaves the element in
+active_list when it's the last opened element. This eventually leads
+to list corruption or use-after-free error.
+
+This hasn't been revealed because we used to delete the list forcibly
+in snd_timer_stop() in the past. However, the recent fix avoids the
+double-stop behavior (in commit [f784beb75ce8: ALSA: timer: Fix link
+corruption due to double start or stop]), and this leak hits reality.
+
+This patch fixes the link management in snd_timer_interrupt(). Now it
+simply unlinks no matter which stream is.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Yy2aukHP-EDp8-ziNqNNmb-NTf=jDWXMP7jB8HDa2vng@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/timer.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -727,8 +727,8 @@ void snd_timer_interrupt(struct snd_time
+ ti->cticks = ti->ticks;
+ } else {
+ ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+- if (--timer->running)
+- list_del_init(&ti->active_list);
++ --timer->running;
++ list_del_init(&ti->active_list);
+ }
+ if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
+ (ti->flags & SNDRV_TIMER_IFLG_FAST))
diff --git a/releases/3.2.78/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch b/releases/3.2.78/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
new file mode 100644
index 00000000..d18e7718
--- /dev/null
+++ b/releases/3.2.78/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
@@ -0,0 +1,108 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Sat, 30 Jan 2016 23:09:08 +0100
+Subject: ALSA: timer: Fix link corruption due to double start or stop
+
+commit f784beb75ce82f4136f8a0960d3ee872f7109e09 upstream.
+
+Although ALSA timer code got hardening for races, it still causes
+use-after-free error. This is however rather a corrupted linked list,
+not actually the concurrent accesses. Namely, when timer start is
+triggered twice, list_add_tail() is called twice, too. This ends
+up with the link corruption and triggers KASAN error.
+
+The simplest fix would be replacing list_add_tail() with
+list_move_tail(), but fundamentally it's the problem that we don't
+check the double start/stop correctly. So, the right fix here is to
+add the proper checks to snd_timer_start() and snd_timer_stop() (and
+their variants).
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+ZyPRoMQjmawbvmCEDrkBD2BQuH7R09=eOkf5ESK8kJAw@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[bwh: Backported to 3.2: adjust context, indentation]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/timer.c | 30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -443,6 +443,10 @@ static int snd_timer_start_slave(struct
+ unsigned long flags;
+
+ spin_lock_irqsave(&slave_active_lock, flags);
++ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
++ spin_unlock_irqrestore(&slave_active_lock, flags);
++ return -EBUSY;
++ }
+ timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
+ if (timeri->master && timeri->timer) {
+ spin_lock(&timeri->timer->lock);
+@@ -467,18 +471,26 @@ int snd_timer_start(struct snd_timer_ins
+ return -EINVAL;
+ if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
+ result = snd_timer_start_slave(timeri);
+- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
++ if (result >= 0)
++ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+ return result;
+ }
+ timer = timeri->timer;
+ if (timer == NULL)
+ return -EINVAL;
+ spin_lock_irqsave(&timer->lock, flags);
++ if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
++ SNDRV_TIMER_IFLG_START)) {
++ result = -EBUSY;
++ goto unlock;
++ }
+ timeri->ticks = timeri->cticks = ticks;
+ timeri->pticks = 0;
+ result = snd_timer_start1(timer, timeri, ticks);
++ unlock:
+ spin_unlock_irqrestore(&timer->lock, flags);
+- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
++ if (result >= 0)
++ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+ return result;
+ }
+
+@@ -494,6 +506,10 @@ static int _snd_timer_stop(struct snd_ti
+ if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
+ if (!keep_flag) {
+ spin_lock_irqsave(&slave_active_lock, flags);
++ if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
++ spin_unlock_irqrestore(&slave_active_lock, flags);
++ return -EBUSY;
++ }
+ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
+@@ -505,6 +521,11 @@ static int _snd_timer_stop(struct snd_ti
+ if (!timer)
+ return -EINVAL;
+ spin_lock_irqsave(&timer->lock, flags);
++ if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
++ SNDRV_TIMER_IFLG_START))) {
++ spin_unlock_irqrestore(&timer->lock, flags);
++ return -EBUSY;
++ }
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
+ if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
+@@ -570,10 +591,15 @@ int snd_timer_continue(struct snd_timer_
+ if (! timer)
+ return -EINVAL;
+ spin_lock_irqsave(&timer->lock, flags);
++ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
++ result = -EBUSY;
++ goto unlock;
++ }
+ if (!timeri->cticks)
+ timeri->cticks = 1;
+ timeri->pticks = 0;
+ result = snd_timer_start1(timer, timeri, timer->sticks);
++ unlock:
+ spin_unlock_irqrestore(&timer->lock, flags);
+ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
+ return result;
diff --git a/releases/3.2.78/alsa-timer-fix-race-at-concurrent-reads.patch b/releases/3.2.78/alsa-timer-fix-race-at-concurrent-reads.patch
new file mode 100644
index 00000000..1cc77af8
--- /dev/null
+++ b/releases/3.2.78/alsa-timer-fix-race-at-concurrent-reads.patch
@@ -0,0 +1,85 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 8 Feb 2016 17:26:58 +0100
+Subject: ALSA: timer: Fix race at concurrent reads
+
+commit 4dff5c7b7093b19c19d3a100f8a3ad87cb7cd9e7 upstream.
+
+snd_timer_user_read() has a potential race among parallel reads, as
+qhead and qused are updated outside the critical section due to
+copy_to_user() calls. Move them into the critical section, and also
+sanitize the relevant code a bit.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[bwh: Backported to 3.2: there's no check for tu->connected to fix up]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -1890,6 +1890,7 @@ static ssize_t snd_timer_user_read(struc
+ {
+ struct snd_timer_user *tu;
+ long result = 0, unit;
++ int qhead;
+ int err = 0;
+
+ tu = file->private_data;
+@@ -1901,7 +1902,7 @@ static ssize_t snd_timer_user_read(struc
+
+ if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
+ err = -EAGAIN;
+- break;
++ goto _error;
+ }
+
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -1916,38 +1917,33 @@ static ssize_t snd_timer_user_read(struc
+
+ if (signal_pending(current)) {
+ err = -ERESTARTSYS;
+- break;
++ goto _error;
+ }
+ }
+
++ qhead = tu->qhead++;
++ tu->qhead %= tu->queue_size;
+ spin_unlock_irq(&tu->qlock);
+- if (err < 0)
+- goto _error;
+
+ if (tu->tread) {
+- if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
+- sizeof(struct snd_timer_tread))) {
++ if (copy_to_user(buffer, &tu->tqueue[qhead],
++ sizeof(struct snd_timer_tread)))
+ err = -EFAULT;
+- goto _error;
+- }
+ } else {
+- if (copy_to_user(buffer, &tu->queue[tu->qhead++],
+- sizeof(struct snd_timer_read))) {
++ if (copy_to_user(buffer, &tu->queue[qhead],
++ sizeof(struct snd_timer_read)))
+ err = -EFAULT;
+- goto _error;
+- }
+ }
+
+- tu->qhead %= tu->queue_size;
+-
+- result += unit;
+- buffer += unit;
+-
+ spin_lock_irq(&tu->qlock);
+ tu->qused--;
++ if (err < 0)
++ goto _error;
++ result += unit;
++ buffer += unit;
+ }
+- spin_unlock_irq(&tu->qlock);
+ _error:
++ spin_unlock_irq(&tu->qlock);
+ return result > 0 ? result : err;
+ }
+
diff --git a/releases/3.2.78/alsa-timer-fix-race-between-stop-and-interrupt.patch b/releases/3.2.78/alsa-timer-fix-race-between-stop-and-interrupt.patch
new file mode 100644
index 00000000..df002da6
--- /dev/null
+++ b/releases/3.2.78/alsa-timer-fix-race-between-stop-and-interrupt.patch
@@ -0,0 +1,40 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 9 Feb 2016 12:02:32 +0100
+Subject: ALSA: timer: Fix race between stop and interrupt
+
+commit ed8b1d6d2c741ab26d60d499d7fbb7ac801f0f51 upstream.
+
+A slave timer element also unlinks at snd_timer_stop() but it takes
+only slave_active_lock. When a slave is assigned to a master,
+however, this may become a race against the master's interrupt
+handling, eventually resulting in a list corruption. The actual bug
+could be seen with a syzkaller fuzzer test case in BugLink below.
+
+As a fix, we need to take timeri->timer->lock when timer isn't NULL,
+i.e. assigned to a master, while the assignment to a master itself is
+protected by slave_active_lock.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Y_Bm+7epAb=8Wi=AaWd+DYS7qawX52qxdCfOfY49vozQ@mail.gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+[bwh: Backported to 3.2: adjust context, indentation]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/timer.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -510,9 +510,13 @@ static int _snd_timer_stop(struct snd_ti
+ spin_unlock_irqrestore(&slave_active_lock, flags);
+ return -EBUSY;
+ }
++ if (timeri->timer)
++ spin_lock(&timeri->timer->lock);
+ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
++ if (timeri->timer)
++ spin_unlock(&timeri->timer->lock);
+ spin_unlock_irqrestore(&slave_active_lock, flags);
+ }
+ goto __end;
diff --git a/releases/3.2.78/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch b/releases/3.2.78/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
new file mode 100644
index 00000000..adf3d48c
--- /dev/null
+++ b/releases/3.2.78/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
@@ -0,0 +1,32 @@
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 8 Feb 2016 17:36:25 +0100
+Subject: ALSA: timer: Fix wrong instance passed to slave callbacks
+
+commit 117159f0b9d392fb433a7871426fad50317f06f7 upstream.
+
+In snd_timer_notify1(), the wrong timer instance was passed for slave
+ccallback function. This leads to the access to the wrong data when
+an incompatible master is handled (e.g. the master is the sequencer
+timer and the slave is a user timer), as spotted by syzkaller fuzzer.
+
+This patch fixes that wrong assignment.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Y_Bm+7epAb=8Wi=AaWd+DYS7qawX52qxdCfOfY49vozQ@mail.gmail.com
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/core/timer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -414,7 +414,7 @@ static void snd_timer_notify1(struct snd
+ spin_lock_irqsave(&timer->lock, flags);
+ list_for_each_entry(ts, &ti->slave_active_head, active_list)
+ if (ts->ccallback)
+- ts->ccallback(ti, event + 100, &tstamp, resolution);
++ ts->ccallback(ts, event + 100, &tstamp, resolution);
+ spin_unlock_irqrestore(&timer->lock, flags);
+ }
+
diff --git a/releases/3.2.78/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch b/releases/3.2.78/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch
new file mode 100644
index 00000000..ae22e8f5
--- /dev/null
+++ b/releases/3.2.78/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch
@@ -0,0 +1,30 @@
+From: Andrey Konovalov <andreyknvl@gmail.com>
+Date: Sat, 13 Feb 2016 11:08:06 +0300
+Subject: ALSA: usb-audio: avoid freeing umidi object twice
+
+commit 07d86ca93db7e5cdf4743564d98292042ec21af7 upstream.
+
+The 'umidi' object will be free'd on the error path by snd_usbmidi_free()
+when tearing down the rawmidi interface. So we shouldn't try to free it
+in snd_usbmidi_create() after having registered the rawmidi interface.
+
+Found by KASAN.
+
+Signed-off-by: Andrey Konovalov <andreyknvl@gmail.com>
+Acked-by: Clemens Ladisch <clemens@ladisch.de>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ sound/usb/midi.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -2289,7 +2289,6 @@ int snd_usbmidi_create(struct snd_card *
+ else
+ err = snd_usbmidi_create_endpoints(umidi, endpoints);
+ if (err < 0) {
+- snd_usbmidi_free(umidi);
+ return err;
+ }
+
diff --git a/releases/3.2.78/arm-8517-1-icst-avoid-arithmetic-overflow-in-icst_hz.patch b/releases/3.2.78/arm-8517-1-icst-avoid-arithmetic-overflow-in-icst_hz.patch
new file mode 100644
index 00000000..d7e7a027
--- /dev/null
+++ b/releases/3.2.78/arm-8517-1-icst-avoid-arithmetic-overflow-in-icst_hz.patch
@@ -0,0 +1,70 @@
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Mon, 8 Feb 2016 09:14:37 +0100
+Subject: ARM: 8517/1: ICST: avoid arithmetic overflow in icst_hz()
+
+commit 5070fb14a0154f075c8b418e5bc58a620ae85a45 upstream.
+
+When trying to set the ICST 307 clock to 25174000 Hz I ran into
+this arithmetic error: the icst_hz_to_vco() correctly figure out
+DIVIDE=2, RDW=100 and VDW=99 yielding a frequency of
+25174000 Hz out of the VCO. (I replicated the icst_hz() function
+in a spreadsheet to verify this.)
+
+However, when I called icst_hz() on these VCO settings it would
+instead return 4122709 Hz. This causes an error in the common
+clock driver for ICST as the common clock framework will call
+.round_rate() on the clock which will utilize icst_hz_to_vco()
+followed by icst_hz() suggesting the erroneous frequency, and
+then the clock gets set to this.
+
+The error did not manifest in the old clock framework since
+this high frequency was only used by the CLCD, which calls
+clk_set_rate() without first calling clk_round_rate() and since
+the old clock framework would not call clk_round_rate() before
+setting the frequency, the correct values propagated into
+the VCO.
+
+After some experimenting I figured out that it was due to a simple
+arithmetic overflow: the divisor for 24Mhz reference frequency
+as reference becomes 24000000*2*(99+8)=0x132212400 and the "1"
+in bit 32 overflows and is lost.
+
+But introducing an explicit 64-by-32 bit do_div() and casting
+the divisor into (u64) we get the right frequency back, and the
+right frequency gets set.
+
+Tested on the ARM Versatile.
+
+Cc: linux-clk@vger.kernel.org
+Cc: Pawel Moll <pawel.moll@arm.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/arm/common/icst.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/common/icst.c
++++ b/arch/arm/common/icst.c
+@@ -16,7 +16,7 @@
+ */
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-
++#include <asm/div64.h>
+ #include <asm/hardware/icst.h>
+
+ /*
+@@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div);
+
+ unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco)
+ {
+- return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]);
++ u64 dividend = p->ref * 2 * (u64)(vco.v + 8);
++ u32 divisor = (vco.r + 2) * p->s2div[vco.s];
++
++ do_div(dividend, divisor);
++ return (unsigned long)dividend;
+ }
+
+ EXPORT_SYMBOL(icst_hz);
diff --git a/releases/3.2.78/arm-8519-1-icst-try-other-dividends-than-1.patch b/releases/3.2.78/arm-8519-1-icst-try-other-dividends-than-1.patch
new file mode 100644
index 00000000..9b553716
--- /dev/null
+++ b/releases/3.2.78/arm-8519-1-icst-try-other-dividends-than-1.patch
@@ -0,0 +1,34 @@
+From: Linus Walleij <linus.walleij@linaro.org>
+Date: Wed, 10 Feb 2016 09:25:17 +0100
+Subject: ARM: 8519/1: ICST: try other dividends than 1
+
+commit e972c37459c813190461dabfeaac228e00aae259 upstream.
+
+Since the dawn of time the ICST code has only supported divide
+by one or hang in an eternal loop. Luckily we were always dividing
+by one because the reference frequency for the systems using
+the ICSTs is 24MHz and the [min,max] values for the PLL input
+if [10,320] MHz for ICST307 and [6,200] for ICST525, so the loop
+will always terminate immediately without assigning any divisor
+for the reference frequency.
+
+But for the code to make sense, let's insert the missing i++
+
+Reported-by: David Binderman <dcb314@hotmail.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/arm/common/icst.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/common/icst.c
++++ b/arch/arm/common/icst.c
+@@ -62,6 +62,7 @@ icst_hz_to_vco(const struct icst_params
+
+ if (f > p->vco_min && f <= p->vco_max)
+ break;
++ i++;
+ } while (i < 8);
+
+ if (i >= 8)
diff --git a/releases/3.2.78/btrfs-properly-set-the-termination-value-of-ctx-pos-in-readdir.patch b/releases/3.2.78/btrfs-properly-set-the-termination-value-of-ctx-pos-in-readdir.patch
new file mode 100644
index 00000000..f7eaa012
--- /dev/null
+++ b/releases/3.2.78/btrfs-properly-set-the-termination-value-of-ctx-pos-in-readdir.patch
@@ -0,0 +1,155 @@
+From: David Sterba <dsterba@suse.com>
+Date: Fri, 13 Nov 2015 13:44:28 +0100
+Subject: btrfs: properly set the termination value of ctx->pos in readdir
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit bc4ef7592f657ae81b017207a1098817126ad4cb upstream.
+
+The value of ctx->pos in the last readdir call is supposed to be set to
+INT_MAX due to 32bit compatibility, unless 'pos' is intentially set to a
+larger value, then it's LLONG_MAX.
+
+There's a report from PaX SIZE_OVERFLOW plugin that "ctx->pos++"
+overflows (https://forums.grsecurity.net/viewtopic.php?f=1&t=4284), on a
+64bit arch, where the value is 0x7fffffffffffffff ie. LLONG_MAX before
+the increment.
+
+We can get to that situation like that:
+
+* emit all regular readdir entries
+* still in the same call to readdir, bump the last pos to INT_MAX
+* next call to readdir will not emit any entries, but will reach the
+ bump code again, finds pos to be INT_MAX and sets it to LLONG_MAX
+
+Normally this is not a problem, but if we call readdir again, we'll find
+'pos' set to LLONG_MAX and the unconditional increment will overflow.
+
+The report from Victor at
+(http://thread.gmane.org/gmane.comp.file-systems.btrfs/49500) with debugging
+print shows that pattern:
+
+ Overflow: e
+ Overflow: 7fffffff
+ Overflow: 7fffffffffffffff
+ PAX: size overflow detected in function btrfs_real_readdir
+ fs/btrfs/inode.c:5760 cicus.935_282 max, count: 9, decl: pos; num: 0;
+ context: dir_context;
+ CPU: 0 PID: 2630 Comm: polkitd Not tainted 4.2.3-grsec #1
+ Hardware name: Gigabyte Technology Co., Ltd. H81ND2H/H81ND2H, BIOS F3 08/11/2015
+ ffffffff81901608 0000000000000000 ffffffff819015e6 ffffc90004973d48
+ ffffffff81742f0f 0000000000000007 ffffffff81901608 ffffc90004973d78
+ ffffffff811cb706 0000000000000000 ffff8800d47359e0 ffffc90004973ed8
+ Call Trace:
+ [<ffffffff81742f0f>] dump_stack+0x4c/0x7f
+ [<ffffffff811cb706>] report_size_overflow+0x36/0x40
+ [<ffffffff812ef0bc>] btrfs_real_readdir+0x69c/0x6d0
+ [<ffffffff811dafc8>] iterate_dir+0xa8/0x150
+ [<ffffffff811e6d8d>] ? __fget_light+0x2d/0x70
+ [<ffffffff811dba3a>] SyS_getdents+0xba/0x1c0
+ Overflow: 1a
+ [<ffffffff811db070>] ? iterate_dir+0x150/0x150
+ [<ffffffff81749b69>] entry_SYSCALL_64_fastpath+0x12/0x83
+
+The jump from 7fffffff to 7fffffffffffffff happens when new dir entries
+are not yet synced and are processed from the delayed list. Then the code
+could go to the bump section again even though it might not emit any new
+dir entries from the delayed list.
+
+The fix avoids entering the "bump" section again once we've finished
+emitting the entries, both for synced and delayed entries.
+
+References: https://forums.grsecurity.net/viewtopic.php?f=1&t=4284
+Reported-by: Victor <services@swwu.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Tested-by: Holger Hoffstätte <holger.hoffstaette@googlemail.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+[bwh: Backported to 3.2:
+ - s/ctx->pos/filp->f_pos/
+ - Adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ fs/btrfs/delayed-inode.c | 3 ++-
+ fs/btrfs/delayed-inode.h | 2 +-
+ fs/btrfs/inode.c | 14 +++++++++++++-
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -1593,7 +1593,7 @@ int btrfs_should_delete_dir_index(struct
+ */
+ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
+ filldir_t filldir,
+- struct list_head *ins_list)
++ struct list_head *ins_list, bool *emitted)
+ {
+ struct btrfs_dir_item *di;
+ struct btrfs_delayed_item *curr, *next;
+@@ -1637,6 +1637,7 @@ int btrfs_readdir_delayed_dir_index(stru
+
+ if (over)
+ return 1;
++ *emitted = true;
+ }
+ return 0;
+ }
+--- a/fs/btrfs/delayed-inode.h
++++ b/fs/btrfs/delayed-inode.h
+@@ -133,7 +133,7 @@ int btrfs_should_delete_dir_index(struct
+ u64 index);
+ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
+ filldir_t filldir,
+- struct list_head *ins_list);
++ struct list_head *ins_list, bool *emitted);
+
+ /* for init */
+ int __init btrfs_delayed_inode_init(void);
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4111,6 +4111,7 @@ static int btrfs_real_readdir(struct fil
+ char *name_ptr;
+ int name_len;
+ int is_curr = 0; /* filp->f_pos points to the current index? */
++ bool emitted;
+
+ /* FIXME, use a real flag for deciding about the key type */
+ if (root->fs_info->tree_root == root)
+@@ -4153,6 +4154,7 @@ static int btrfs_real_readdir(struct fil
+ if (ret < 0)
+ goto err;
+
++ emitted = false;
+ while (1) {
+ leaf = path->nodes[0];
+ slot = path->slots[0];
+@@ -4254,6 +4256,7 @@ skip:
+
+ if (over)
+ goto nopos;
++ emitted = true;
+ di_len = btrfs_dir_name_len(leaf, di) +
+ btrfs_dir_data_len(leaf, di) + sizeof(*di);
+ di_cur += di_len;
+@@ -4267,11 +4270,20 @@ next:
+ if (is_curr)
+ filp->f_pos++;
+ ret = btrfs_readdir_delayed_dir_index(filp, dirent, filldir,
+- &ins_list);
++ &ins_list, &emitted);
+ if (ret)
+ goto nopos;
+ }
+
++ /*
++ * If we haven't emitted any dir entry, we must not touch filp->f_pos as
++ * it was was set to the termination value in previous call. We assume
++ * that "." and ".." were emitted if we reach this point and set the
++ * termination value as well for an empty directory.
++ */
++ if (filp->f_pos > 2 && !emitted)
++ goto nopos;
++
+ /* Reached end of directory/root. Bump pos past the last item. */
+ if (key_type == BTRFS_DIR_INDEX_KEY)
+ /*
diff --git a/releases/3.2.78/cdc-acm-exclude-samsung-phone-04e8-685d.patch b/releases/3.2.78/cdc-acm-exclude-samsung-phone-04e8-685d.patch
new file mode 100644
index 00000000..db3d4493
--- /dev/null
+++ b/releases/3.2.78/cdc-acm-exclude-samsung-phone-04e8-685d.patch
@@ -0,0 +1,30 @@
+From: Oliver Neukum <oneukum@suse.com>
+Date: Mon, 18 Jan 2016 15:45:18 +0100
+Subject: cdc-acm:exclude Samsung phone 04e8:685d
+
+commit e912e685f372ab62a2405a1acd923597f524e94a upstream.
+
+This phone needs to be handled by a specialised firmware tool
+and is reported to crash irrevocably if cdc-acm takes it.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/class/cdc-acm.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1668,6 +1668,11 @@ static const struct usb_device_id acm_id
+ .driver_info = NO_DATA_INTERFACE,
+ },
+
++ /*Samsung phone in firmware update mode */
++ { USB_DEVICE(0x04e8, 0x685d),
++ .driver_info = IGNORE_DEVICE,
++ },
++
+ /* Exclude Infineon Flash Loader utility */
+ { USB_DEVICE(0x058b, 0x0041),
+ .driver_info = IGNORE_DEVICE,
diff --git a/releases/3.2.78/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch b/releases/3.2.78/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch
new file mode 100644
index 00000000..3d925168
--- /dev/null
+++ b/releases/3.2.78/crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch
@@ -0,0 +1,36 @@
+From: "Wang, Rui Y" <rui.y.wang@intel.com>
+Date: Wed, 27 Jan 2016 17:08:37 +0800
+Subject: crypto: algif_hash - wait for crypto_ahash_init() to complete
+
+commit fe09786178f9df713a4b2dd6b93c0a722346bf5e upstream.
+
+hash_sendmsg/sendpage() need to wait for the completion
+of crypto_ahash_init() otherwise it can cause panic.
+
+Signed-off-by: Rui Wang <rui.y.wang@intel.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ crypto/algif_hash.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/crypto/algif_hash.c
++++ b/crypto/algif_hash.c
+@@ -56,7 +56,8 @@ static int hash_sendmsg(struct kiocb *un
+
+ lock_sock(sk);
+ if (!ctx->more) {
+- err = crypto_ahash_init(&ctx->req);
++ err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
++ &ctx->completion);
+ if (err)
+ goto unlock;
+ }
+@@ -136,6 +137,7 @@ static ssize_t hash_sendpage(struct sock
+ } else {
+ if (!ctx->more) {
+ err = crypto_ahash_init(&ctx->req);
++ err = af_alg_wait_for_completion(err, &ctx->completion);
+ if (err)
+ goto unlock;
+ }
diff --git a/releases/3.2.78/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch b/releases/3.2.78/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch
new file mode 100644
index 00000000..04b7be5d
--- /dev/null
+++ b/releases/3.2.78/crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch
@@ -0,0 +1,38 @@
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 3 Feb 2016 21:39:26 +0800
+Subject: crypto: algif_skcipher - Do not dereference ctx without socket lock
+
+commit 6454c2b83f719057069777132b13949e4c6b6350 upstream.
+
+Any access to non-constant bits of the private context must be
+done under the socket lock, in particular, this includes ctx->req.
+
+This patch moves such accesses under the lock, and fetches the
+tfm from the parent socket which is guaranteed to be constant,
+rather than from ctx->req.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+[bwh: Backported to 3.2:
+ - Drop changes to skcipher_recvmsg_async
+ - s/skcipher/ablkcipher/ in many places
+ - s/skc->skcipher/skc->base/]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ crypto/algif_skcipher.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -249,8 +249,11 @@ static int skcipher_sendmsg(struct kiocb
+ {
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
++ struct sock *psk = ask->parent;
++ struct alg_sock *pask = alg_sk(psk);
+ struct skcipher_ctx *ctx = ask->private;
+- struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
++ struct ablkcipher_tfm *skc = pask->private;
++ struct crypto_ablkcipher *tfm = skc->base;
+ unsigned ivsize = crypto_ablkcipher_ivsize(tfm);
+ struct skcipher_sg_list *sgl;
+ struct af_alg_control con = {};
diff --git a/releases/3.2.78/crypto-shash-fix-has_key-setting.patch b/releases/3.2.78/crypto-shash-fix-has_key-setting.patch
new file mode 100644
index 00000000..17a61a77
--- /dev/null
+++ b/releases/3.2.78/crypto-shash-fix-has_key-setting.patch
@@ -0,0 +1,36 @@
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 27 Jan 2016 00:16:37 +0800
+Subject: crypto: shash - Fix has_key setting
+
+commit 00420a65fa2beb3206090ead86942484df2275f3 upstream.
+
+The has_key logic is wrong for shash algorithms as they always
+have a setkey function. So we should instead be testing against
+shash_no_setkey.
+
+Fixes: a5596d633278 ("crypto: hash - Add crypto_ahash_has_setkey")
+Reported-by: Stephan Mueller <smueller@chronox.de>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Tested-by: Stephan Mueller <smueller@chronox.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ crypto/shash.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+--- a/crypto/shash.c
++++ b/crypto/shash.c
+@@ -353,11 +353,10 @@ int crypto_init_shash_ops_async(struct c
+ crt->final = shash_async_final;
+ crt->finup = shash_async_finup;
+ crt->digest = shash_async_digest;
++ crt->setkey = shash_async_setkey;
++
++ crt->has_setkey = alg->setkey != shash_no_setkey;
+
+- if (alg->setkey) {
+- crt->setkey = shash_async_setkey;
+- crt->has_setkey = true;
+- }
+ if (alg->export)
+ crt->export = shash_async_export;
+ if (alg->import)
diff --git a/releases/3.2.78/crypto-user-lock-crypto_alg_list-on-alg-dump.patch b/releases/3.2.78/crypto-user-lock-crypto_alg_list-on-alg-dump.patch
new file mode 100644
index 00000000..7e529b5c
--- /dev/null
+++ b/releases/3.2.78/crypto-user-lock-crypto_alg_list-on-alg-dump.patch
@@ -0,0 +1,89 @@
+From: Mathias Krause <minipli@googlemail.com>
+Date: Mon, 1 Feb 2016 14:27:30 +0100
+Subject: crypto: user - lock crypto_alg_list on alg dump
+
+commit 63e41ebc6630f39422d87f8a4bade1e793f37a01 upstream.
+
+We miss to take the crypto_alg_sem semaphore when traversing the
+crypto_alg_list for CRYPTO_MSG_GETALG dumps. This allows a race with
+crypto_unregister_alg() removing algorithms from the list while we're
+still traversing it, thereby leading to a use-after-free as show below:
+
+[ 3482.071639] general protection fault: 0000 [#1] SMP
+[ 3482.075639] Modules linked in: aes_x86_64 glue_helper lrw ablk_helper cryptd gf128mul ipv6 pcspkr serio_raw virtio_net microcode virtio_pci virtio_ring virtio sr_mod cdrom [last unloaded: aesni_intel]
+[ 3482.075639] CPU: 1 PID: 11065 Comm: crconf Not tainted 4.3.4-grsec+ #126
+[ 3482.075639] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
+[ 3482.075639] task: ffff88001cd41a40 ti: ffff88001cd422c8 task.ti: ffff88001cd422c8
+[ 3482.075639] RIP: 0010:[<ffffffff93722bd3>] [<ffffffff93722bd3>] strncpy+0x13/0x30
+[ 3482.075639] RSP: 0018:ffff88001f713b60 EFLAGS: 00010202
+[ 3482.075639] RAX: ffff88001f6c4430 RBX: ffff88001f6c43a0 RCX: ffff88001f6c4430
+[ 3482.075639] RDX: 0000000000000040 RSI: fefefefefefeff16 RDI: ffff88001f6c4430
+[ 3482.075639] RBP: ffff88001f713b60 R08: ffff88001f6c4470 R09: ffff88001f6c4480
+[ 3482.075639] R10: 0000000000000002 R11: 0000000000000246 R12: ffff88001ce2aa28
+[ 3482.075639] R13: ffff880000093700 R14: ffff88001f5e4bf8 R15: 0000000000003b20
+[ 3482.075639] FS: 0000033826fa2700(0000) GS:ffff88001e900000(0000) knlGS:0000000000000000
+[ 3482.075639] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 3482.075639] CR2: ffffffffff600400 CR3: 00000000139ec000 CR4: 00000000001606f0
+[ 3482.075639] Stack:
+[ 3482.075639] ffff88001f713bd8 ffffffff936ccd00 ffff88001e5c4200 ffff880000093700
+[ 3482.075639] ffff88001f713bd0 ffffffff938ef4bf 0000000000000000 0000000000003b20
+[ 3482.075639] ffff88001f5e4bf8 ffff88001f5e4848 0000000000000000 0000000000003b20
+[ 3482.075639] Call Trace:
+[ 3482.075639] [<ffffffff936ccd00>] crypto_report_alg+0xc0/0x3e0
+[ 3482.075639] [<ffffffff938ef4bf>] ? __alloc_skb+0x16f/0x300
+[ 3482.075639] [<ffffffff936cd08a>] crypto_dump_report+0x6a/0x90
+[ 3482.075639] [<ffffffff93935707>] netlink_dump+0x147/0x2e0
+[ 3482.075639] [<ffffffff93935f99>] __netlink_dump_start+0x159/0x190
+[ 3482.075639] [<ffffffff936ccb13>] crypto_user_rcv_msg+0xc3/0x130
+[ 3482.075639] [<ffffffff936cd020>] ? crypto_report_alg+0x3e0/0x3e0
+[ 3482.075639] [<ffffffff936cc4b0>] ? alg_test_crc32c+0x120/0x120
+[ 3482.075639] [<ffffffff93933145>] ? __netlink_lookup+0xd5/0x120
+[ 3482.075639] [<ffffffff936cca50>] ? crypto_add_alg+0x1d0/0x1d0
+[ 3482.075639] [<ffffffff93938141>] netlink_rcv_skb+0xe1/0x130
+[ 3482.075639] [<ffffffff936cc4f8>] crypto_netlink_rcv+0x28/0x40
+[ 3482.075639] [<ffffffff939375a8>] netlink_unicast+0x108/0x180
+[ 3482.075639] [<ffffffff93937c21>] netlink_sendmsg+0x541/0x770
+[ 3482.075639] [<ffffffff938e31e1>] sock_sendmsg+0x21/0x40
+[ 3482.075639] [<ffffffff938e4763>] SyS_sendto+0xf3/0x130
+[ 3482.075639] [<ffffffff93444203>] ? bad_area_nosemaphore+0x13/0x20
+[ 3482.075639] [<ffffffff93444470>] ? __do_page_fault+0x80/0x3a0
+[ 3482.075639] [<ffffffff939d80cb>] entry_SYSCALL_64_fastpath+0x12/0x6e
+[ 3482.075639] Code: 88 4a ff 75 ed 5d 48 0f ba 2c 24 3f c3 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 85 d2 48 89 f8 48 89 f9 4c 8d 04 17 48 89 e5 74 15 <0f> b6 16 80 fa 01 88 11 48 83 de ff 48 83 c1 01 4c 39 c1 75 eb
+[ 3482.075639] RIP [<ffffffff93722bd3>] strncpy+0x13/0x30
+
+To trigger the race run the following loops simultaneously for a while:
+ $ while : ; do modprobe aesni-intel; rmmod aesni-intel; done
+ $ while : ; do crconf show all > /dev/null; done
+
+Fix the race by taking the crypto_alg_sem read lock, thereby preventing
+crypto_unregister_alg() from modifying the algorithm list during the
+dump.
+
+This bug has been detected by the PaX memory sanitize feature.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: PaX Team <pageexec@freemail.hu>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ crypto/crypto_user.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/crypto/crypto_user.c
++++ b/crypto/crypto_user.c
+@@ -390,8 +390,12 @@ static int crypto_user_rcv_msg(struct sk
+ if (link->dump == NULL)
+ return -EINVAL;
+
+- return netlink_dump_start(crypto_nlsk, skb, nlh,
++ down_read(&crypto_alg_sem);
++ err = netlink_dump_start(crypto_nlsk, skb, nlh,
+ link->dump, link->done, 0);
++ up_read(&crypto_alg_sem);
++
++ return err;
+ }
+
+ err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
diff --git a/releases/3.2.78/drm-vmwgfx-respect-nomodeset.patch b/releases/3.2.78/drm-vmwgfx-respect-nomodeset.patch
new file mode 100644
index 00000000..ce6b21f7
--- /dev/null
+++ b/releases/3.2.78/drm-vmwgfx-respect-nomodeset.patch
@@ -0,0 +1,37 @@
+From: Rob Clark <robdclark@gmail.com>
+Date: Wed, 15 Oct 2014 15:00:47 -0400
+Subject: drm/vmwgfx: respect 'nomodeset'
+
+commit 96c5d076f0a5e2023ecdb44d8261f87641ee71e0 upstream.
+
+Signed-off-by: Rob Clark <robdclark@gmail.com>
+Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>.
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -25,6 +25,7 @@
+ *
+ **************************************************************************/
+ #include <linux/module.h>
++#include <linux/console.h>
+
+ #include "drmP.h"
+ #include "vmwgfx_drv.h"
+@@ -1142,6 +1143,12 @@ static int vmw_probe(struct pci_dev *pde
+ static int __init vmwgfx_init(void)
+ {
+ int ret;
++
++#ifdef CONFIG_VGA_CONSOLE
++ if (vgacon_text_force())
++ return -EINVAL;
++#endif
++
+ ret = drm_pci_init(&driver, &vmw_pci_driver);
+ if (ret)
+ DRM_ERROR("Failed initializing DRM.\n");
diff --git a/releases/3.2.78/hrtimer-handle-remaining-time-proper-for-time_low_res.patch b/releases/3.2.78/hrtimer-handle-remaining-time-proper-for-time_low_res.patch
new file mode 100644
index 00000000..f75f49a5
--- /dev/null
+++ b/releases/3.2.78/hrtimer-handle-remaining-time-proper-for-time_low_res.patch
@@ -0,0 +1,224 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Jan 2016 16:54:46 +0000
+Subject: hrtimer: Handle remaining time proper for TIME_LOW_RES
+
+commit 203cbf77de59fc8f13502dcfd11350c6d4a5c95f upstream.
+
+If CONFIG_TIME_LOW_RES is enabled we add a jiffie to the relative timeout to
+prevent short sleeps, but we do not account for that in interfaces which
+retrieve the remaining time.
+
+Helge observed that timerfd can return a remaining time larger than the
+relative timeout. That's not expected and breaks userland test programs.
+
+Store the information that the timer was armed relative and provide functions
+to adjust the remaining time. To avoid bloating the hrtimer struct make state
+a u8, which as a bonus results in better code on x86 at least.
+
+Reported-and-tested-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: John Stultz <john.stultz@linaro.org>
+Cc: linux-m68k@lists.linux-m68k.org
+Cc: dhowells@redhat.com
+Link: http://lkml.kernel.org/r/20160114164159.273328486@linutronix.de
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+[bwh: Backported to 3.2:
+ - Use #ifdef instead of IS_ENABLED() as that doesn't work for config
+ symbols that don't exist on the current architecture
+ - Use KTIME_LOW_RES directly instead of hrtimer_resolution
+ - Use ktime_sub() instead of modifying ktime::tv64 directly
+ - Adjust filename, context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ include/linux/hrtimer.h | 34 +++++++++++++++++++++++++++---
+ kernel/hrtimer.c | 55 ++++++++++++++++++++++++++++++++----------------
+ kernel/time/timer_list.c | 2 +-
+ 3 files changed, 69 insertions(+), 22 deletions(-)
+
+--- a/include/linux/hrtimer.h
++++ b/include/linux/hrtimer.h
+@@ -96,6 +96,7 @@ enum hrtimer_restart {
+ * @function: timer expiry callback function
+ * @base: pointer to the timer base (per cpu and per clock)
+ * @state: state information (See bit values above)
++ * @is_rel: Set if the timer was armed relative
+ * @start_site: timer statistics field to store the site where the timer
+ * was started
+ * @start_comm: timer statistics field to store the name of the process which
+@@ -110,7 +111,8 @@ struct hrtimer {
+ ktime_t _softexpires;
+ enum hrtimer_restart (*function)(struct hrtimer *);
+ struct hrtimer_clock_base *base;
+- unsigned long state;
++ u8 state;
++ u8 is_rel;
+ #ifdef CONFIG_TIMER_STATS
+ int start_pid;
+ void *start_site;
+@@ -315,6 +317,29 @@ static inline void clock_was_set_delayed
+
+ #endif
+
++static inline ktime_t
++__hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t now)
++{
++ ktime_t rem = ktime_sub(timer->node.expires, now);
++
++ /*
++ * Adjust relative timers for the extra we added in
++ * hrtimer_start_range_ns() to prevent short timeouts.
++ */
++#ifdef CONFIG_TIME_LOW_RES
++ if (timer->is_rel)
++ rem = ktime_sub(rem, KTIME_LOW_RES);
++#endif
++ return rem;
++}
++
++static inline ktime_t
++hrtimer_expires_remaining_adjusted(const struct hrtimer *timer)
++{
++ return __hrtimer_expires_remaining_adjusted(timer,
++ timer->base->get_time());
++}
++
+ extern void clock_was_set(void);
+ #ifdef CONFIG_TIMERFD
+ extern void timerfd_clock_was_set(void);
+@@ -383,7 +408,12 @@ static inline int hrtimer_restart(struct
+ }
+
+ /* Query timers: */
+-extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
++extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust);
++
++static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
++{
++ return __hrtimer_get_remaining(timer, false);
++}
+ extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
+
+ extern ktime_t hrtimer_get_next_event(void);
+--- a/kernel/hrtimer.c
++++ b/kernel/hrtimer.c
+@@ -910,7 +910,7 @@ static int enqueue_hrtimer(struct hrtime
+ */
+ static void __remove_hrtimer(struct hrtimer *timer,
+ struct hrtimer_clock_base *base,
+- unsigned long newstate, int reprogram)
++ u8 newstate, int reprogram)
+ {
+ struct timerqueue_node *next_timer;
+ if (!(timer->state & HRTIMER_STATE_ENQUEUED))
+@@ -944,7 +944,7 @@ static inline int
+ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
+ {
+ if (hrtimer_is_queued(timer)) {
+- unsigned long state;
++ u8 state;
+ int reprogram;
+
+ /*
+@@ -970,6 +970,22 @@ remove_hrtimer(struct hrtimer *timer, st
+ return 0;
+ }
+
++static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
++ const enum hrtimer_mode mode)
++{
++#ifdef CONFIG_TIME_LOW_RES
++ /*
++ * CONFIG_TIME_LOW_RES indicates that the system has no way to return
++ * granular time values. For relative timers we add KTIME_LOW_RES
++ * (i.e. one jiffie) to prevent short timeouts.
++ */
++ timer->is_rel = mode & HRTIMER_MODE_REL;
++ if (timer->is_rel)
++ tim = ktime_add_safe(tim, KTIME_LOW_RES);
++#endif
++ return tim;
++}
++
+ int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
+ unsigned long delta_ns, const enum hrtimer_mode mode,
+ int wakeup)
+@@ -983,19 +999,10 @@ int __hrtimer_start_range_ns(struct hrti
+ /* Remove an active timer from the queue: */
+ ret = remove_hrtimer(timer, base);
+
+- if (mode & HRTIMER_MODE_REL) {
++ if (mode & HRTIMER_MODE_REL)
+ tim = ktime_add_safe(tim, base->get_time());
+- /*
+- * CONFIG_TIME_LOW_RES is a temporary way for architectures
+- * to signal that they simply return xtime in
+- * do_gettimeoffset(). In this case we want to round up by
+- * resolution when starting a relative timer, to avoid short
+- * timeouts. This will go away with the GTOD framework.
+- */
+-#ifdef CONFIG_TIME_LOW_RES
+- tim = ktime_add_safe(tim, base->resolution);
+-#endif
+- }
++
++ tim = hrtimer_update_lowres(timer, tim, mode);
+
+ hrtimer_set_expires_range_ns(timer, tim, delta_ns);
+
+@@ -1120,19 +1127,25 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
+ /**
+ * hrtimer_get_remaining - get remaining time for the timer
+ * @timer: the timer to read
++ * @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y
+ */
+-ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
++ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust)
+ {
+ unsigned long flags;
+ ktime_t rem;
+
+ lock_hrtimer_base(timer, &flags);
+- rem = hrtimer_expires_remaining(timer);
++#ifdef CONFIG_TIME_LOW_RES
++ if (adjust)
++ rem = hrtimer_expires_remaining_adjusted(timer);
++ else
++#endif
++ rem = hrtimer_expires_remaining(timer);
+ unlock_hrtimer_base(timer, &flags);
+
+ return rem;
+ }
+-EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
++EXPORT_SYMBOL_GPL(__hrtimer_get_remaining);
+
+ #ifdef CONFIG_NO_HZ
+ /**
+@@ -1249,6 +1262,15 @@ static void __run_hrtimer(struct hrtimer
+ fn = timer->function;
+
+ /*
++ * Clear the 'is relative' flag for the TIME_LOW_RES case. If the
++ * timer is restarted with a period then it becomes an absolute
++ * timer. If its not restarted it does not matter.
++ */
++#ifdef CONFIG_TIME_LOW_RES
++ timer->is_rel = false;
++#endif
++
++ /*
+ * Because we run timers from hardirq context, there is no chance
+ * they get migrated to another cpu, therefore its safe to unlock
+ * the timer base.
+--- a/kernel/time/timer_list.c
++++ b/kernel/time/timer_list.c
+@@ -57,7 +57,7 @@ print_timer(struct seq_file *m, struct h
+ print_name_offset(m, taddr);
+ SEQ_printf(m, ", ");
+ print_name_offset(m, timer->function);
+- SEQ_printf(m, ", S:%02lx", timer->state);
++ SEQ_printf(m, ", S:%02x", timer->state);
+ #ifdef CONFIG_TIMER_STATS
+ SEQ_printf(m, ", ");
+ print_name_offset(m, timer->start_site);
diff --git a/releases/3.2.78/intel_scu_ipcutil-underflow-in-scu_reg_access.patch b/releases/3.2.78/intel_scu_ipcutil-underflow-in-scu_reg_access.patch
new file mode 100644
index 00000000..1cab86ec
--- /dev/null
+++ b/releases/3.2.78/intel_scu_ipcutil-underflow-in-scu_reg_access.patch
@@ -0,0 +1,29 @@
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 26 Jan 2016 12:24:25 +0300
+Subject: intel_scu_ipcutil: underflow in scu_reg_access()
+
+commit b1d353ad3d5835b16724653b33c05124e1b5acf1 upstream.
+
+"count" is controlled by the user and it can be negative. Let's prevent
+that by making it unsigned. You have to have CAP_SYS_RAWIO to call this
+function so the bug is not as serious as it could be.
+
+Fixes: 5369c02d951a ('intel_scu_ipc: Utility driver for intel scu ipc')
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Darren Hart <dvhart@linux.intel.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/platform/x86/intel_scu_ipcutil.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/platform/x86/intel_scu_ipcutil.c
++++ b/drivers/platform/x86/intel_scu_ipcutil.c
+@@ -52,7 +52,7 @@ struct scu_ipc_data {
+
+ static int scu_reg_access(u32 cmd, struct scu_ipc_data *data)
+ {
+- int count = data->count;
++ unsigned int count = data->count;
+
+ if (count == 0 || count == 3 || count > 4)
+ return -EINVAL;
diff --git a/releases/3.2.78/itimers-handle-relative-timers-with-config_time_low_res-proper.patch b/releases/3.2.78/itimers-handle-relative-timers-with-config_time_low_res-proper.patch
new file mode 100644
index 00000000..d566b3ff
--- /dev/null
+++ b/releases/3.2.78/itimers-handle-relative-timers-with-config_time_low_res-proper.patch
@@ -0,0 +1,36 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Jan 2016 16:54:48 +0000
+Subject: itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper
+
+commit 51cbb5242a41700a3f250ecfb48dcfb7e4375ea4 upstream.
+
+As Helge reported for timerfd we have the same issue in itimers. We return
+remaining time larger than the programmed relative time to user space in case
+of CONFIG_TIME_LOW_RES=y. Use the proper function to adjust the extra time
+added in hrtimer_start_range_ns().
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Helge Deller <deller@gmx.de>
+Cc: John Stultz <john.stultz@linaro.org>
+Cc: linux-m68k@lists.linux-m68k.org
+Cc: dhowells@redhat.com
+Link: http://lkml.kernel.org/r/20160114164159.528222587@linutronix.de
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+[bwh: Backported to 3.2: adjust filename]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ kernel/itimer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/itimer.c
++++ b/kernel/itimer.c
+@@ -26,7 +26,7 @@
+ */
+ static struct timeval itimer_get_remtime(struct hrtimer *timer)
+ {
+- ktime_t rem = hrtimer_get_remaining(timer);
++ ktime_t rem = __hrtimer_get_remaining(timer, true);
+
+ /*
+ * Racy but safe: if the itimer expires after the above
diff --git a/releases/3.2.78/iw_cxgb3-fix-incorrectly-returning-error-on-success.patch b/releases/3.2.78/iw_cxgb3-fix-incorrectly-returning-error-on-success.patch
new file mode 100644
index 00000000..531c1f2e
--- /dev/null
+++ b/releases/3.2.78/iw_cxgb3-fix-incorrectly-returning-error-on-success.patch
@@ -0,0 +1,38 @@
+From: Hariprasad S <hariprasad@chelsio.com>
+Date: Fri, 11 Dec 2015 13:59:17 +0530
+Subject: iw_cxgb3: Fix incorrectly returning error on success
+
+commit 67f1aee6f45059fd6b0f5b0ecb2c97ad0451f6b3 upstream.
+
+The cxgb3_*_send() functions return NET_XMIT_ values, which are
+positive integers values. So don't treat positive return values
+as an error.
+
+Signed-off-by: Steve Wise <swise@opengridcomputing.com>
+Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/infiniband/hw/cxgb3/iwch_cm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+@@ -150,7 +150,7 @@ static int iwch_l2t_send(struct t3cdev *
+ error = l2t_send(tdev, skb, l2e);
+ if (error < 0)
+ kfree_skb(skb);
+- return error;
++ return error < 0 ? error : 0;
+ }
+
+ int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb)
+@@ -166,7 +166,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *
+ error = cxgb3_ofld_send(tdev, skb);
+ if (error < 0)
+ kfree_skb(skb);
+- return error;
++ return error < 0 ? error : 0;
+ }
+
+ static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb)
diff --git a/releases/3.2.78/klist-fix-starting-point-removed-bug-in-klist-iterators.patch b/releases/3.2.78/klist-fix-starting-point-removed-bug-in-klist-iterators.patch
new file mode 100644
index 00000000..5c90dcab
--- /dev/null
+++ b/releases/3.2.78/klist-fix-starting-point-removed-bug-in-klist-iterators.patch
@@ -0,0 +1,61 @@
+From: James Bottomley <James.Bottomley@HansenPartnership.com>
+Date: Wed, 13 Jan 2016 08:10:31 -0800
+Subject: klist: fix starting point removed bug in klist iterators
+
+commit 00cd29b799e3449f0c68b1cc77cd4a5f95b42d17 upstream.
+
+The starting node for a klist iteration is often passed in from
+somewhere way above the klist infrastructure, meaning there's no
+guarantee the node is still on the list. We've seen this in SCSI where
+we use bus_find_device() to iterate through a list of devices. In the
+face of heavy hotplug activity, the last device returned by
+bus_find_device() can be removed before the next call. This leads to
+
+Dec 3 13:22:02 localhost kernel: WARNING: CPU: 2 PID: 28073 at include/linux/kref.h:47 klist_iter_init_node+0x3d/0x50()
+Dec 3 13:22:02 localhost kernel: Modules linked in: scsi_debug x86_pkg_temp_thermal kvm_intel kvm irqbypass crc32c_intel joydev iTCO_wdt dcdbas ipmi_devintf acpi_power_meter iTCO_vendor_support ipmi_si imsghandler pcspkr wmi acpi_cpufreq tpm_tis tpm shpchp lpc_ich mfd_core nfsd nfs_acl lockd grace sunrpc tg3 ptp pps_core
+Dec 3 13:22:02 localhost kernel: CPU: 2 PID: 28073 Comm: cat Not tainted 4.4.0-rc1+ #2
+Dec 3 13:22:02 localhost kernel: Hardware name: Dell Inc. PowerEdge R320/08VT7V, BIOS 2.0.22 11/19/2013
+Dec 3 13:22:02 localhost kernel: ffffffff81a20e77 ffff880613acfd18 ffffffff81321eef 0000000000000000
+Dec 3 13:22:02 localhost kernel: ffff880613acfd50 ffffffff8107ca52 ffff88061176b198 0000000000000000
+Dec 3 13:22:02 localhost kernel: ffffffff814542b0 ffff880610cfb100 ffff88061176b198 ffff880613acfd60
+Dec 3 13:22:02 localhost kernel: Call Trace:
+Dec 3 13:22:02 localhost kernel: [<ffffffff81321eef>] dump_stack+0x44/0x55
+Dec 3 13:22:02 localhost kernel: [<ffffffff8107ca52>] warn_slowpath_common+0x82/0xc0
+Dec 3 13:22:02 localhost kernel: [<ffffffff814542b0>] ? proc_scsi_show+0x20/0x20
+Dec 3 13:22:02 localhost kernel: [<ffffffff8107cb4a>] warn_slowpath_null+0x1a/0x20
+Dec 3 13:22:02 localhost kernel: [<ffffffff8167225d>] klist_iter_init_node+0x3d/0x50
+Dec 3 13:22:02 localhost kernel: [<ffffffff81421d41>] bus_find_device+0x51/0xb0
+Dec 3 13:22:02 localhost kernel: [<ffffffff814545ad>] scsi_seq_next+0x2d/0x40
+[...]
+
+And an eventual crash. It can actually occur in any hotplug system
+which has a device finder and a starting device.
+
+We can fix this globally by making sure the starting node for
+klist_iter_init_node() is actually a member of the list before using it
+(and by starting from the beginning if it isn't).
+
+Reported-by: Ewan D. Milne <emilne@redhat.com>
+Tested-by: Ewan D. Milne <emilne@redhat.com>
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ lib/klist.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/lib/klist.c
++++ b/lib/klist.c
+@@ -282,9 +282,9 @@ void klist_iter_init_node(struct klist *
+ struct klist_node *n)
+ {
+ i->i_klist = k;
+- i->i_cur = n;
+- if (n)
+- kref_get(&n->n_ref);
++ i->i_cur = NULL;
++ if (n && kref_get_unless_zero(&n->n_ref))
++ i->i_cur = n;
+ }
+ EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
diff --git a/releases/3.2.78/kvm-vmx-fix-mpx-detection.patch b/releases/3.2.78/kvm-vmx-fix-mpx-detection.patch
new file mode 100644
index 00000000..111972e7
--- /dev/null
+++ b/releases/3.2.78/kvm-vmx-fix-mpx-detection.patch
@@ -0,0 +1,36 @@
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Wed, 26 Mar 2014 15:54:00 +0100
+Subject: KVM: vmx: fix MPX detection
+
+commit 920c837785699bcc48f4a729ba9ee3492f620b95 upstream.
+
+kvm_x86_ops is still NULL at this point. Since kvm_init_msr_list
+cannot fail, it is safe to initialize it before the call.
+
+Fixes: 93c4adc7afedf9b0ec190066d45b6d67db5270da
+Reported-by: Fengguang Wu <fengguang.wu@intel.com>
+Tested-by: Jet Chen <jet.chen@intel.com>
+Cc: kvm@vger.kernel.org
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Brad Spengler <spender@grsecurity.net>
+[bwh: Dependency of "KVM: x86: expose MSR_TSC_AUX to userspace",
+ applied in 3.2.77]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/x86/kvm/x86.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -5257,9 +5257,10 @@ int kvm_arch_init(void *opaque)
+ goto out;
+
+ kvm_set_mmio_spte_mask();
+- kvm_init_msr_list();
+
+ kvm_x86_ops = ops;
++ kvm_init_msr_list();
++
+ kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
+ PT_DIRTY_MASK, PT64_NX_MASK, 0);
+
diff --git a/releases/3.2.78/libata-disable-forced-ports_impl-for-ahci-1.3.patch b/releases/3.2.78/libata-disable-forced-ports_impl-for-ahci-1.3.patch
new file mode 100644
index 00000000..3c7bf3f5
--- /dev/null
+++ b/releases/3.2.78/libata-disable-forced-ports_impl-for-ahci-1.3.patch
@@ -0,0 +1,36 @@
+From: Tejun Heo <tj@kernel.org>
+Date: Fri, 15 Jan 2016 15:13:05 -0500
+Subject: libata: disable forced PORTS_IMPL for >= AHCI 1.3
+
+commit 566d1827df2ef0cbe921d3d6946ac3007b1a6938 upstream.
+
+Some early controllers incorrectly reported zero ports in PORTS_IMPL
+register and the ahci driver fabricates PORTS_IMPL from the number of
+ports in those cases. This hasn't mattered but with the new nvme
+controllers there are cases where zero PORTS_IMPL is valid and should
+be honored.
+
+Disable the workaround for >= AHCI 1.3.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Andy Lutomirski <luto@amacapital.net>
+Link: http://lkml.kernel.org/g/CALCETrU7yMvXEDhjAUShoHEhDwifJGapdw--BKxsP0jmjKGmRw@mail.gmail.com
+Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/ata/libahci.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/ata/libahci.c
++++ b/drivers/ata/libahci.c
+@@ -480,8 +480,8 @@ void ahci_save_initial_config(struct dev
+ }
+ }
+
+- /* fabricate port_map from cap.nr_ports */
+- if (!port_map) {
++ /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
++ if (!port_map && vers < 0x10300) {
+ port_map = (1 << ahci_nr_ports(cap)) - 1;
+ dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
+
diff --git a/releases/3.2.78/libata-fix-sff-host-state-machine-locking-while-polling.patch b/releases/3.2.78/libata-fix-sff-host-state-machine-locking-while-polling.patch
new file mode 100644
index 00000000..95f52673
--- /dev/null
+++ b/releases/3.2.78/libata-fix-sff-host-state-machine-locking-while-polling.patch
@@ -0,0 +1,179 @@
+From: Tejun Heo <tj@kernel.org>
+Date: Mon, 1 Feb 2016 11:33:21 -0500
+Subject: libata: fix sff host state machine locking while polling
+
+commit 8eee1d3ed5b6fc8e14389567c9a6f53f82bb7224 upstream.
+
+The bulk of ATA host state machine is implemented by
+ata_sff_hsm_move(). The function is called from either the interrupt
+handler or, if polling, a work item. Unlike from the interrupt path,
+the polling path calls the function without holding the host lock and
+ata_sff_hsm_move() selectively grabs the lock.
+
+This is completely broken. If an IRQ triggers while polling is in
+progress, the two can easily race and end up accessing the hardware
+and updating state machine state at the same time. This can put the
+state machine in an illegal state and lead to a crash like the
+following.
+
+ kernel BUG at drivers/ata/libata-sff.c:1302!
+ invalid opcode: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN
+ Modules linked in:
+ CPU: 1 PID: 10679 Comm: syz-executor Not tainted 4.5.0-rc1+ #300
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
+ task: ffff88002bd00000 ti: ffff88002e048000 task.ti: ffff88002e048000
+ RIP: 0010:[<ffffffff83a83409>] [<ffffffff83a83409>] ata_sff_hsm_move+0x619/0x1c60
+ ...
+ Call Trace:
+ <IRQ>
+ [<ffffffff83a84c31>] __ata_sff_port_intr+0x1e1/0x3a0 drivers/ata/libata-sff.c:1584
+ [<ffffffff83a85611>] ata_bmdma_port_intr+0x71/0x400 drivers/ata/libata-sff.c:2877
+ [< inline >] __ata_sff_interrupt drivers/ata/libata-sff.c:1629
+ [<ffffffff83a85bf3>] ata_bmdma_interrupt+0x253/0x580 drivers/ata/libata-sff.c:2902
+ [<ffffffff81479f98>] handle_irq_event_percpu+0x108/0x7e0 kernel/irq/handle.c:157
+ [<ffffffff8147a717>] handle_irq_event+0xa7/0x140 kernel/irq/handle.c:205
+ [<ffffffff81484573>] handle_edge_irq+0x1e3/0x8d0 kernel/irq/chip.c:623
+ [< inline >] generic_handle_irq_desc include/linux/irqdesc.h:146
+ [<ffffffff811a92bc>] handle_irq+0x10c/0x2a0 arch/x86/kernel/irq_64.c:78
+ [<ffffffff811a7e4d>] do_IRQ+0x7d/0x1a0 arch/x86/kernel/irq.c:240
+ [<ffffffff86653d4c>] common_interrupt+0x8c/0x8c arch/x86/entry/entry_64.S:520
+ <EOI>
+ [< inline >] rcu_lock_acquire include/linux/rcupdate.h:490
+ [< inline >] rcu_read_lock include/linux/rcupdate.h:874
+ [<ffffffff8164b4a1>] filemap_map_pages+0x131/0xba0 mm/filemap.c:2145
+ [< inline >] do_fault_around mm/memory.c:2943
+ [< inline >] do_read_fault mm/memory.c:2962
+ [< inline >] do_fault mm/memory.c:3133
+ [< inline >] handle_pte_fault mm/memory.c:3308
+ [< inline >] __handle_mm_fault mm/memory.c:3418
+ [<ffffffff816efb16>] handle_mm_fault+0x2516/0x49a0 mm/memory.c:3447
+ [<ffffffff8127dc16>] __do_page_fault+0x376/0x960 arch/x86/mm/fault.c:1238
+ [<ffffffff8127e358>] trace_do_page_fault+0xe8/0x420 arch/x86/mm/fault.c:1331
+ [<ffffffff8126f514>] do_async_page_fault+0x14/0xd0 arch/x86/kernel/kvm.c:264
+ [<ffffffff86655578>] async_page_fault+0x28/0x30 arch/x86/entry/entry_64.S:986
+
+Fix it by ensuring that the polling path is holding the host lock
+before entering ata_sff_hsm_move() so that all hardware accesses and
+state updates are performed under the host lock.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-and-tested-by: Dmitry Vyukov <dvyukov@google.com>
+Link: http://lkml.kernel.org/g/CACT4Y+b_JsOxJu2EZyEf+mOXORc_zid5V1-pLZSroJVxyWdSpw@mail.gmail.com
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/ata/libata-sff.c | 32 +++++++++++---------------------
+ 1 file changed, 11 insertions(+), 21 deletions(-)
+
+--- a/drivers/ata/libata-sff.c
++++ b/drivers/ata/libata-sff.c
+@@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struc
+ static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+ {
+ struct ata_port *ap = qc->ap;
+- unsigned long flags;
+
+ if (ap->ops->error_handler) {
+ if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+-
+ /* EH might have kicked in while host lock is
+ * released.
+ */
+@@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct a
+ } else
+ ata_port_freeze(ap);
+ }
+-
+- spin_unlock_irqrestore(ap->lock, flags);
+ } else {
+ if (likely(!(qc->err_mask & AC_ERR_HSM)))
+ ata_qc_complete(qc);
+@@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct a
+ }
+ } else {
+ if (in_wq) {
+- spin_lock_irqsave(ap->lock, flags);
+ ata_sff_irq_on(ap);
+ ata_qc_complete(qc);
+- spin_unlock_irqrestore(ap->lock, flags);
+ } else
+ ata_qc_complete(qc);
+ }
+@@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap
+ {
+ struct ata_link *link = qc->dev->link;
+ struct ata_eh_info *ehi = &link->eh_info;
+- unsigned long flags = 0;
+ int poll_next;
+
++ lockdep_assert_held(ap->lock);
++
+ WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+
+ /* Make sure ata_sff_qc_issue() does not throw things
+@@ -1112,14 +1106,6 @@ fsm_start:
+ }
+ }
+
+- /* Send the CDB (atapi) or the first data block (ata pio out).
+- * During the state transition, interrupt handler shouldn't
+- * be invoked before the data transfer is complete and
+- * hsm_task_state is changed. Hence, the following locking.
+- */
+- if (in_wq)
+- spin_lock_irqsave(ap->lock, flags);
+-
+ if (qc->tf.protocol == ATA_PROT_PIO) {
+ /* PIO data out protocol.
+ * send first data block.
+@@ -1135,9 +1121,6 @@ fsm_start:
+ /* send CDB */
+ atapi_send_cdb(ap, qc);
+
+- if (in_wq)
+- spin_unlock_irqrestore(ap->lock, flags);
+-
+ /* if polling, ata_sff_pio_task() handles the rest.
+ * otherwise, interrupt handler takes over from here.
+ */
+@@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct work
+ u8 status;
+ int poll_next;
+
++ spin_lock_irq(ap->lock);
++
+ BUG_ON(ap->sff_pio_task_link == NULL);
+ /* qc can be NULL if timeout occurred */
+ qc = ata_qc_from_tag(ap, link->active_tag);
+ if (!qc) {
+ ap->sff_pio_task_link = NULL;
+- return;
++ goto out_unlock;
+ }
+
+ fsm_start:
+@@ -1381,11 +1366,14 @@ fsm_start:
+ */
+ status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
+ if (status & ATA_BUSY) {
++ spin_unlock_irq(ap->lock);
+ ata_msleep(ap, 2);
++ spin_lock_irq(ap->lock);
++
+ status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
+ if (status & ATA_BUSY) {
+ ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
+- return;
++ goto out_unlock;
+ }
+ }
+
+@@ -1402,6 +1390,8 @@ fsm_start:
+ */
+ if (poll_next)
+ goto fsm_start;
++out_unlock:
++ spin_unlock_irq(ap->lock);
+ }
+
+ /**
diff --git a/releases/3.2.78/mm-vmstat-fix-wrong-wq-sleep-when-memory-reclaim-doesn-t-make-any.patch b/releases/3.2.78/mm-vmstat-fix-wrong-wq-sleep-when-memory-reclaim-doesn-t-make-any.patch
new file mode 100644
index 00000000..7f3a4473
--- /dev/null
+++ b/releases/3.2.78/mm-vmstat-fix-wrong-wq-sleep-when-memory-reclaim-doesn-t-make-any.patch
@@ -0,0 +1,49 @@
+From: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
+Date: Fri, 5 Feb 2016 15:36:30 -0800
+Subject: mm, vmstat: fix wrong WQ sleep when memory reclaim doesn't make any
+ progress
+
+commit 564e81a57f9788b1475127012e0fd44e9049e342 upstream.
+
+Jan Stancek has reported that system occasionally hanging after "oom01"
+testcase from LTP triggers OOM. Guessing from a result that there is a
+kworker thread doing memory allocation and the values between "Node 0
+Normal free:" and "Node 0 Normal:" differs when hanging, vmstat is not
+up-to-date for some reason.
+
+According to commit 373ccbe59270 ("mm, vmstat: allow WQ concurrency to
+discover memory reclaim doesn't make any progress"), it meant to force
+the kworker thread to take a short sleep, but it by error used
+schedule_timeout(1). We missed that schedule_timeout() in state
+TASK_RUNNING doesn't do anything.
+
+Fix it by using schedule_timeout_uninterruptible(1) which forces the
+kworker thread to take a short sleep in order to make sure that vmstat
+is up-to-date.
+
+Fixes: 373ccbe59270 ("mm, vmstat: allow WQ concurrency to discover memory reclaim doesn't make any progress")
+Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Reported-by: Jan Stancek <jstancek@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Cristopher Lameter <clameter@sgi.com>
+Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+Cc: Arkadiusz Miskiewicz <arekm@maven.pl>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ mm/backing-dev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/backing-dev.c
++++ b/mm/backing-dev.c
+@@ -879,7 +879,7 @@ long wait_iff_congested(struct zone *zon
+ * here rather than calling cond_resched().
+ */
+ if (current->flags & PF_WQ_WORKER)
+- schedule_timeout(1);
++ schedule_timeout_uninterruptible(1);
+ else
+ cond_resched();
+
diff --git a/releases/3.2.78/ocfs2-dlm-clear-refmap-bit-of-recovery-lock-while-doing-local.patch b/releases/3.2.78/ocfs2-dlm-clear-refmap-bit-of-recovery-lock-while-doing-local.patch
new file mode 100644
index 00000000..bf8c7060
--- /dev/null
+++ b/releases/3.2.78/ocfs2-dlm-clear-refmap-bit-of-recovery-lock-while-doing-local.patch
@@ -0,0 +1,35 @@
+From: xuejiufei <xuejiufei@huawei.com>
+Date: Fri, 5 Feb 2016 15:36:47 -0800
+Subject: ocfs2/dlm: clear refmap bit of recovery lock while doing local
+ recovery cleanup
+
+commit c95a51807b730e4681e2ecbdfd669ca52601959e upstream.
+
+When recovery master down, dlm_do_local_recovery_cleanup() only remove
+the $RECOVERY lock owned by dead node, but do not clear the refmap bit.
+Which will make umount thread falling in dead loop migrating $RECOVERY
+to the dead node.
+
+Signed-off-by: xuejiufei <xuejiufei@huawei.com>
+Reviewed-by: Joseph Qi <joseph.qi@huawei.com>
+Cc: Mark Fasheh <mfasheh@suse.de>
+Cc: Joel Becker <jlbec@evilplan.org>
+Cc: Junxiao Bi <junxiao.bi@oracle.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ fs/ocfs2/dlm/dlmrecovery.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/ocfs2/dlm/dlmrecovery.c
++++ b/fs/ocfs2/dlm/dlmrecovery.c
+@@ -2333,6 +2333,8 @@ static void dlm_do_local_recovery_cleanu
+ break;
+ }
+ }
++ dlm_lockres_clear_refmap_bit(dlm, res,
++ dead_node);
+ spin_unlock(&res->spinlock);
+ continue;
+ }
diff --git a/releases/3.2.78/pci-aer-flush-workqueue-on-device-remove-to-avoid-use-after-free.patch b/releases/3.2.78/pci-aer-flush-workqueue-on-device-remove-to-avoid-use-after-free.patch
new file mode 100644
index 00000000..e63eaf02
--- /dev/null
+++ b/releases/3.2.78/pci-aer-flush-workqueue-on-device-remove-to-avoid-use-after-free.patch
@@ -0,0 +1,94 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 25 Jan 2016 10:08:00 -0600
+Subject: PCI/AER: Flush workqueue on device remove to avoid use-after-free
+
+commit 4ae2182b1e3407de369f8c5d799543b7db74221b upstream.
+
+A Root Port's AER structure (rpc) contains a queue of events. aer_irq()
+enqueues AER status information and schedules aer_isr() to dequeue and
+process it. When we remove a device, aer_remove() waits for the queue to
+be empty, then frees the rpc struct.
+
+But aer_isr() references the rpc struct after dequeueing and possibly
+emptying the queue, which can cause a use-after-free error as in the
+following scenario with two threads, aer_isr() on the left and a
+concurrent aer_remove() on the right:
+
+ Thread A Thread B
+ -------- --------
+ aer_irq():
+ rpc->prod_idx++
+ aer_remove():
+ wait_event(rpc->prod_idx == rpc->cons_idx)
+ # now blocked until queue becomes empty
+ aer_isr(): # ...
+ rpc->cons_idx++ # unblocked because queue is now empty
+ ... kfree(rpc)
+ mutex_unlock(&rpc->rpc_mutex)
+
+To prevent this problem, use flush_work() to wait until the last scheduled
+instance of aer_isr() has completed before freeing the rpc struct in
+aer_remove().
+
+I reproduced this use-after-free by flashing a device FPGA and
+re-enumerating the bus to find the new device. With SLUB debug, this
+crashes with 0x6b bytes (POISON_FREE, the use-after-free magic number) in
+GPR25:
+
+ pcieport 0000:00:00.0: AER: Multiple Corrected error received: id=0000
+ Unable to handle kernel paging request for data at address 0x27ef9e3e
+ Workqueue: events aer_isr
+ GPR24: dd6aa000 6b6b6b6b 605f8378 605f8360 d99b12c0 604fc674 606b1704 d99b12c0
+ NIP [602f5328] pci_walk_bus+0xd4/0x104
+
+[bhelgaas: changelog, stable tag]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/pci/pcie/aer/aerdrv.c | 4 +---
+ drivers/pci/pcie/aer/aerdrv.h | 1 -
+ drivers/pci/pcie/aer/aerdrv_core.c | 2 --
+ 3 files changed, 1 insertion(+), 6 deletions(-)
+
+--- a/drivers/pci/pcie/aer/aerdrv.c
++++ b/drivers/pci/pcie/aer/aerdrv.c
+@@ -263,7 +263,6 @@ static struct aer_rpc *aer_alloc_rpc(str
+ rpc->rpd = dev;
+ INIT_WORK(&rpc->dpc_handler, aer_isr);
+ mutex_init(&rpc->rpc_mutex);
+- init_waitqueue_head(&rpc->wait_release);
+
+ /* Use PCIe bus function to store rpc into PCIe device */
+ set_service_data(dev, rpc);
+@@ -286,8 +285,7 @@ static void aer_remove(struct pcie_devic
+ if (rpc->isr)
+ free_irq(dev->irq, dev);
+
+- wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
+-
++ flush_work(&rpc->dpc_handler);
+ aer_disable_rootport(rpc);
+ kfree(rpc);
+ set_service_data(dev, NULL);
+--- a/drivers/pci/pcie/aer/aerdrv.h
++++ b/drivers/pci/pcie/aer/aerdrv.h
+@@ -76,7 +76,6 @@ struct aer_rpc {
+ * recovery on the same
+ * root port hierarchy
+ */
+- wait_queue_head_t wait_release;
+ };
+
+ struct aer_broadcast_data {
+--- a/drivers/pci/pcie/aer/aerdrv_core.c
++++ b/drivers/pci/pcie/aer/aerdrv_core.c
+@@ -823,8 +823,6 @@ void aer_isr(struct work_struct *work)
+ while (get_e_source(rpc, &e_src))
+ aer_isr_one_error(p_device, &e_src);
+ mutex_unlock(&rpc->rpc_mutex);
+-
+- wake_up(&rpc->wait_release);
+ }
+
+ /**
diff --git a/releases/3.2.78/perf-annotate-browser-fix-behaviour-of-shift-tab-with-nothing.patch b/releases/3.2.78/perf-annotate-browser-fix-behaviour-of-shift-tab-with-nothing.patch
new file mode 100644
index 00000000..05a40268
--- /dev/null
+++ b/releases/3.2.78/perf-annotate-browser-fix-behaviour-of-shift-tab-with-nothing.patch
@@ -0,0 +1,39 @@
+From: Markus Trippelsdorf <markus@trippelsdorf.de>
+Date: Mon, 14 Dec 2015 16:44:03 +0100
+Subject: perf annotate browser: Fix behaviour of Shift-Tab with nothing
+ focussed
+
+commit d4913cbd05bab685e49c8174896e563b2487d054 upstream.
+
+The issue was pointed out by gcc-6's -Wmisleading-indentation.
+
+Signed-off-by: Markus Trippelsdorf <markus@trippelsdorf.de>
+Acked-by: Ingo Molnar <mingo@kernel.org>
+Cc: Ben Hutchings <ben@decadent.org.uk>
+Cc: Matt Fleming <matt@codeblueprint.co.uk>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Fixes: c97cf42219b7 ("perf top: Live TUI Annotation")
+Link: http://lkml.kernel.org/r/20151214154403.GB1409@x4
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+[bwh: Backported to 3.2: adjust filename, context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ tools/perf/util/ui/browsers/annotate.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/tools/perf/util/ui/browsers/annotate.c
++++ b/tools/perf/util/ui/browsers/annotate.c
+@@ -276,11 +276,11 @@ static int annotate_browser__run(struct
+ nd = self->curr_hot;
+ break;
+ case K_UNTAB:
+- if (nd != NULL)
++ if (nd != NULL) {
+ nd = rb_next(nd);
+ if (nd == NULL)
+ nd = rb_first(&self->entries);
+- else
++ } else
+ nd = self->curr_hot;
+ break;
+ case 'H':
diff --git a/releases/3.2.78/pipe-fix-buffer-offset-after-partially-failed-read.patch b/releases/3.2.78/pipe-fix-buffer-offset-after-partially-failed-read.patch
new file mode 100644
index 00000000..1d0d29b7
--- /dev/null
+++ b/releases/3.2.78/pipe-fix-buffer-offset-after-partially-failed-read.patch
@@ -0,0 +1,51 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 13 Feb 2016 02:34:52 +0000
+Subject: pipe: Fix buffer offset after partially failed read
+
+Quoting the RHEL advisory:
+
+> It was found that the fix for CVE-2015-1805 incorrectly kept buffer
+> offset and buffer length in sync on a failed atomic read, potentially
+> resulting in a pipe buffer state corruption. A local, unprivileged user
+> could use this flaw to crash the system or leak kernel memory to user
+> space. (CVE-2016-0774, Moderate)
+
+The same flawed fix was applied to stable branches from 2.6.32.y to
+3.14.y inclusive, and I was able to reproduce the issue on 3.2.y.
+We need to give pipe_iov_copy_to_user() a separate offset variable
+and only update the buffer offset if it succeeds.
+
+References: https://rhn.redhat.com/errata/RHSA-2016-0103.html
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -395,6 +395,7 @@ pipe_read(struct kiocb *iocb, const stru
+ void *addr;
+ size_t chars = buf->len, remaining;
+ int error, atomic;
++ int offset;
+
+ if (chars > total_len)
+ chars = total_len;
+@@ -408,9 +409,10 @@ pipe_read(struct kiocb *iocb, const stru
+
+ atomic = !iov_fault_in_pages_write(iov, chars);
+ remaining = chars;
++ offset = buf->offset;
+ redo:
+ addr = ops->map(pipe, buf, atomic);
+- error = pipe_iov_copy_to_user(iov, addr, &buf->offset,
++ error = pipe_iov_copy_to_user(iov, addr, &offset,
+ &remaining, atomic);
+ ops->unmap(pipe, buf, addr);
+ if (unlikely(error)) {
+@@ -426,6 +428,7 @@ redo:
+ break;
+ }
+ ret += chars;
++ buf->offset += chars;
+ buf->len -= chars;
+
+ /* Was it a packet buffer? Clean up and exit */
+
diff --git a/releases/3.2.78/pipe-limit-the-per-user-amount-of-pages-allocated-in-pipes.patch b/releases/3.2.78/pipe-limit-the-per-user-amount-of-pages-allocated-in-pipes.patch
new file mode 100644
index 00000000..546353c4
--- /dev/null
+++ b/releases/3.2.78/pipe-limit-the-per-user-amount-of-pages-allocated-in-pipes.patch
@@ -0,0 +1,240 @@
+From: Willy Tarreau <w@1wt.eu>
+Date: Mon, 18 Jan 2016 16:36:09 +0100
+Subject: pipe: limit the per-user amount of pages allocated in pipes
+
+commit 759c01142a5d0f364a462346168a56de28a80f52 upstream.
+
+On no-so-small systems, it is possible for a single process to cause an
+OOM condition by filling large pipes with data that are never read. A
+typical process filling 4000 pipes with 1 MB of data will use 4 GB of
+memory. On small systems it may be tricky to set the pipe max size to
+prevent this from happening.
+
+This patch makes it possible to enforce a per-user soft limit above
+which new pipes will be limited to a single page, effectively limiting
+them to 4 kB each, as well as a hard limit above which no new pipes may
+be created for this user. This has the effect of protecting the system
+against memory abuse without hurting other users, and still allowing
+pipes to work correctly though with less data at once.
+
+The limit are controlled by two new sysctls : pipe-user-pages-soft, and
+pipe-user-pages-hard. Both may be disabled by setting them to zero. The
+default soft limit allows the default number of FDs per process (1024)
+to create pipes of the default size (64kB), thus reaching a limit of 64MB
+before starting to create only smaller pipes. With 256 processes limited
+to 1024 FDs each, this results in 1024*64kB + (256*1024 - 1024) * 4kB =
+1084 MB of memory allocated for a user. The hard limit is disabled by
+default to avoid breaking existing applications that make intensive use
+of pipes (eg: for splicing).
+
+Reported-by: socketpair@gmail.com
+Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Mitigates: CVE-2013-4312 (Linux 2.0+)
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ Documentation/sysctl/fs.txt | 23 ++++++++++++++++++++++
+ fs/pipe.c | 47 +++++++++++++++++++++++++++++++++++++++++++--
+ include/linux/pipe_fs_i.h | 4 ++++
+ include/linux/sched.h | 1 +
+ kernel/sysctl.c | 14 ++++++++++++++
+ 5 files changed, 87 insertions(+), 2 deletions(-)
+
+--- a/Documentation/sysctl/fs.txt
++++ b/Documentation/sysctl/fs.txt
+@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/
+ - nr_open
+ - overflowuid
+ - overflowgid
++- pipe-user-pages-hard
++- pipe-user-pages-soft
+ - suid_dumpable
+ - super-max
+ - super-nr
+@@ -157,6 +159,27 @@ The default is 65534.
+
+ ==============================================================
+
++pipe-user-pages-hard:
++
++Maximum total number of pages a non-privileged user may allocate for pipes.
++Once this limit is reached, no new pipes may be allocated until usage goes
++below the limit again. When set to 0, no limit is applied, which is the default
++setting.
++
++==============================================================
++
++pipe-user-pages-soft:
++
++Maximum total number of pages a non-privileged user may allocate for pipes
++before the pipe size gets limited to a single page. Once this limit is reached,
++new pipes will be limited to a single page in size for this user in order to
++limit total memory usage, and trying to increase them using fcntl() will be
++denied until usage goes below the limit again. The default value allows to
++allocate up to 1024 pipes at their default size. When set to 0, no limit is
++applied.
++
++==============================================================
++
+ suid_dumpable:
+
+ This value can be used to query and set the core dump mode for setuid
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -35,6 +35,12 @@ unsigned int pipe_max_size = 1048576;
+ */
+ unsigned int pipe_min_size = PAGE_SIZE;
+
++/* Maximum allocatable pages per user. Hard limit is unset by default, soft
++ * matches default values.
++ */
++unsigned long pipe_user_pages_hard;
++unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
++
+ /*
+ * We use a start+len construction, which provides full use of the
+ * allocated memory.
+@@ -929,20 +935,49 @@ const struct file_operations rdwr_pipefi
+ .fasync = pipe_rdwr_fasync,
+ };
+
++static void account_pipe_buffers(struct pipe_inode_info *pipe,
++ unsigned long old, unsigned long new)
++{
++ atomic_long_add(new - old, &pipe->user->pipe_bufs);
++}
++
++static bool too_many_pipe_buffers_soft(struct user_struct *user)
++{
++ return pipe_user_pages_soft &&
++ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
++}
++
++static bool too_many_pipe_buffers_hard(struct user_struct *user)
++{
++ return pipe_user_pages_hard &&
++ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
++}
++
+ struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
+ {
+ struct pipe_inode_info *pipe;
+
+ pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
+ if (pipe) {
+- pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL);
++ unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
++ struct user_struct *user = get_current_user();
++
++ if (!too_many_pipe_buffers_hard(user)) {
++ if (too_many_pipe_buffers_soft(user))
++ pipe_bufs = 1;
++ pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
++ }
++
+ if (pipe->bufs) {
+ init_waitqueue_head(&pipe->wait);
+ pipe->r_counter = pipe->w_counter = 1;
+ pipe->inode = inode;
+- pipe->buffers = PIPE_DEF_BUFFERS;
++ pipe->buffers = pipe_bufs;
++ pipe->user = user;
++ account_pipe_buffers(pipe, 0, pipe_bufs);
+ return pipe;
+ }
++ free_uid(user);
+ kfree(pipe);
+ }
+
+@@ -953,6 +988,8 @@ void __free_pipe_info(struct pipe_inode_
+ {
+ int i;
+
++ account_pipe_buffers(pipe, pipe->buffers, 0);
++ free_uid(pipe->user);
+ for (i = 0; i < pipe->buffers; i++) {
+ struct pipe_buffer *buf = pipe->bufs + i;
+ if (buf->ops)
+@@ -1201,6 +1238,7 @@ static long pipe_set_size(struct pipe_in
+ memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
+ }
+
++ account_pipe_buffers(pipe, pipe->buffers, nr_pages);
+ pipe->curbuf = 0;
+ kfree(pipe->bufs);
+ pipe->bufs = bufs;
+@@ -1274,6 +1312,11 @@ long pipe_fcntl(struct file *file, unsig
+ if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
+ ret = -EPERM;
+ goto out;
++ } else if ((too_many_pipe_buffers_hard(pipe->user) ||
++ too_many_pipe_buffers_soft(pipe->user)) &&
++ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
++ ret = -EPERM;
++ goto out;
+ }
+ ret = pipe_set_size(pipe, nr_pages);
+ break;
+--- a/include/linux/pipe_fs_i.h
++++ b/include/linux/pipe_fs_i.h
+@@ -43,6 +43,7 @@ struct pipe_buffer {
+ * @fasync_writers: writer side fasync
+ * @inode: inode this pipe is attached to
+ * @bufs: the circular array of pipe buffers
++ * @user: the user who created this pipe
+ **/
+ struct pipe_inode_info {
+ wait_queue_head_t wait;
+@@ -57,6 +58,7 @@ struct pipe_inode_info {
+ struct fasync_struct *fasync_writers;
+ struct inode *inode;
+ struct pipe_buffer *bufs;
++ struct user_struct *user;
+ };
+
+ /*
+@@ -142,6 +144,8 @@ void pipe_unlock(struct pipe_inode_info
+ void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
+
+ extern unsigned int pipe_max_size, pipe_min_size;
++extern unsigned long pipe_user_pages_hard;
++extern unsigned long pipe_user_pages_soft;
+ int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
+
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -710,6 +710,7 @@ struct user_struct {
+ #endif
+ unsigned long locked_shm; /* How many pages of mlocked shm ? */
+ unsigned long unix_inflight; /* How many files in flight in unix sockets */
++ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */
+
+ #ifdef CONFIG_KEYS
+ struct key *uid_keyring; /* UID specific keyring */
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -1518,6 +1518,20 @@ static struct ctl_table fs_table[] = {
+ .proc_handler = &pipe_proc_fn,
+ .extra1 = &pipe_min_size,
+ },
++ {
++ .procname = "pipe-user-pages-hard",
++ .data = &pipe_user_pages_hard,
++ .maxlen = sizeof(pipe_user_pages_hard),
++ .mode = 0644,
++ .proc_handler = proc_doulongvec_minmax,
++ },
++ {
++ .procname = "pipe-user-pages-soft",
++ .data = &pipe_user_pages_soft,
++ .maxlen = sizeof(pipe_user_pages_soft),
++ .mode = 0644,
++ .proc_handler = proc_doulongvec_minmax,
++ },
+ { }
+ };
+
diff --git a/releases/3.2.78/posix-timers-handle-relative-timers-with-config_time_low_res-proper.patch b/releases/3.2.78/posix-timers-handle-relative-timers-with-config_time_low_res-proper.patch
new file mode 100644
index 00000000..91b08dfd
--- /dev/null
+++ b/releases/3.2.78/posix-timers-handle-relative-timers-with-config_time_low_res-proper.patch
@@ -0,0 +1,36 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Jan 2016 16:54:47 +0000
+Subject: posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper
+
+commit 572c39172684c3711e4a03c9a7380067e2b0661c upstream.
+
+As Helge reported for timerfd we have the same issue in posix timers. We
+return remaining time larger than the programmed relative time to user space
+in case of CONFIG_TIME_LOW_RES=y. Use the proper function to adjust the extra
+time added in hrtimer_start_range_ns().
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Helge Deller <deller@gmx.de>
+Cc: John Stultz <john.stultz@linaro.org>
+Cc: linux-m68k@lists.linux-m68k.org
+Cc: dhowells@redhat.com
+Link: http://lkml.kernel.org/r/20160114164159.450510905@linutronix.de
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+[bwh: Backported to 3.2: adjust filename]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ kernel/posix-timers.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/posix-timers.c
++++ b/kernel/posix-timers.c
+@@ -706,7 +706,7 @@ common_timer_get(struct k_itimer *timr,
+ (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+ timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
+
+- remaining = ktime_sub(hrtimer_get_expires(timer), now);
++ remaining = __hrtimer_expires_remaining_adjusted(timer, now);
+ /* Return 0 only, when the timer is expired and not pending */
+ if (remaining.tv64 <= 0) {
+ /*
diff --git a/releases/3.2.78/pptp-fix-illegal-memory-access-caused-by-multiple-bind-s.patch b/releases/3.2.78/pptp-fix-illegal-memory-access-caused-by-multiple-bind-s.patch
new file mode 100644
index 00000000..96dfe708
--- /dev/null
+++ b/releases/3.2.78/pptp-fix-illegal-memory-access-caused-by-multiple-bind-s.patch
@@ -0,0 +1,111 @@
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Date: Fri, 22 Jan 2016 01:39:43 +0100
+Subject: pptp: fix illegal memory access caused by multiple bind()s
+
+commit 9a368aff9cb370298fa02feeffa861f2db497c18 upstream.
+
+Several times already this has been reported as kasan reports caused by
+syzkaller and trinity and people always looked at RCU races, but it is
+much more simple. :)
+
+In case we bind a pptp socket multiple times, we simply add it to
+the callid_sock list but don't remove the old binding. Thus the old
+socket stays in the bucket with unused call_id indexes and doesn't get
+cleaned up. This causes various forms of kasan reports which were hard
+to pinpoint.
+
+Simply don't allow multiple binds and correct error handling in
+pptp_bind. Also keep sk_state bits in place in pptp_connect.
+
+Fixes: 00959ade36acad ("PPTP: PPP over IPv4 (Point-to-Point Tunneling Protocol)")
+Cc: Dmitry Kozlov <xeb@mail.ru>
+Cc: Sasha Levin <sasha.levin@oracle.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Cc: Dave Jones <davej@codemonkey.org.uk>
+Reported-by: Dave Jones <davej@codemonkey.org.uk>
+Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/net/ppp/pptp.c | 34 ++++++++++++++++++++++++----------
+ 1 file changed, 24 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ppp/pptp.c
++++ b/drivers/net/ppp/pptp.c
+@@ -131,24 +131,27 @@ static int lookup_chan_dst(u16 call_id,
+ return i < MAX_CALLID;
+ }
+
+-static int add_chan(struct pppox_sock *sock)
++static int add_chan(struct pppox_sock *sock,
++ struct pptp_addr *sa)
+ {
+ static int call_id;
+
+ spin_lock(&chan_lock);
+- if (!sock->proto.pptp.src_addr.call_id) {
++ if (!sa->call_id) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
+ if (call_id == MAX_CALLID) {
+ call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
+ if (call_id == MAX_CALLID)
+ goto out_err;
+ }
+- sock->proto.pptp.src_addr.call_id = call_id;
+- } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
++ sa->call_id = call_id;
++ } else if (test_bit(sa->call_id, callid_bitmap)) {
+ goto out_err;
++ }
+
+- set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
+- rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
++ sock->proto.pptp.src_addr = *sa;
++ set_bit(sa->call_id, callid_bitmap);
++ rcu_assign_pointer(callid_sock[sa->call_id], sock);
+ spin_unlock(&chan_lock);
+
+ return 0;
+@@ -417,7 +420,6 @@ static int pptp_bind(struct socket *sock
+ struct sock *sk = sock->sk;
+ struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
+ struct pppox_sock *po = pppox_sk(sk);
+- struct pptp_opt *opt = &po->proto.pptp;
+ int error = 0;
+
+ if (sockaddr_len < sizeof(struct sockaddr_pppox))
+@@ -425,10 +427,22 @@ static int pptp_bind(struct socket *sock
+
+ lock_sock(sk);
+
+- opt->src_addr = sp->sa_addr.pptp;
+- if (add_chan(po))
++ if (sk->sk_state & PPPOX_DEAD) {
++ error = -EALREADY;
++ goto out;
++ }
++
++ if (sk->sk_state & PPPOX_BOUND) {
+ error = -EBUSY;
++ goto out;
++ }
++
++ if (add_chan(po, &sp->sa_addr.pptp))
++ error = -EBUSY;
++ else
++ sk->sk_state |= PPPOX_BOUND;
+
++out:
+ release_sock(sk);
+ return error;
+ }
+@@ -499,7 +513,7 @@ static int pptp_connect(struct socket *s
+ }
+
+ opt->dst_addr = sp->sa_addr.pptp;
+- sk->sk_state = PPPOX_CONNECTED;
++ sk->sk_state |= PPPOX_CONNECTED;
+
+ end:
+ release_sock(sk);
diff --git a/releases/3.2.78/revert-xhci-don-t-finish-a-td-if-we-get-a-short-transfer-event-mid.patch b/releases/3.2.78/revert-xhci-don-t-finish-a-td-if-we-get-a-short-transfer-event-mid.patch
new file mode 100644
index 00000000..30e252bc
--- /dev/null
+++ b/releases/3.2.78/revert-xhci-don-t-finish-a-td-if-we-get-a-short-transfer-event-mid.patch
@@ -0,0 +1,58 @@
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Tue, 26 Jan 2016 17:50:04 +0200
+Subject: Revert "xhci: don't finish a TD if we get a short-transfer event mid
+ TD"
+
+commit a6835090716a85f2297668ba593bd00e1051e662 upstream.
+
+This reverts commit e210c422b6fd ("xhci: don't finish a TD if we get a
+short transfer event mid TD")
+
+Turns out that most host controllers do not follow the xHCI specs and never
+send the second event for the last TRB in the TD if there was a short event
+mid-TD.
+
+Returning the URB directly after the first short-transfer event is far
+better than never returning the URB. (class drivers usually timeout
+after 30sec). For the hosts that do send the second event we will go
+back to treating it as misplaced event and print an error message for it.
+
+The origial patch was sent to stable kernels and needs to be reverted from
+there as well
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/host/xhci-ring.c | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index f1c21c40b4a6..3915657e6078 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2187,10 +2187,6 @@
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+ /* Fast path - was this the last TRB in the TD for this URB? */
+ if (event_trb == td->last_trb) {
+- if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
+- return finish_td(xhci, td, event_trb, event, ep,
+- status, false);
+-
+ if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+ td->urb->actual_length =
+ td->urb->transfer_buffer_length -
+@@ -2242,12 +2238,6 @@
+ td->urb->actual_length +=
+ TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+-
+- if (trb_comp_code == COMP_SHORT_TX) {
+- xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
+- td->urb_length_set = true;
+- return 0;
+- }
+ }
+
+ return finish_td(xhci, td, event_trb, event, ep, status, false);
diff --git a/releases/3.2.78/rfkill-fix-rfkill_fop_read-wait_event-usage.patch b/releases/3.2.78/rfkill-fix-rfkill_fop_read-wait_event-usage.patch
new file mode 100644
index 00000000..2c016cbb
--- /dev/null
+++ b/releases/3.2.78/rfkill-fix-rfkill_fop_read-wait_event-usage.patch
@@ -0,0 +1,59 @@
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 26 Jan 2016 11:29:03 +0100
+Subject: rfkill: fix rfkill_fop_read wait_event usage
+
+commit 6736fde9672ff6717ac576e9bba2fd5f3dfec822 upstream.
+
+The code within wait_event_interruptible() is called with
+!TASK_RUNNING, so mustn't call any functions that can sleep,
+like mutex_lock().
+
+Since we re-check the list_empty() in a loop after the wait,
+it's safe to simply use list_empty() without locking.
+
+This bug has existed forever, but was only discovered now
+because all userspace implementations, including the default
+'rfkill' tool, use poll() or select() to get a readable fd
+before attempting to read.
+
+Fixes: c64fb01627e24 ("rfkill: create useful userspace interface")
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ net/rfkill/core.c | 16 ++++------------
+ 1 file changed, 4 insertions(+), 12 deletions(-)
+
+--- a/net/rfkill/core.c
++++ b/net/rfkill/core.c
+@@ -1065,17 +1065,6 @@ static unsigned int rfkill_fop_poll(stru
+ return res;
+ }
+
+-static bool rfkill_readable(struct rfkill_data *data)
+-{
+- bool r;
+-
+- mutex_lock(&data->mtx);
+- r = !list_empty(&data->events);
+- mutex_unlock(&data->mtx);
+-
+- return r;
+-}
+-
+ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+ {
+@@ -1092,8 +1081,11 @@ static ssize_t rfkill_fop_read(struct fi
+ goto out;
+ }
+ mutex_unlock(&data->mtx);
++ /* since we re-check and it just compares pointers,
++ * using !list_empty() without locking isn't a problem
++ */
+ ret = wait_event_interruptible(data->read_wait,
+- rfkill_readable(data));
++ !list_empty(&data->events));
+ mutex_lock(&data->mtx);
+
+ if (ret)
diff --git a/releases/3.2.78/saa7134-alsa-only-frees-registered-sound-cards.patch b/releases/3.2.78/saa7134-alsa-only-frees-registered-sound-cards.patch
new file mode 100644
index 00000000..034bbd6c
--- /dev/null
+++ b/releases/3.2.78/saa7134-alsa-only-frees-registered-sound-cards.patch
@@ -0,0 +1,66 @@
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Date: Thu, 4 Feb 2016 15:59:43 -0200
+Subject: [media] saa7134-alsa: Only frees registered sound cards
+
+commit ac75fe5d8fe4a0bf063be18fb29684405279e79e upstream.
+
+That prevents this bug:
+[ 2382.269496] BUG: unable to handle kernel NULL pointer dereference at 0000000000000540
+[ 2382.270013] IP: [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
+[ 2382.270013] PGD 0
+[ 2382.270013] Oops: 0002 [#1] SMP
+[ 2382.270013] Modules linked in: saa7134_alsa(-) tda1004x saa7134_dvb videobuf2_dvb dvb_core tda827x tda8290 tuner saa7134 tveeprom videobuf2_dma_sg videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media auth_rpcgss nfsv4 dns_resolver nfs lockd grace sunrpc tun bridge stp llc ebtables ip6table_filter ip6_tables nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack it87 hwmon_vid snd_hda_codec_idt snd_hda_codec_generic iTCO_wdt iTCO_vendor_support snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_seq pcspkr i2c_i801 snd_seq_device snd_pcm snd_timer lpc_ich snd mfd_core soundcore binfmt_misc i915 video i2c_algo_bit drm_kms_helper drm r8169 ata_generic serio_raw pata_acpi mii i2c_core [last unloaded: videobuf2_memops]
+[ 2382.270013] CPU: 0 PID: 4899 Comm: rmmod Not tainted 4.5.0-rc1+ #4
+[ 2382.270013] Hardware name: PCCHIPS P17G/P17G, BIOS 080012 05/14/2008
+[ 2382.270013] task: ffff880039c38000 ti: ffff88003c764000 task.ti: ffff88003c764000
+[ 2382.270013] RIP: 0010:[<ffffffffa01fe616>] [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
+[ 2382.270013] RSP: 0018:ffff88003c767ea0 EFLAGS: 00010286
+[ 2382.270013] RAX: ffff88003c767eb8 RBX: 0000000000000000 RCX: 0000000000006260
+[ 2382.270013] RDX: ffffffffa020a060 RSI: ffffffffa0206de1 RDI: ffff88003c767eb0
+[ 2382.270013] RBP: ffff88003c767ed8 R08: 0000000000019960 R09: ffffffff811a5412
+[ 2382.270013] R10: ffffea0000d7c200 R11: 0000000000000000 R12: ffff88003c767ea8
+[ 2382.270013] R13: 00007ffe760617f7 R14: 0000000000000000 R15: 0000557625d7f1e0
+[ 2382.270013] FS: 00007f80bb1c0700(0000) GS:ffff88003f400000(0000) knlGS:0000000000000000
+[ 2382.270013] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+[ 2382.270013] CR2: 0000000000000540 CR3: 000000003c00f000 CR4: 00000000000006f0
+[ 2382.270013] Stack:
+[ 2382.270013] 000000003c767ed8 ffffffff00000000 ffff880000000000 ffff88003c767eb8
+[ 2382.270013] ffff88003c767eb8 ffffffffa049a890 00007ffe76060060 ffff88003c767ef0
+[ 2382.270013] ffffffffa049889d ffffffffa049a500 ffff88003c767f48 ffffffff8111079c
+[ 2382.270013] Call Trace:
+[ 2382.270013] [<ffffffffa049889d>] saa7134_alsa_exit+0x1d/0x780 [saa7134_alsa]
+[ 2382.270013] [<ffffffff8111079c>] SyS_delete_module+0x19c/0x1f0
+[ 2382.270013] [<ffffffff8170fc2e>] entry_SYSCALL_64_fastpath+0x12/0x71
+[ 2382.270013] Code: 20 a0 48 c7 c6 e1 6d 20 a0 48 89 e5 41 54 53 4c 8d 65 d0 48 89 fb 48 83 ec 28 c7 45 d0 00 00 00 00 49 8d 7c 24 08 e8 7a 55 ed e0 <4c> 89 a3 40 05 00 00 48 89 df e8 eb fd ff ff 85 c0 75 1a 48 8d
+[ 2382.270013] RIP [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
+[ 2382.270013] RSP <ffff88003c767ea0>
+[ 2382.270013] CR2: 0000000000000540
+
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+[bwh: Backported to 3.2: adjust filename]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/media/video/saa7134/saa7134-alsa.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/media/video/saa7134/saa7134-alsa.c
++++ b/drivers/media/video/saa7134/saa7134-alsa.c
+@@ -1145,6 +1145,8 @@ static int alsa_device_init(struct saa71
+
+ static int alsa_device_exit(struct saa7134_dev *dev)
+ {
++ if (!snd_saa7134_cards[dev->nr])
++ return 1;
+
+ snd_card_free(snd_saa7134_cards[dev->nr]);
+ snd_saa7134_cards[dev->nr] = NULL;
+@@ -1194,7 +1196,8 @@ static void saa7134_alsa_exit(void)
+ int idx;
+
+ for (idx = 0; idx < SNDRV_CARDS; idx++) {
+- snd_card_free(snd_saa7134_cards[idx]);
++ if (snd_saa7134_cards[idx])
++ snd_card_free(snd_saa7134_cards[idx]);
+ }
+
+ saa7134_dmasound_init = NULL;
diff --git a/releases/3.2.78/sched-fix-__sched_setscheduler-vs-load-balancing-race.patch b/releases/3.2.78/sched-fix-__sched_setscheduler-vs-load-balancing-race.patch
new file mode 100644
index 00000000..279701da
--- /dev/null
+++ b/releases/3.2.78/sched-fix-__sched_setscheduler-vs-load-balancing-race.patch
@@ -0,0 +1,50 @@
+From: Mike Galbraith <umgwanakikbuti@gmail.com>
+Date: Wed, 17 Feb 2016 04:02:59 +0100
+Subject: sched: fix __sched_setscheduler() vs load balancing race
+
+__sched_setscheduler() may release rq->lock in pull_rt_task() as a task is
+being changed rt -> fair class. load balancing may sneak in, move the task
+behind __sched_setscheduler()'s back, which explodes in switched_to_fair()
+when the passed but no longer valid rq is used. Tell can_migrate_task() to
+say no if ->pi_lock is held.
+
+@stable: Kernels that predate SCHED_DEADLINE can use this simple (and tested)
+check in lieu of backport of the full 18 patch mainline treatment.
+
+Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com>
+[bwh: Backported to 3.2:
+ - Adjust numbering in the comment
+ - Adjust filename]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Cc: Byungchul Park <byungchul.park@lge.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Willy Tarreau <w@1wt.eu>
+---
+ kernel/sched/fair.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/kernel/sched_fair.c
++++ b/kernel/sched_fair.c
+@@ -2791,6 +2791,7 @@ int can_migrate_task(struct task_struct
+ * 1) running (obviously), or
+ * 2) cannot be migrated to this CPU due to cpus_allowed, or
+ * 3) are cache-hot on their current CPU.
++ * 4) p->pi_lock is held.
+ */
+ if (!cpumask_test_cpu(this_cpu, tsk_cpus_allowed(p))) {
+ schedstat_inc(p, se.statistics.nr_failed_migrations_affine);
+@@ -2804,6 +2805,14 @@ int can_migrate_task(struct task_struct
+ }
+
+ /*
++ * rt -> fair class change may be in progress. If we sneak in should
++ * double_lock_balance() release rq->lock, and move the task, we will
++ * cause switched_to_fair() to meet a passed but no longer valid rq.
++ */
++ if (raw_spin_is_locked(&p->pi_lock))
++ return 0;
++
++ /*
+ * Aggressive migration if:
+ * 1) task is cache cold, or
+ * 2) too many balance attempts have failed.
diff --git a/releases/3.2.78/scsi-fix-crashes-in-sd-and-sr-runtime-pm.patch b/releases/3.2.78/scsi-fix-crashes-in-sd-and-sr-runtime-pm.patch
new file mode 100644
index 00000000..6e8f351f
--- /dev/null
+++ b/releases/3.2.78/scsi-fix-crashes-in-sd-and-sr-runtime-pm.patch
@@ -0,0 +1,53 @@
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 20 Jan 2016 11:26:01 -0500
+Subject: SCSI: fix crashes in sd and sr runtime PM
+
+commit 13b4389143413a1f18127c07f72c74cad5b563e8 upstream.
+
+Runtime suspend during driver probe and removal can cause problems.
+The driver's runtime_suspend or runtime_resume callbacks may invoked
+before the driver has finished binding to the device or after the
+driver has unbound from the device.
+
+This problem shows up with the sd and sr drivers, and can cause disk
+or CD/DVD drives to become unusable as a result. The fix is simple.
+The drivers store a pointer to the scsi_disk or scsi_cd structure as
+their private device data when probing is finished, so we simply have
+to be sure to clear the private data during removal and test it during
+runtime suspend/resume.
+
+This fixes <https://bugs.debian.org/801925>.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-by: Paul Menzel <paul.menzel@giantmonkey.de>
+Reported-by: Erich Schubert <erich@debian.org>
+Reported-by: Alexandre Rossi <alexandre.rossi@gmail.com>
+Tested-by: Paul Menzel <paul.menzel@giantmonkey.de>
+Tested-by: Erich Schubert <erich@debian.org>
+Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
+[bwh: Backported to 3.2: drop changes to sr as it doesn't support runtime PM]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -2767,8 +2767,8 @@ static int sd_suspend(struct device *dev
+ struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+ int ret = 0;
+
+- if (!sdkp)
+- return 0; /* this can happen */
++ if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
++ return 0;
+
+ if (sdkp->WCE) {
+ sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
+@@ -2792,6 +2792,9 @@ static int sd_resume(struct device *dev)
+ struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
+ int ret = 0;
+
++ if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
++ return 0;
++
+ if (!sdkp->device->manage_start_stop)
+ goto done;
+
diff --git a/releases/3.2.78/scsi_dh_rdac-always-retry-mode-select-on-command-lock-violation.patch b/releases/3.2.78/scsi_dh_rdac-always-retry-mode-select-on-command-lock-violation.patch
new file mode 100644
index 00000000..d7b67490
--- /dev/null
+++ b/releases/3.2.78/scsi_dh_rdac-always-retry-mode-select-on-command-lock-violation.patch
@@ -0,0 +1,40 @@
+From: Hannes Reinecke <hare@suse.de>
+Date: Fri, 22 Jan 2016 15:42:41 +0100
+Subject: scsi_dh_rdac: always retry MODE SELECT on command lock violation
+
+commit d2d06d4fe0f2cc2df9b17fefec96e6e1a1271d91 upstream.
+
+If MODE SELECT returns with sense '05/91/36' (command lock violation)
+it should always be retried without counting the number of retries.
+During an HBA upgrade or similar circumstances one might see a flood
+of MODE SELECT command from various HBAs, which will easily trigger
+the sense code and exceed the retry count.
+
+Signed-off-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
++++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
+@@ -573,7 +573,7 @@ static int mode_select_handle_sense(stru
+ /*
+ * Command Lock contention
+ */
+- err = SCSI_DH_RETRY;
++ err = SCSI_DH_IMM_RETRY;
+ break;
+ default:
+ break;
+@@ -623,6 +623,8 @@ retry:
+ err = mode_select_handle_sense(sdev, h->sense);
+ if (err == SCSI_DH_RETRY && retry_cnt--)
+ goto retry;
++ if (err == SCSI_DH_IMM_RETRY)
++ goto retry;
+ }
+ if (err == SCSI_DH_OK) {
+ h->state = RDAC_STATE_ACTIVE;
diff --git a/releases/3.2.78/sctp-allow-setting-sctp_sack_immediately-by-the-application.patch b/releases/3.2.78/sctp-allow-setting-sctp_sack_immediately-by-the-application.patch
new file mode 100644
index 00000000..02eb4109
--- /dev/null
+++ b/releases/3.2.78/sctp-allow-setting-sctp_sack_immediately-by-the-application.patch
@@ -0,0 +1,37 @@
+From: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Date: Fri, 22 Jan 2016 18:29:49 -0200
+Subject: sctp: allow setting SCTP_SACK_IMMEDIATELY by the application
+
+commit 27f7ed2b11d42ab6d796e96533c2076ec220affc upstream.
+
+This patch extends commit b93d6471748d ("sctp: implement the sender side
+for SACK-IMMEDIATELY extension") as it didn't white list
+SCTP_SACK_IMMEDIATELY on sctp_msghdr_parse(), causing it to be
+understood as an invalid flag and returning -EINVAL to the application.
+
+Note that the actual handling of the flag is already there in
+sctp_datamsg_from_user().
+
+https://tools.ietf.org/html/rfc7053#section-7
+
+Fixes: b93d6471748d ("sctp: implement the sender side for SACK-IMMEDIATELY extension")
+Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: Backported to 3.2: drop the second hunk as we don't have SCTP_SNDINFO
+ cmsg support]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -6241,6 +6241,7 @@ SCTP_STATIC int sctp_msghdr_parse(const
+ /* Minimally, validate the sinfo_flags. */
+ if (cmsgs->info->sinfo_flags &
+ ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
++ SCTP_SACK_IMMEDIATELY |
+ SCTP_ABORT | SCTP_EOF))
+ return -EINVAL;
+ break;
diff --git a/releases/3.2.78/sctp-translate-network-order-to-host-order-when-users-get-a-hmacid.patch b/releases/3.2.78/sctp-translate-network-order-to-host-order-when-users-get-a-hmacid.patch
new file mode 100644
index 00000000..4906c6ed
--- /dev/null
+++ b/releases/3.2.78/sctp-translate-network-order-to-host-order-when-users-get-a-hmacid.patch
@@ -0,0 +1,47 @@
+From: Xin Long <lucien.xin@gmail.com>
+Date: Wed, 3 Feb 2016 23:33:30 +0800
+Subject: sctp: translate network order to host order when users get a hmacid
+
+commit 7a84bd46647ff181eb2659fdc99590e6f16e501d upstream.
+
+Commit ed5a377d87dc ("sctp: translate host order to network order when
+setting a hmacid") corrected the hmacid byte-order when setting a hmacid.
+but the same issue also exists on getting a hmacid.
+
+We fix it by changing hmacids to host order when users get them with
+getsockopt.
+
+Fixes: Commit ed5a377d87dc ("sctp: translate host order to network order when setting a hmacid")
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ net/sctp/socket.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -5309,6 +5309,7 @@ static int sctp_getsockopt_hmac_ident(st
+ struct sctp_hmac_algo_param *hmacs;
+ __u16 data_len = 0;
+ u32 num_idents;
++ int i;
+
+ if (!sctp_auth_enable)
+ return -EACCES;
+@@ -5326,8 +5327,12 @@ static int sctp_getsockopt_hmac_ident(st
+ return -EFAULT;
+ if (put_user(num_idents, &p->shmac_num_idents))
+ return -EFAULT;
+- if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
+- return -EFAULT;
++ for (i = 0; i < num_idents; i++) {
++ __u16 hmacid = ntohs(hmacs->hmac_ids[i]);
++
++ if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16)))
++ return -EFAULT;
++ }
+ return 0;
+ }
+
diff --git a/releases/3.2.78/series b/releases/3.2.78/series
new file mode 100644
index 00000000..f4d3009a
--- /dev/null
+++ b/releases/3.2.78/series
@@ -0,0 +1,67 @@
+kvm-vmx-fix-mpx-detection.patch
+hrtimer-handle-remaining-time-proper-for-time_low_res.patch
+timerfd-handle-relative-timers-with-config_time_low_res-proper.patch
+posix-timers-handle-relative-timers-with-config_time_low_res-proper.patch
+itimers-handle-relative-timers-with-config_time_low_res-proper.patch
+usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch
+cdc-acm-exclude-samsung-phone-04e8-685d.patch
+af_unix-fix-struct-pid-memory-leak.patch
+pptp-fix-illegal-memory-access-caused-by-multiple-bind-s.patch
+sctp-allow-setting-sctp_sack_immediately-by-the-application.patch
+usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch
+usb-visor-fix-null-deref-at-probe.patch
+usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch
+usb-serial-option-adding-support-for-telit-le922.patch
+alsa-seq-fix-incorrect-sanity-check-at-snd_seq_oss_synth_cleanup.patch
+alsa-seq-degrade-the-error-message-for-too-many-opens.patch
+usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch
+pci-aer-flush-workqueue-on-device-remove-to-avoid-use-after-free.patch
+libata-disable-forced-ports_impl-for-ahci-1.3.patch
+virtio_pci-fix-use-after-free-on-release.patch
+rfkill-fix-rfkill_fop_read-wait_event-usage.patch
+perf-annotate-browser-fix-behaviour-of-shift-tab-with-nothing.patch
+scsi-fix-crashes-in-sd-and-sr-runtime-pm.patch
+tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
+crypto-shash-fix-has_key-setting.patch
+alsa-dummy-disable-switching-timer-backend-via-sysfs.patch
+drm-vmwgfx-respect-nomodeset.patch
+x86-mm-pat-avoid-truncation-when-converting-cpa-numpages-to-address.patch
+crypto-algif_hash-wait-for-crypto_ahash_init-to-complete.patch
+intel_scu_ipcutil-underflow-in-scu_reg_access.patch
+alsa-seq-fix-race-at-closing-in-virmidi-driver.patch
+alsa-rawmidi-remove-kernel-warning-for-null-user-space-buffer-check.patch
+alsa-pcm-fix-potential-deadlock-in-oss-emulation.patch
+alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch
+alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
+libata-fix-sff-host-state-machine-locking-while-polling.patch
+alsa-rawmidi-make-snd_rawmidi_transmit-race-free.patch
+alsa-rawmidi-fix-race-at-copying-updating-the-position.patch
+alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch
+revert-xhci-don-t-finish-a-td-if-we-get-a-short-transfer-event-mid.patch
+usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch
+xhci-fix-list-corruption-in-urb-dequeue-at-host-removal.patch
+tda1004x-only-update-the-frontend-properties-if-locked.patch
+alsa-timer-fix-leftover-link-at-closing.patch
+saa7134-alsa-only-frees-registered-sound-cards.patch
+scsi_dh_rdac-always-retry-mode-select-on-command-lock-violation.patch
+mm-vmstat-fix-wrong-wq-sleep-when-memory-reclaim-doesn-t-make-any.patch
+ocfs2-dlm-clear-refmap-bit-of-recovery-lock-while-doing-local.patch
+crypto-user-lock-crypto_alg_list-on-alg-dump.patch
+crypto-algif_skcipher-do-not-dereference-ctx-without-socket-lock.patch
+klist-fix-starting-point-removed-bug-in-klist-iterators.patch
+alsa-dummy-implement-timer-backend-switching-more-safely.patch
+alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
+arm-8517-1-icst-avoid-arithmetic-overflow-in-icst_hz.patch
+sctp-translate-network-order-to-host-order-when-users-get-a-hmacid.patch
+alsa-timer-fix-race-between-stop-and-interrupt.patch
+alsa-timer-fix-race-at-concurrent-reads.patch
+ahci-intel-dnv-device-ids-sata.patch
+arm-8519-1-icst-try-other-dividends-than-1.patch
+btrfs-properly-set-the-termination-value-of-ctx-pos-in-readdir.patch
+alsa-usb-audio-avoid-freeing-umidi-object-twice.patch
+unix-properly-account-for-fds-passed-over-unix-sockets.patch
+unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch
+pipe-limit-the-per-user-amount-of-pages-allocated-in-pipes.patch
+iw_cxgb3-fix-incorrectly-returning-error-on-success.patch
+pipe-fix-buffer-offset-after-partially-failed-read.patch
+sched-fix-__sched_setscheduler-vs-load-balancing-race.patch
diff --git a/releases/3.2.78/tda1004x-only-update-the-frontend-properties-if-locked.patch b/releases/3.2.78/tda1004x-only-update-the-frontend-properties-if-locked.patch
new file mode 100644
index 00000000..4a6a5c89
--- /dev/null
+++ b/releases/3.2.78/tda1004x-only-update-the-frontend-properties-if-locked.patch
@@ -0,0 +1,45 @@
+From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+Date: Wed, 3 Feb 2016 17:33:48 -0200
+Subject: [media] tda1004x: only update the frontend properties if locked
+
+commit e8beb02343e7582980c6705816cd957cf4f74c7a upstream.
+
+The tda1004x was updating the properties cache before locking.
+If the device is not locked, the data at the registers are just
+random values with no real meaning.
+
+This caused the driver to fail with libdvbv5, as such library
+calls GET_PROPERTY from time to time, in order to return the
+DVB stats.
+
+Tested with a saa7134 card 78:
+ ASUSTeK P7131 Dual, vendor PCI ID: 1043:4862
+
+Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+[bwh: Backported to 3.2: adjust filename]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/media/dvb/frontends/tda1004x.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/media/dvb/frontends/tda1004x.c
++++ b/drivers/media/dvb/frontends/tda1004x.c
+@@ -898,9 +898,18 @@ static int tda1004x_set_fe(struct dvb_fr
+ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
+ {
+ struct tda1004x_state* state = fe->demodulator_priv;
++ int status;
+
+ dprintk("%s\n", __func__);
+
++ status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
++ if (status == -1)
++ return -EIO;
++
++ /* Only update the properties cache if device is locked */
++ if (!(status & 8))
++ return 0;
++
+ // inversion status
+ fe_params->inversion = INVERSION_OFF;
+ if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
diff --git a/releases/3.2.78/timerfd-handle-relative-timers-with-config_time_low_res-proper.patch b/releases/3.2.78/timerfd-handle-relative-timers-with-config_time_low_res-proper.patch
new file mode 100644
index 00000000..74ade5d2
--- /dev/null
+++ b/releases/3.2.78/timerfd-handle-relative-timers-with-config_time_low_res-proper.patch
@@ -0,0 +1,40 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Thu, 14 Jan 2016 16:54:46 +0000
+Subject: timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper
+
+commit b62526ed11a1fe3861ab98d40b7fdab8981d788a upstream.
+
+Helge reported that a relative timer can return a remaining time larger than
+the programmed relative time on parisc and other architectures which have
+CONFIG_TIME_LOW_RES set. This happens because we add a jiffie to the resulting
+expiry time to prevent short timeouts.
+
+Use the new function hrtimer_expires_remaining_adjusted() to calculate the
+remaining time. It takes that extra added time into account for relative
+timers.
+
+Reported-and-tested-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: John Stultz <john.stultz@linaro.org>
+Cc: linux-m68k@lists.linux-m68k.org
+Cc: dhowells@redhat.com
+Link: http://lkml.kernel.org/r/20160114164159.354500742@linutronix.de
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ fs/timerfd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/timerfd.c
++++ b/fs/timerfd.c
+@@ -123,7 +123,7 @@ static ktime_t timerfd_get_remaining(str
+ {
+ ktime_t remaining;
+
+- remaining = hrtimer_expires_remaining(&ctx->tmr);
++ remaining = hrtimer_expires_remaining_adjusted(&ctx->tmr);
+ return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
+ }
+
diff --git a/releases/3.2.78/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch b/releases/3.2.78/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
new file mode 100644
index 00000000..e855e53a
--- /dev/null
+++ b/releases/3.2.78/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
@@ -0,0 +1,65 @@
+From: Peter Hurley <peter@hurleysoftware.com>
+Date: Sun, 10 Jan 2016 22:40:55 -0800
+Subject: tty: Fix unsafe ldisc reference via ioctl(TIOCGETD)
+
+commit 5c17c861a357e9458001f021a7afa7aab9937439 upstream.
+
+ioctl(TIOCGETD) retrieves the line discipline id directly from the
+ldisc because the line discipline id (c_line) in termios is untrustworthy;
+userspace may have set termios via ioctl(TCSETS*) without actually
+changing the line discipline via ioctl(TIOCSETD).
+
+However, directly accessing the current ldisc via tty->ldisc is
+unsafe; the ldisc ptr dereferenced may be stale if the line discipline
+is changing via ioctl(TIOCSETD) or hangup.
+
+Wait for the line discipline reference (just like read() or write())
+to retrieve the "current" line discipline id.
+
+Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/tty/tty_io.c | 24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
+
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -2475,6 +2475,28 @@ static int tiocsetd(struct tty_struct *t
+ }
+
+ /**
++ * tiocgetd - get line discipline
++ * @tty: tty device
++ * @p: pointer to user data
++ *
++ * Retrieves the line discipline id directly from the ldisc.
++ *
++ * Locking: waits for ldisc reference (in case the line discipline
++ * is changing or the tty is being hungup)
++ */
++
++static int tiocgetd(struct tty_struct *tty, int __user *p)
++{
++ struct tty_ldisc *ld;
++ int ret;
++
++ ld = tty_ldisc_ref_wait(tty);
++ ret = put_user(ld->ops->num, p);
++ tty_ldisc_deref(ld);
++ return ret;
++}
++
++/**
+ * send_break - performed time break
+ * @tty: device to break on
+ * @duration: timeout in mS
+@@ -2684,7 +2706,7 @@ long tty_ioctl(struct file *file, unsign
+ case TIOCGSID:
+ return tiocgsid(tty, real_tty, p);
+ case TIOCGETD:
+- return put_user(tty->ldisc->ops->num, (int __user *)p);
++ return tiocgetd(tty, p);
+ case TIOCSETD:
+ return tiocsetd(tty, p);
+ case TIOCVHANGUP:
diff --git a/releases/3.2.78/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch b/releases/3.2.78/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch
new file mode 100644
index 00000000..afa143b8
--- /dev/null
+++ b/releases/3.2.78/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch
@@ -0,0 +1,148 @@
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Date: Wed, 3 Feb 2016 02:11:03 +0100
+Subject: unix: correctly track in-flight fds in sending process user_struct
+
+commit 415e3d3e90ce9e18727e8843ae343eda5a58fad6 upstream.
+
+The commit referenced in the Fixes tag incorrectly accounted the number
+of in-flight fds over a unix domain socket to the original opener
+of the file-descriptor. This allows another process to arbitrary
+deplete the original file-openers resource limit for the maximum of
+open files. Instead the sending processes and its struct cred should
+be credited.
+
+To do so, we add a reference counted struct user_struct pointer to the
+scm_fp_list and use it to account for the number of inflight unix fds.
+
+Fixes: 712f4aad406bb1 ("unix: properly account for FDs passed over unix sockets")
+Reported-by: David Herrmann <dh.herrmann@gmail.com>
+Cc: David Herrmann <dh.herrmann@gmail.com>
+Cc: Willy Tarreau <w@1wt.eu>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ include/net/af_unix.h | 4 ++--
+ include/net/scm.h | 1 +
+ net/core/scm.c | 7 +++++++
+ net/unix/af_unix.c | 4 ++--
+ net/unix/garbage.c | 8 ++++----
+ 5 files changed, 16 insertions(+), 8 deletions(-)
+
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -6,8 +6,8 @@
+ #include <linux/mutex.h>
+ #include <net/sock.h>
+
+-extern void unix_inflight(struct file *fp);
+-extern void unix_notinflight(struct file *fp);
++extern void unix_inflight(struct user_struct *user, struct file *fp);
++extern void unix_notinflight(struct user_struct *user, struct file *fp);
+ extern void unix_gc(void);
+ extern void wait_for_unix_gc(void);
+ extern struct sock *unix_get_socket(struct file *filp);
+--- a/include/net/scm.h
++++ b/include/net/scm.h
+@@ -16,6 +16,7 @@ struct scm_fp_list {
+ struct list_head list;
+ short count;
+ short max;
++ struct user_struct *user;
+ struct file *fp[SCM_MAX_FD];
+ };
+
+--- a/net/core/scm.c
++++ b/net/core/scm.c
+@@ -80,6 +80,7 @@ static int scm_fp_copy(struct cmsghdr *c
+ *fplp = fpl;
+ fpl->count = 0;
+ fpl->max = SCM_MAX_FD;
++ fpl->user = NULL;
+ }
+ fpp = &fpl->fp[fpl->count];
+
+@@ -100,6 +101,10 @@ static int scm_fp_copy(struct cmsghdr *c
+ *fpp++ = file;
+ fpl->count++;
+ }
++
++ if (!fpl->user)
++ fpl->user = get_uid(current_user());
++
+ return num;
+ }
+
+@@ -124,6 +129,7 @@ void __scm_destroy(struct scm_cookie *sc
+ list_del(&fpl->list);
+ for (i=fpl->count-1; i>=0; i--)
+ fput(fpl->fp[i]);
++ free_uid(fpl->user);
+ kfree(fpl);
+ }
+
+@@ -342,6 +348,7 @@ struct scm_fp_list *scm_fp_dup(struct sc
+ for (i = 0; i < fpl->count; i++)
+ get_file(fpl->fp[i]);
+ new_fpl->max = new_fpl->count;
++ new_fpl->user = get_uid(fpl->user);
+ }
+ return new_fpl;
+ }
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1454,7 +1454,7 @@ static void unix_detach_fds(struct scm_c
+ UNIXCB(skb).fp = NULL;
+
+ for (i = scm->fp->count-1; i >= 0; i--)
+- unix_notinflight(scm->fp->fp[i]);
++ unix_notinflight(scm->fp->user, scm->fp->fp[i]);
+ }
+
+ static void unix_destruct_scm(struct sk_buff *skb)
+@@ -1520,7 +1520,7 @@ static int unix_attach_fds(struct scm_co
+ return -ENOMEM;
+
+ for (i = scm->fp->count - 1; i >= 0; i--)
+- unix_inflight(scm->fp->fp[i]);
++ unix_inflight(scm->fp->user, scm->fp->fp[i]);
+ return max_level;
+ }
+
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -122,7 +122,7 @@ struct sock *unix_get_socket(struct file
+ * descriptor if it is for an AF_UNIX socket.
+ */
+
+-void unix_inflight(struct file *fp)
++void unix_inflight(struct user_struct *user, struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
+
+@@ -138,11 +138,11 @@ void unix_inflight(struct file *fp)
+ }
+ unix_tot_inflight++;
+ }
+- fp->f_cred->user->unix_inflight++;
++ user->unix_inflight++;
+ spin_unlock(&unix_gc_lock);
+ }
+
+-void unix_notinflight(struct file *fp)
++void unix_notinflight(struct user_struct *user, struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
+
+@@ -155,7 +155,7 @@ void unix_notinflight(struct file *fp)
+ list_del_init(&u->link);
+ unix_tot_inflight--;
+ }
+- fp->f_cred->user->unix_inflight--;
++ user->unix_inflight--;
+ spin_unlock(&unix_gc_lock);
+ }
+
diff --git a/releases/3.2.78/unix-properly-account-for-fds-passed-over-unix-sockets.patch b/releases/3.2.78/unix-properly-account-for-fds-passed-over-unix-sockets.patch
new file mode 100644
index 00000000..410b0bf3
--- /dev/null
+++ b/releases/3.2.78/unix-properly-account-for-fds-passed-over-unix-sockets.patch
@@ -0,0 +1,131 @@
+From: willy tarreau <w@1wt.eu>
+Date: Sun, 10 Jan 2016 07:54:56 +0100
+Subject: unix: properly account for FDs passed over unix sockets
+
+commit 712f4aad406bb1ed67f3f98d04c044191f0ff593 upstream.
+
+It is possible for a process to allocate and accumulate far more FDs than
+the process' limit by sending them over a unix socket then closing them
+to keep the process' fd count low.
+
+This change addresses this problem by keeping track of the number of FDs
+in flight per user and preventing non-privileged processes from having
+more FDs in flight than their configured FD limit.
+
+Reported-by: socketpair@gmail.com
+Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Mitigates: CVE-2013-4312 (Linux 2.0+)
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[carnil: Backported to 3.16: adjust context]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ include/linux/sched.h | 1 +
+ net/unix/af_unix.c | 24 ++++++++++++++++++++----
+ net/unix/garbage.c | 13 ++++++++-----
+ 3 files changed, 29 insertions(+), 9 deletions(-)
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -709,6 +709,7 @@ struct user_struct {
+ unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */
+ #endif
+ unsigned long locked_shm; /* How many pages of mlocked shm ? */
++ unsigned long unix_inflight; /* How many files in flight in unix sockets */
+
+ #ifdef CONFIG_KEYS
+ struct key *uid_keyring; /* UID specific keyring */
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1472,6 +1472,21 @@ static void unix_destruct_scm(struct sk_
+ sock_wfree(skb);
+ }
+
++/*
++ * The "user->unix_inflight" variable is protected by the garbage
++ * collection lock, and we just read it locklessly here. If you go
++ * over the limit, there might be a tiny race in actually noticing
++ * it across threads. Tough.
++ */
++static inline bool too_many_unix_fds(struct task_struct *p)
++{
++ struct user_struct *user = current_user();
++
++ if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)))
++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
++ return false;
++}
++
+ #define MAX_RECURSION_LEVEL 4
+
+ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
+@@ -1480,6 +1495,9 @@ static int unix_attach_fds(struct scm_co
+ unsigned char max_level = 0;
+ int unix_sock_count = 0;
+
++ if (too_many_unix_fds(current))
++ return -ETOOMANYREFS;
++
+ for (i = scm->fp->count - 1; i >= 0; i--) {
+ struct sock *sk = unix_get_socket(scm->fp->fp[i]);
+
+@@ -1501,10 +1519,8 @@ static int unix_attach_fds(struct scm_co
+ if (!UNIXCB(skb).fp)
+ return -ENOMEM;
+
+- if (unix_sock_count) {
+- for (i = scm->fp->count - 1; i >= 0; i--)
+- unix_inflight(scm->fp->fp[i]);
+- }
++ for (i = scm->fp->count - 1; i >= 0; i--)
++ unix_inflight(scm->fp->fp[i]);
+ return max_level;
+ }
+
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -125,9 +125,11 @@ struct sock *unix_get_socket(struct file
+ void unix_inflight(struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
++
++ spin_lock(&unix_gc_lock);
++
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+- spin_lock(&unix_gc_lock);
+ if (atomic_long_inc_return(&u->inflight) == 1) {
+ BUG_ON(!list_empty(&u->link));
+ list_add_tail(&u->link, &gc_inflight_list);
+@@ -135,22 +137,26 @@ void unix_inflight(struct file *fp)
+ BUG_ON(list_empty(&u->link));
+ }
+ unix_tot_inflight++;
+- spin_unlock(&unix_gc_lock);
+ }
++ fp->f_cred->user->unix_inflight++;
++ spin_unlock(&unix_gc_lock);
+ }
+
+ void unix_notinflight(struct file *fp)
+ {
+ struct sock *s = unix_get_socket(fp);
++
++ spin_lock(&unix_gc_lock);
++
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+- spin_lock(&unix_gc_lock);
+ BUG_ON(list_empty(&u->link));
+ if (atomic_long_dec_and_test(&u->inflight))
+ list_del_init(&u->link);
+ unix_tot_inflight--;
+- spin_unlock(&unix_gc_lock);
+ }
++ fp->f_cred->user->unix_inflight--;
++ spin_unlock(&unix_gc_lock);
+ }
+
+ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
diff --git a/releases/3.2.78/usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch b/releases/3.2.78/usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch
new file mode 100644
index 00000000..8ab3d129
--- /dev/null
+++ b/releases/3.2.78/usb-cdc-acm-send-zero-packet-for-intel-7260-modem.patch
@@ -0,0 +1,49 @@
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Wed, 6 Jan 2016 15:10:04 +0800
+Subject: usb: cdc-acm: send zero packet for intel 7260 modem
+
+commit ffdb1e369a73b380fce95b05f8498d92c43842b4 upstream.
+
+For Intel 7260 modem, it is needed for host side to send zero
+packet if the BULK OUT size is equal to USB endpoint max packet
+length. Otherwise, modem side may still wait for more data and
+cannot give response to host side.
+
+Signed-off-by: Konrad Leszczynski <konrad.leszczynski@intel.com>
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/class/cdc-acm.c | 6 ++++++
+ drivers/usb/class/cdc-acm.h | 1 +
+ 2 files changed, 7 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -1237,6 +1237,8 @@ made_compressed_probe:
+ usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+ NULL, acm->writesize, acm_write_bulk, snd);
+ snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
++ if (quirks & SEND_ZERO_PACKET)
++ snd->urb->transfer_flags |= URB_ZERO_PACKET;
+ snd->instance = acm;
+ }
+
+@@ -1689,6 +1691,10 @@ static const struct usb_device_id acm_id
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_ACM_PROTO_AT_CDMA) },
+
++ { USB_DEVICE(0x1519, 0x0452), /* Intel 7260 modem */
++ .driver_info = SEND_ZERO_PACKET,
++ },
++
+ { }
+ };
+
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -129,3 +129,4 @@ struct acm {
+ #define NO_DATA_INTERFACE 16
+ #define IGNORE_DEVICE 32
+ #define CLEAR_HALT_CONDITIONS BIT(7)
++#define SEND_ZERO_PACKET BIT(8)
diff --git a/releases/3.2.78/usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch b/releases/3.2.78/usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch
new file mode 100644
index 00000000..59ab441d
--- /dev/null
+++ b/releases/3.2.78/usb-cp210x-add-id-for-iai-usb-to-rs485-adaptor.patch
@@ -0,0 +1,26 @@
+From: Peter Dedecker <peter.dedecker@hotmail.com>
+Date: Fri, 8 Jan 2016 12:34:41 +0100
+Subject: USB: cp210x: add ID for IAI USB to RS485 adaptor
+
+commit f487c54ddd544e1c9172cd510954f697b77b76e3 upstream.
+
+Added the USB serial console device ID for IAI Corp. RCB-CV-USB
+USB to RS485 adaptor.
+
+Signed-off-by: Peter Dedecker <peter.dedecker@hotmail.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/serial/cp210x.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -104,6 +104,7 @@ static const struct usb_device_id id_tab
+ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
+ { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
+ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
++ { USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */
+ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
+ { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
+ { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
diff --git a/releases/3.2.78/usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch b/releases/3.2.78/usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch
new file mode 100644
index 00000000..707f74e7
--- /dev/null
+++ b/releases/3.2.78/usb-serial-ftdi_sio-add-support-for-yaesu-scu-18-cable.patch
@@ -0,0 +1,39 @@
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Tue, 19 Jan 2016 23:43:13 -0800
+Subject: USB: serial: ftdi_sio: add support for Yaesu SCU-18 cable
+
+commit e03cdf22a2727c60307be6a729233edab3bfda9c upstream.
+
+Harald Linden reports that the ftdi_sio driver works properly for the
+Yaesu SCU-18 cable if the device ids are added to the driver. So let's
+add them.
+
+Reported-by: Harald Linden <harald.linden@7183.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/serial/ftdi_sio.c | 1 +
+ drivers/usb/serial/ftdi_sio_ids.h | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -848,6 +848,7 @@ static struct usb_device_id id_table_com
+ { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
++ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
+ { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
+
+ /* Papouch devices based on FTDI chip */
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -615,6 +615,7 @@
+ */
+ #define RATOC_VENDOR_ID 0x0584
+ #define RATOC_PRODUCT_ID_USB60F 0xb020
++#define RATOC_PRODUCT_ID_SCU18 0xb03a
+
+ /*
+ * Acton Research Corp.
diff --git a/releases/3.2.78/usb-serial-option-adding-support-for-telit-le922.patch b/releases/3.2.78/usb-serial-option-adding-support-for-telit-le922.patch
new file mode 100644
index 00000000..5e216614
--- /dev/null
+++ b/releases/3.2.78/usb-serial-option-adding-support-for-telit-le922.patch
@@ -0,0 +1,54 @@
+From: Daniele Palmas <dnlplm@gmail.com>
+Date: Tue, 12 Jan 2016 17:22:06 +0100
+Subject: USB: serial: option: Adding support for Telit LE922
+
+commit ff4e2494dc17b173468e1713fdf6237fd8578bc7 upstream.
+
+This patch adds support for two PIDs of LE922.
+
+Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/serial/option.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -269,6 +269,8 @@ static void option_instat_callback(struc
+ #define TELIT_PRODUCT_CC864_SINGLE 0x1006
+ #define TELIT_PRODUCT_DE910_DUAL 0x1010
+ #define TELIT_PRODUCT_UE910_V2 0x1012
++#define TELIT_PRODUCT_LE922_USBCFG0 0x1042
++#define TELIT_PRODUCT_LE922_USBCFG3 0x1043
+ #define TELIT_PRODUCT_LE920 0x1200
+ #define TELIT_PRODUCT_LE910 0x1201
+
+@@ -621,6 +623,16 @@ static const struct option_blacklist_inf
+ .reserved = BIT(1) | BIT(5),
+ };
+
++static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = {
++ .sendsetup = BIT(2),
++ .reserved = BIT(0) | BIT(1) | BIT(3),
++};
++
++static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = {
++ .sendsetup = BIT(0),
++ .reserved = BIT(1) | BIT(2) | BIT(3),
++};
++
+ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+@@ -1166,6 +1178,10 @@ static const struct usb_device_id option
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
++ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
+ .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
diff --git a/releases/3.2.78/usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch b/releases/3.2.78/usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch
new file mode 100644
index 00000000..87a0cda9
--- /dev/null
+++ b/releases/3.2.78/usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch
@@ -0,0 +1,34 @@
+From: Vladis Dronov <vdronov@redhat.com>
+Date: Tue, 12 Jan 2016 15:10:50 +0100
+Subject: USB: serial: visor: fix crash on detecting device without write_urbs
+
+commit cb3232138e37129e88240a98a1d2aba2187ff57c upstream.
+
+The visor driver crashes in clie_5_attach() when a specially crafted USB
+device without bulk-out endpoint is detected. This fix adds a check that
+the device has proper configuration expected by the driver.
+
+Reported-by: Ralf Spenneberg <ralf@spenneberg.net>
+Signed-off-by: Vladis Dronov <vdronov@redhat.com>
+Fixes: cfb8da8f69b8 ("USB: visor: fix initialisation of UX50/TH55 devices")
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/serial/visor.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -640,8 +640,10 @@ static int clie_5_attach(struct usb_seri
+ */
+
+ /* some sanity check */
+- if (serial->num_ports < 2)
+- return -1;
++ if (serial->num_bulk_out < 2) {
++ dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
++ return -ENODEV;
++ }
+
+ /* port 0 now uses the modified endpoint Address */
+ port = serial->port[0];
diff --git a/releases/3.2.78/usb-visor-fix-null-deref-at-probe.patch b/releases/3.2.78/usb-visor-fix-null-deref-at-probe.patch
new file mode 100644
index 00000000..fceab3d3
--- /dev/null
+++ b/releases/3.2.78/usb-visor-fix-null-deref-at-probe.patch
@@ -0,0 +1,34 @@
+From: Johan Hovold <johan@kernel.org>
+Date: Tue, 12 Jan 2016 12:05:20 +0100
+Subject: USB: visor: fix null-deref at probe
+
+commit cac9b50b0d75a1d50d6c056ff65c005f3224c8e0 upstream.
+
+Fix null-pointer dereference at probe should a (malicious) Treo device
+lack the expected endpoints.
+
+Specifically, the Treo port-setup hack was dereferencing the bulk-in and
+interrupt-in urbs without first making sure they had been allocated by
+core.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/serial/visor.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/usb/serial/visor.c
++++ b/drivers/usb/serial/visor.c
+@@ -587,6 +587,11 @@ static int treo_attach(struct usb_serial
+
+ dbg("%s", __func__);
+
++ if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
++ dev_err(&serial->interface->dev, "missing endpoints\n");
++ return -ENODEV;
++ }
++
+ /*
+ * It appears that Treos and Kyoceras want to use the
+ * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
diff --git a/releases/3.2.78/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch b/releases/3.2.78/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch
new file mode 100644
index 00000000..201326ef
--- /dev/null
+++ b/releases/3.2.78/usb-xhci-apply-xhci_pme_stuck_quirk-to-intel-broxton-m-platforms.patch
@@ -0,0 +1,36 @@
+From: Lu Baolu <baolu.lu@linux.intel.com>
+Date: Tue, 26 Jan 2016 17:50:08 +0200
+Subject: usb: xhci: apply XHCI_PME_STUCK_QUIRK to Intel Broxton-M platforms
+
+commit ccc04afb72cddbdf7c0e1c17e92886405a71b754 upstream.
+
+Intel Broxton M was verifed to require XHCI_PME_STUCK_QUIRK quirk as well.
+
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/host/xhci-pci.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -39,6 +39,7 @@
+ #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
+ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
+ #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f
++#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8
+
+ static const char hcd_name[] = "xhci_hcd";
+
+@@ -132,7 +133,8 @@ static void xhci_pci_quirks(struct devic
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
+- pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
++ pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
++ pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) {
+ xhci->quirks |= XHCI_PME_STUCK_QUIRK;
+ }
+ if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
diff --git a/releases/3.2.78/virtio_pci-fix-use-after-free-on-release.patch b/releases/3.2.78/virtio_pci-fix-use-after-free-on-release.patch
new file mode 100644
index 00000000..8b14402d
--- /dev/null
+++ b/releases/3.2.78/virtio_pci-fix-use-after-free-on-release.patch
@@ -0,0 +1,42 @@
+From: "Michael S. Tsirkin" <mst@redhat.com>
+Date: Thu, 14 Jan 2016 16:00:41 +0200
+Subject: virtio_pci: fix use after free on release
+
+commit 2989be09a8a9d62a785137586ad941f916e08f83 upstream.
+
+KASan detected a use-after-free error in virtio-pci remove code. In
+virtio_pci_remove(), vp_dev is still used after being freed in
+unregister_virtio_device() (in virtio_pci_release_dev() more
+precisely).
+
+To fix, keep a reference until cleanup is done.
+
+Fixes: 63bd62a08ca4 ("virtio_pci: defer kfree until release callback")
+Reported-by: Jerome Marchand <jmarchan@redhat.com>
+Cc: Sasha Levin <sasha.levin@oracle.com>
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Tested-by: Jerome Marchand <jmarchan@redhat.com>
+[bwh: Backported to 3.2: adjust filename]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/virtio/virtio_pci.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/virtio/virtio_pci.c
++++ b/drivers/virtio/virtio_pci.c
+@@ -698,6 +698,7 @@ out:
+ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
+ {
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
++ struct device *dev = get_device(&vp_dev->vdev.dev);
+
+ unregister_virtio_device(&vp_dev->vdev);
+
+@@ -706,6 +707,7 @@ static void __devexit virtio_pci_remove(
+ pci_iounmap(pci_dev, vp_dev->ioaddr);
+ pci_release_regions(pci_dev);
+ pci_disable_device(pci_dev);
++ put_device(dev);
+ }
+
+ #ifdef CONFIG_PM
diff --git a/releases/3.2.78/x86-mm-pat-avoid-truncation-when-converting-cpa-numpages-to-address.patch b/releases/3.2.78/x86-mm-pat-avoid-truncation-when-converting-cpa-numpages-to-address.patch
new file mode 100644
index 00000000..764c995b
--- /dev/null
+++ b/releases/3.2.78/x86-mm-pat-avoid-truncation-when-converting-cpa-numpages-to-address.patch
@@ -0,0 +1,83 @@
+From: Matt Fleming <matt@codeblueprint.co.uk>
+Date: Fri, 29 Jan 2016 11:36:10 +0000
+Subject: x86/mm/pat: Avoid truncation when converting cpa->numpages to address
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 742563777e8da62197d6cb4b99f4027f59454735 upstream.
+
+There are a couple of nasty truncation bugs lurking in the pageattr
+code that can be triggered when mapping EFI regions, e.g. when we pass
+a cpa->pgd pointer. Because cpa->numpages is a 32-bit value, shifting
+left by PAGE_SHIFT will truncate the resultant address to 32-bits.
+
+Viorel-Cătălin managed to trigger this bug on his Dell machine that
+provides a ~5GB EFI region which requires 1236992 pages to be mapped.
+When calling populate_pud() the end of the region gets calculated
+incorrectly in the following buggy expression,
+
+ end = start + (cpa->numpages << PAGE_SHIFT);
+
+And only 188416 pages are mapped. Next, populate_pud() gets invoked
+for a second time because of the loop in __change_page_attr_set_clr(),
+only this time no pages get mapped because shifting the remaining
+number of pages (1048576) by PAGE_SHIFT is zero. At which point the
+loop in __change_page_attr_set_clr() spins forever because we fail to
+map progress.
+
+Hitting this bug depends very much on the virtual address we pick to
+map the large region at and how many pages we map on the initial run
+through the loop. This explains why this issue was only recently hit
+with the introduction of commit
+
+ a5caa209ba9c ("x86/efi: Fix boot crash by mapping EFI memmap
+ entries bottom-up at runtime, instead of top-down")
+
+It's interesting to note that safe uses of cpa->numpages do exist in
+the pageattr code. If instead of shifting ->numpages we multiply by
+PAGE_SIZE, no truncation occurs because PAGE_SIZE is a UL value, and
+so the result is unsigned long.
+
+To avoid surprises when users try to convert very large cpa->numpages
+values to addresses, change the data type from 'int' to 'unsigned
+long', thereby making it suitable for shifting by PAGE_SHIFT without
+any type casting.
+
+The alternative would be to make liberal use of casting, but that is
+far more likely to cause problems in the future when someone adds more
+code and fails to cast properly; this bug was difficult enough to
+track down in the first place.
+
+Reported-and-tested-by: Viorel-Cătălin Răpițeanu <rapiteanu.catalin@gmail.com>
+Acked-by: Borislav Petkov <bp@alien8.de>
+Cc: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
+Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=110131
+Link: http://lkml.kernel.org/r/1454067370-10374-1-git-send-email-matt@codeblueprint.co.uk
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ arch/x86/mm/pageattr.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/mm/pageattr.c
++++ b/arch/x86/mm/pageattr.c
+@@ -32,7 +32,7 @@ struct cpa_data {
+ unsigned long *vaddr;
+ pgprot_t mask_set;
+ pgprot_t mask_clr;
+- int numpages;
++ unsigned long numpages;
+ int flags;
+ unsigned long pfn;
+ unsigned force_split : 1;
+@@ -820,7 +820,7 @@ static int __change_page_attr_set_clr(st
+ * CPA operation. Either a large page has been
+ * preserved or a single page update happened.
+ */
+- BUG_ON(cpa->numpages > numpages);
++ BUG_ON(cpa->numpages > numpages || !cpa->numpages);
+ numpages -= cpa->numpages;
+ if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
+ cpa->curpage++;
diff --git a/releases/3.2.78/xhci-fix-list-corruption-in-urb-dequeue-at-host-removal.patch b/releases/3.2.78/xhci-fix-list-corruption-in-urb-dequeue-at-host-removal.patch
new file mode 100644
index 00000000..6a169218
--- /dev/null
+++ b/releases/3.2.78/xhci-fix-list-corruption-in-urb-dequeue-at-host-removal.patch
@@ -0,0 +1,36 @@
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Tue, 26 Jan 2016 17:50:12 +0200
+Subject: xhci: Fix list corruption in urb dequeue at host removal
+
+commit 5c82171167adb8e4ac77b91a42cd49fb211a81a0 upstream.
+
+xhci driver frees data for all devices, both usb2 and and usb3 the
+first time usb_remove_hcd() is called, including td_list and and xhci_ring
+structures.
+
+When usb_remove_hcd() is called a second time for the second xhci bus it
+will try to dequeue all pending urbs, and touches td_list which is already
+freed for that endpoint.
+
+Reported-by: Joe Lawrence <joe.lawrence@stratus.com>
+Tested-by: Joe Lawrence <joe.lawrence@stratus.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ drivers/usb/host/xhci.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1533,7 +1533,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
+ if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
+ xhci_dbg(xhci, "HW died, freeing TD.\n");
+ urb_priv = urb->hcpriv;
+- for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
++ for (i = urb_priv->td_cnt;
++ i < urb_priv->length && xhci->devs[urb->dev->slot_id];
++ i++) {
+ td = urb_priv->td[i];
+ if (!list_empty(&td->td_list))
+ list_del_init(&td->td_list);