--- /dev/null
+From 191e885a2e130e639bb0c8ee350d7047294f2ce6 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@kernel.org>
+Date: Wed, 25 Jan 2017 10:31:52 -0800
+Subject: firmware: fix NULL pointer dereference in __fw_load_abort()
+
+From: Luis R. Rodriguez <mcgrof@kernel.org>
+
+commit 191e885a2e130e639bb0c8ee350d7047294f2ce6 upstream.
+
+Since commit 5d47ec02c37ea6 ("firmware: Correct handling of
+fw_state_wait() return value") fw_load_abort() could be called twice and
+lead us to a kernel crash. This happens only when the firmware fallback
+mechanism (regular or custom) is used. The fallback mechanism exposes a
+sysfs interface for userspace to upload a file and notify the kernel
+when the file is loaded and ready, or to cancel an upload by echo'ing -1
+into on the loading file:
+
+echo -n "-1" > /sys/$DEVPATH/loading
+
+This will call fw_load_abort(). Some distributions actually have a udev
+rule in place to *always* immediately cancel all firmware fallback
+mechanism requests (Debian), they have:
+
+ $ cat /lib/udev/rules.d/50-firmware.rules
+ # stub for immediately telling the kernel that userspace firmware loading
+ # failed; necessary to avoid long timeouts with CONFIG_FW_LOADER_USER_HELPER=y
+ SUBSYSTEM=="firmware", ACTION=="add", ATTR{loading}="-1
+
+Distributions with this udev rule would run into this crash only if the
+fallback mechanism is used. Since most distributions disable by default
+using the fallback mechanism (CONFIG_FW_LOADER_USER_HELPER_FALLBACK),
+this would typicaly mean only 2 drivers which *require* the fallback
+mechanism could typically incur a crash: drivers/firmware/dell_rbu.c and
+the drivers/leds/leds-lp55xx-common.c driver. Distributions enabling
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK by default are obviously more
+exposed to this crash.
+
+The crash happens because after commit 5b029624948d ("firmware: do not
+use fw_lock for fw_state protection") and subsequent fix commit
+5d47ec02c37ea6 ("firmware: Correct handling of fw_state_wait() return
+value") a race can happen between this cancelation and the firmware
+fw_state_wait_timeout() being woken up after a state change with which
+fw_load_abort() as that calls swake_up(). Upon error
+fw_state_wait_timeout() will also again call fw_load_abort() and trigger
+a null reference.
+
+At first glance we could just fix this with a !buf check on
+fw_load_abort() before accessing buf->fw_st, however there is a logical
+issue in having a state machine used for the fallback mechanism and
+preventing access from it once we abort as its inside the buf
+(buf->fw_st).
+
+The firmware_class.c code is setting the buf to NULL to annotate an
+abort has occurred. Replace this mechanism by simply using the state
+check instead. All the other code in place already uses similar checks
+for aborting as well so no further changes are needed.
+
+An oops can be reproduced with the new fw_fallback.sh fallback mechanism
+cancellation test. Either cancelling the fallback mechanism or the
+custom fallback mechanism triggers a crash.
+
+mcgrof@piggy ~/linux-next/tools/testing/selftests/firmware
+(git::20170111-fw-fixes)$ sudo ./fw_fallback.sh
+
+./fw_fallback.sh: timeout works
+./fw_fallback.sh: firmware comparison works
+./fw_fallback.sh: fallback mechanism works
+
+[ this then sits here when it is trying the cancellation test ]
+
+Kernel log:
+
+test_firmware: loading 'nope-test-firmware.bin'
+misc test_firmware: Direct firmware load for nope-test-firmware.bin failed with error -2
+misc test_firmware: Falling back to user helper
+BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
+IP: _request_firmware+0xa27/0xad0
+PGD 0
+
+Oops: 0000 [#1] SMP
+Modules linked in: test_firmware(E) ... etc ...
+CPU: 1 PID: 1396 Comm: fw_fallback.sh Tainted: G W E 4.10.0-rc3-next-20170111+ #30
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.10.1-0-g8891697-prebuilt.qemu-project.org 04/01/2014
+task: ffff9740b27f4340 task.stack: ffffbb15c0bc8000
+RIP: 0010:_request_firmware+0xa27/0xad0
+RSP: 0018:ffffbb15c0bcbd10 EFLAGS: 00010246
+RAX: 00000000fffffffe RBX: ffff9740afe5aa80 RCX: 0000000000000000
+RDX: ffff9740b27f4340 RSI: 0000000000000283 RDI: 0000000000000000
+RBP: ffffbb15c0bcbd90 R08: ffffbb15c0bcbcd8 R09: 0000000000000000
+R10: 0000000894a0d4b1 R11: 000000000000008c R12: ffffffffc0312480
+R13: 0000000000000005 R14: ffff9740b1c32400 R15: 00000000000003e8
+FS: 00007f8604422700(0000) GS:ffff9740bfc80000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000000000000038 CR3: 000000012164c000 CR4: 00000000000006e0
+Call Trace:
+ request_firmware+0x37/0x50
+ trigger_request_store+0x79/0xd0 [test_firmware]
+ dev_attr_store+0x18/0x30
+ sysfs_kf_write+0x37/0x40
+ kernfs_fop_write+0x110/0x1a0
+ __vfs_write+0x37/0x160
+ ? _cond_resched+0x1a/0x50
+ vfs_write+0xb5/0x1a0
+ SyS_write+0x55/0xc0
+ ? trace_do_page_fault+0x37/0xd0
+ entry_SYSCALL_64_fastpath+0x1e/0xad
+RIP: 0033:0x7f8603f49620
+RSP: 002b:00007fff6287b788 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
+RAX: ffffffffffffffda RBX: 000055c307b110a0 RCX: 00007f8603f49620
+RDX: 0000000000000016 RSI: 000055c3084d8a90 RDI: 0000000000000001
+RBP: 0000000000000016 R08: 000000000000c0ff R09: 000055c3084d6336
+R10: 000055c307b108b0 R11: 0000000000000246 R12: 000055c307b13c80
+R13: 000055c3084d6320 R14: 0000000000000000 R15: 00007fff6287b950
+Code: 9f 64 84 e8 9c 61 fe ff b8 f4 ff ff ff e9 6b f9 ff
+ff 48 c7 c7 40 6b 8d 84 89 45 a8 e8 43 84 18 00 49 8b be 00 03 00 00 8b
+45 a8 <83> 7f 38 02 74 08 e8 6e ec ff ff 8b 45 a8 49 c7 86 00 03 00 00
+RIP: _request_firmware+0xa27/0xad0 RSP: ffffbb15c0bcbd10
+CR2: 0000000000000038
+---[ end trace 6d94ac339c133e6f ]---
+
+Fixes: 5d47ec02c37e ("firmware: Correct handling of fw_state_wait() return value")
+Reported-and-Tested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
+Reported-and-Tested-by: Patrick Bruenn <p.bruenn@beckhoff.com>
+Reported-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/firmware_class.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/base/firmware_class.c
++++ b/drivers/base/firmware_class.c
+@@ -495,9 +495,6 @@ static void fw_load_abort(struct firmwar
+ struct firmware_buf *buf = fw_priv->buf;
+
+ __fw_load_abort(buf);
+-
+- /* avoid user action after loading abort */
+- fw_priv->buf = NULL;
+ }
+
+ #define is_fw_load_aborted(buf) \
+@@ -651,7 +648,7 @@ static ssize_t firmware_loading_store(st
+
+ mutex_lock(&fw_lock);
+ fw_buf = fw_priv->buf;
+- if (!fw_buf)
++ if (fw_state_is_aborted(&fw_buf->fw_st))
+ goto out;
+
+ switch (loading) {
usb-serial-qcserial-add-dell-dw5570-qdl.patch
usb-serial-pl2303-add-aten-device-id.patch
usb-add-quirk-for-worlde-easykey.25-midi-keyboard.patch
+usb-gadget-f_fs-assorted-buffer-overflow-checks.patch
+usb-serial-option-add-device-id-for-hp-lt2523-novatel-e371.patch
+x86-irq-make-irq-activate-operations-symmetric.patch
+firmware-fix-null-pointer-dereference-in-__fw_load_abort.patch
--- /dev/null
+From 83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Wed, 18 Jan 2017 00:57:44 +0000
+Subject: usb: gadget: f_fs: Assorted buffer overflow checks.
+
+From: Vincent Pelletier <plr.vincent@gmail.com>
+
+commit 83e526f2a2fa4b2e82b6bd3ddbb26b70acfa8947 upstream.
+
+OS descriptor head, when flagged as provided, is accessed without
+checking if it fits in provided buffer. Verify length before access.
+Also, there are other places where buffer length it checked
+after accessing offsets which are potentially past the end. Check
+buffer length before as well to fail cleanly.
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_fs.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_fs.c
++++ b/drivers/usb/gadget/function/f_fs.c
+@@ -2079,6 +2079,8 @@ static int __ffs_data_do_os_desc(enum ff
+ if (len < sizeof(*d) || h->interface >= ffs->interfaces_count)
+ return -EINVAL;
+ length = le32_to_cpu(d->dwSize);
++ if (len < length)
++ return -EINVAL;
+ type = le32_to_cpu(d->dwPropertyDataType);
+ if (type < USB_EXT_PROP_UNICODE ||
+ type > USB_EXT_PROP_UNICODE_MULTI) {
+@@ -2087,6 +2089,11 @@ static int __ffs_data_do_os_desc(enum ff
+ return -EINVAL;
+ }
+ pnl = le16_to_cpu(d->wPropertyNameLength);
++ if (length < 14 + pnl) {
++ pr_vdebug("invalid os descriptor length: %d pnl:%d (descriptor %d)\n",
++ length, pnl, type);
++ return -EINVAL;
++ }
+ pdl = le32_to_cpu(*(u32 *)((u8 *)data + 10 + pnl));
+ if (length != 14 + pnl + pdl) {
+ pr_vdebug("invalid os descriptor length: %d pnl:%d pdl:%d (descriptor %d)\n",
+@@ -2171,6 +2178,9 @@ static int __ffs_data_got_descs(struct f
+ }
+ }
+ if (flags & (1 << i)) {
++ if (len < 4) {
++ goto error;
++ }
+ os_descs_count = get_unaligned_le32(data);
+ data += 4;
+ len -= 4;
+@@ -2243,7 +2253,8 @@ static int __ffs_data_got_strings(struct
+
+ ENTER();
+
+- if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
++ if (unlikely(len < 16 ||
++ get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC ||
+ get_unaligned_le32(data + 4) != len))
+ goto error;
+ str_count = get_unaligned_le32(data + 8);
--- /dev/null
+From 5d03a2fd2292e71936c4235885c35ccc3c94695b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Tue, 24 Jan 2017 10:31:18 +0100
+Subject: USB: serial: option: add device ID for HP lt2523 (Novatel E371)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bjørn Mork <bjorn@mork.no>
+
+commit 5d03a2fd2292e71936c4235885c35ccc3c94695b upstream.
+
+Yet another laptop vendor rebranded Novatel E371.
+
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -2007,6 +2007,7 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD200, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_6802, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(WETELECOM_VENDOR_ID, WETELECOM_PRODUCT_WMD300, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d, 0xff, 0xff, 0xff) }, /* HP lt2523 (Novatel E371) */
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, option_ids);
--- /dev/null
+From aaaec6fc755447a1d056765b11b24d8ff2b81366 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 31 Jan 2017 19:03:21 +0100
+Subject: x86/irq: Make irq activate operations symmetric
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit aaaec6fc755447a1d056765b11b24d8ff2b81366 upstream.
+
+The recent commit which prevents double activation of interrupts unearthed
+interesting code in x86. The code (ab)uses irq_domain_activate_irq() to
+reconfigure an already activated interrupt. That trips over the prevention
+code now.
+
+Fix it by deactivating the interrupt before activating the new configuration.
+
+Fixes: 08d85f3ea99f1 "irqdomain: Avoid activating interrupts more than once"
+Reported-and-tested-by: Mike Galbraith <efault@gmx.de>
+Reported-and-tested-by: Borislav Petkov <bp@alien8.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
+Cc: Marc Zyngier <marc.zyngier@arm.com>
+Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1701311901580.3457@nanos
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/apic/io_apic.c | 2 ++
+ arch/x86/kernel/hpet.c | 1 +
+ 2 files changed, 3 insertions(+)
+
+--- a/arch/x86/kernel/apic/io_apic.c
++++ b/arch/x86/kernel/apic/io_apic.c
+@@ -2117,6 +2117,7 @@ static inline void __init check_timer(vo
+ if (idx != -1 && irq_trigger(idx))
+ unmask_ioapic_irq(irq_get_chip_data(0));
+ }
++ irq_domain_deactivate_irq(irq_data);
+ irq_domain_activate_irq(irq_data);
+ if (timer_irq_works()) {
+ if (disable_timer_pin_1 > 0)
+@@ -2138,6 +2139,7 @@ static inline void __init check_timer(vo
+ * legacy devices should be connected to IO APIC #0
+ */
+ replace_pin_at_irq_node(data, node, apic1, pin1, apic2, pin2);
++ irq_domain_deactivate_irq(irq_data);
+ irq_domain_activate_irq(irq_data);
+ legacy_pic->unmask(0);
+ if (timer_irq_works()) {
+--- a/arch/x86/kernel/hpet.c
++++ b/arch/x86/kernel/hpet.c
+@@ -351,6 +351,7 @@ static int hpet_resume(struct clock_even
+ } else {
+ struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
+
++ irq_domain_deactivate_irq(irq_get_irq_data(hdev->irq));
+ irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
+ disable_irq(hdev->irq);
+ irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));