]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.16-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Apr 2018 08:28:18 +0000 (10:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 20 Apr 2018 08:28:18 +0000 (10:28 +0200)
added patches:
acpi-hotplug-pci-check-presence-of-slot-itself-in-get_slot_status.patch
acpi-nfit-rework-nvdimm-leaf-method-detection.patch
acpi-video-add-quirk-to-force-acpi-video-backlight-on-samsung-670z5e.patch
cifs-add-sha512-secmech.patch
cifs-fix-memory-leak-in-smb2_open.patch
cifs-fix-sha512-check-in-cifs_crypto_secmech_release.patch
cifs-implement-v3.11-preauth-integrity.patch
cifs-refactor-crypto-shash-sdesc-allocation-free.patch
cifs-smbd-avoid-reconnect-lockup.patch
cifs-smbd-disconnect-transport-on-rdma-errors.patch
fix-smb3-encryption-breakage-when-config_debug_sg-y.patch
hid-i2c-hid-fix-size-check-and-type-usage.patch
i2c-i801-restore-configuration-at-shutdown.patch
i2c-i801-save-register-smbslvcmd-value-only-once.patch
regmap-fix-reversed-bounds-check-in-regmap_raw_write.patch
smb3-fix-root-directory-when-server-returns-inode-number-of-zero.patch
tree-connect-for-smb3.1.1-must-be-signed-for-non-encrypted-shares.patch
usb-dwc3-gadget-never-call-complete-from-ep_queue.patch
usb-dwc3-pci-properly-cleanup-resource.patch
usb-dwc3-prevent-setting-prtcap-to-otg-from-debugfs.patch
usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch
usb-gadget-f_midi-fixing-a-possible-double-free-in-f_midi.patch

23 files changed:
queue-4.16/acpi-hotplug-pci-check-presence-of-slot-itself-in-get_slot_status.patch [new file with mode: 0644]
queue-4.16/acpi-nfit-rework-nvdimm-leaf-method-detection.patch [new file with mode: 0644]
queue-4.16/acpi-video-add-quirk-to-force-acpi-video-backlight-on-samsung-670z5e.patch [new file with mode: 0644]
queue-4.16/cifs-add-sha512-secmech.patch [new file with mode: 0644]
queue-4.16/cifs-fix-memory-leak-in-smb2_open.patch [new file with mode: 0644]
queue-4.16/cifs-fix-sha512-check-in-cifs_crypto_secmech_release.patch [new file with mode: 0644]
queue-4.16/cifs-implement-v3.11-preauth-integrity.patch [new file with mode: 0644]
queue-4.16/cifs-refactor-crypto-shash-sdesc-allocation-free.patch [new file with mode: 0644]
queue-4.16/cifs-smbd-avoid-reconnect-lockup.patch [new file with mode: 0644]
queue-4.16/cifs-smbd-disconnect-transport-on-rdma-errors.patch [new file with mode: 0644]
queue-4.16/fix-smb3-encryption-breakage-when-config_debug_sg-y.patch [new file with mode: 0644]
queue-4.16/hid-i2c-hid-fix-size-check-and-type-usage.patch [new file with mode: 0644]
queue-4.16/i2c-i801-restore-configuration-at-shutdown.patch [new file with mode: 0644]
queue-4.16/i2c-i801-save-register-smbslvcmd-value-only-once.patch [new file with mode: 0644]
queue-4.16/regmap-fix-reversed-bounds-check-in-regmap_raw_write.patch [new file with mode: 0644]
queue-4.16/series
queue-4.16/smb3-fix-root-directory-when-server-returns-inode-number-of-zero.patch [new file with mode: 0644]
queue-4.16/tree-connect-for-smb3.1.1-must-be-signed-for-non-encrypted-shares.patch [new file with mode: 0644]
queue-4.16/usb-dwc3-gadget-never-call-complete-from-ep_queue.patch [new file with mode: 0644]
queue-4.16/usb-dwc3-pci-properly-cleanup-resource.patch [new file with mode: 0644]
queue-4.16/usb-dwc3-prevent-setting-prtcap-to-otg-from-debugfs.patch [new file with mode: 0644]
queue-4.16/usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch [new file with mode: 0644]
queue-4.16/usb-gadget-f_midi-fixing-a-possible-double-free-in-f_midi.patch [new file with mode: 0644]

diff --git a/queue-4.16/acpi-hotplug-pci-check-presence-of-slot-itself-in-get_slot_status.patch b/queue-4.16/acpi-hotplug-pci-check-presence-of-slot-itself-in-get_slot_status.patch
new file mode 100644 (file)
index 0000000..fcc0b26
--- /dev/null
@@ -0,0 +1,107 @@
+From 13d3047c81505cc0fb9bdae7810676e70523c8bf Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Mon, 12 Feb 2018 13:55:23 +0300
+Subject: ACPI / hotplug / PCI: Check presence of slot itself in get_slot_status()
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+commit 13d3047c81505cc0fb9bdae7810676e70523c8bf upstream.
+
+Mike Lothian reported that plugging in a USB-C device does not work
+properly in his Dell Alienware system.  This system has an Intel Alpine
+Ridge Thunderbolt controller providing USB-C functionality.  In these
+systems the USB controller (xHCI) is hotplugged whenever a device is
+connected to the port using ACPI-based hotplug.
+
+The ACPI description of the root port in question is as follows:
+
+  Device (RP01)
+  {
+      Name (_ADR, 0x001C0000)
+
+      Device (PXSX)
+      {
+          Name (_ADR, 0x02)
+
+          Method (_RMV, 0, NotSerialized)
+          {
+              // ...
+          }
+      }
+
+Here _ADR 0x02 means device 0, function 2 on the bus under root port (RP01)
+but that seems to be incorrect because device 0 is the upstream port of the
+Alpine Ridge PCIe switch and it has no functions other than 0 (the bridge
+itself).  When we get ACPI Notify() to the root port resulting from
+connecting a USB-C device, Linux tries to read PCI_VENDOR_ID from device 0,
+function 2 which of course always returns 0xffffffff because there is no
+such function and we never find the device.
+
+In Windows this works fine.
+
+Now, since we get ACPI Notify() to the root port and not to the PXSX device
+we should actually start our scan from there as well and not from the
+non-existent PXSX device.  Fix this by checking presence of the slot itself
+(function 0) if we fail to do that otherwise.
+
+While there use pci_bus_read_dev_vendor_id() in get_slot_status(), which is
+the recommended way to read Device and Vendor IDs of devices on PCI buses.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=198557
+Reported-by: Mike Lothian <mike@fireburn.co.uk>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/pci/hotplug/acpiphp_glue.c |   23 ++++++++++++++++-------
+ 1 file changed, 16 insertions(+), 7 deletions(-)
+
+--- a/drivers/pci/hotplug/acpiphp_glue.c
++++ b/drivers/pci/hotplug/acpiphp_glue.c
+@@ -541,6 +541,7 @@ static unsigned int get_slot_status(stru
+ {
+       unsigned long long sta = 0;
+       struct acpiphp_func *func;
++      u32 dvid;
+       list_for_each_entry(func, &slot->funcs, sibling) {
+               if (func->flags & FUNC_HAS_STA) {
+@@ -551,19 +552,27 @@ static unsigned int get_slot_status(stru
+                       if (ACPI_SUCCESS(status) && sta)
+                               break;
+               } else {
+-                      u32 dvid;
+-
+-                      pci_bus_read_config_dword(slot->bus,
+-                                                PCI_DEVFN(slot->device,
+-                                                          func->function),
+-                                                PCI_VENDOR_ID, &dvid);
+-                      if (dvid != 0xffffffff) {
++                      if (pci_bus_read_dev_vendor_id(slot->bus,
++                                      PCI_DEVFN(slot->device, func->function),
++                                      &dvid, 0)) {
+                               sta = ACPI_STA_ALL;
+                               break;
+                       }
+               }
+       }
++      if (!sta) {
++              /*
++               * Check for the slot itself since it may be that the
++               * ACPI slot is a device below PCIe upstream port so in
++               * that case it may not even be reachable yet.
++               */
++              if (pci_bus_read_dev_vendor_id(slot->bus,
++                              PCI_DEVFN(slot->device, 0), &dvid, 0)) {
++                      sta = ACPI_STA_ALL;
++              }
++      }
++
+       return (unsigned int)sta;
+ }
diff --git a/queue-4.16/acpi-nfit-rework-nvdimm-leaf-method-detection.patch b/queue-4.16/acpi-nfit-rework-nvdimm-leaf-method-detection.patch
new file mode 100644 (file)
index 0000000..4572a61
--- /dev/null
@@ -0,0 +1,131 @@
+From 466d1493ea830789a2f063f478aaed2e324f0d3d Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 28 Mar 2018 10:44:50 -0700
+Subject: acpi, nfit: rework NVDIMM leaf method detection
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 466d1493ea830789a2f063f478aaed2e324f0d3d upstream.
+
+Some BIOSen do not handle 0-byte transfer lengths for the _LSR and _LSW
+(label storage read/write) methods. This causes Linux to fallback to the
+deprecated _DSM path, or otherwise disable label support.
+
+Introduce acpi_nvdimm_has_method() to detect whether a method is
+available rather than calling the method, require _LSI and _LSR to be
+paired, and require read support before enabling write support.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 4b27db7e26cd ("acpi, nfit: add support for the _LS...")
+Suggested-by: Erik Schmauss <erik.schmauss@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/nfit/core.c |   41 +++++++++++++++++++++--------------------
+ drivers/acpi/nfit/nfit.h |    5 ++---
+ 2 files changed, 23 insertions(+), 23 deletions(-)
+
+--- a/drivers/acpi/nfit/core.c
++++ b/drivers/acpi/nfit/core.c
+@@ -196,7 +196,7 @@ static int xlat_nvdimm_status(struct nvd
+                * In the _LSI, _LSR, _LSW case the locked status is
+                * communicated via the read/write commands
+                */
+-              if (nfit_mem->has_lsi)
++              if (nfit_mem->has_lsr)
+                       break;
+               if (status >> 16 & ND_CONFIG_LOCKED)
+@@ -483,7 +483,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_desc
+                       min_t(u32, 256, in_buf.buffer.length), true);
+       /* call the BIOS, prefer the named methods over _DSM if available */
+-      if (nvdimm && cmd == ND_CMD_GET_CONFIG_SIZE && nfit_mem->has_lsi)
++      if (nvdimm && cmd == ND_CMD_GET_CONFIG_SIZE && nfit_mem->has_lsr)
+               out_obj = acpi_label_info(handle);
+       else if (nvdimm && cmd == ND_CMD_GET_CONFIG_DATA && nfit_mem->has_lsr) {
+               struct nd_cmd_get_config_data_hdr *p = buf;
+@@ -1654,12 +1654,23 @@ static void acpi_nvdimm_notify(acpi_hand
+       device_unlock(dev->parent);
+ }
++static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
++{
++      acpi_handle handle;
++      acpi_status status;
++
++      status = acpi_get_handle(adev->handle, method, &handle);
++
++      if (ACPI_SUCCESS(status))
++              return true;
++      return false;
++}
++
+ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
+               struct nfit_mem *nfit_mem, u32 device_handle)
+ {
+       struct acpi_device *adev, *adev_dimm;
+       struct device *dev = acpi_desc->dev;
+-      union acpi_object *obj;
+       unsigned long dsm_mask;
+       const guid_t *guid;
+       int i;
+@@ -1732,25 +1743,15 @@ static int acpi_nfit_add_dimm(struct acp
+                                       1ULL << i))
+                       set_bit(i, &nfit_mem->dsm_mask);
+-      obj = acpi_label_info(adev_dimm->handle);
+-      if (obj) {
+-              ACPI_FREE(obj);
+-              nfit_mem->has_lsi = 1;
+-              dev_dbg(dev, "%s: has _LSI\n", dev_name(&adev_dimm->dev));
+-      }
+-
+-      obj = acpi_label_read(adev_dimm->handle, 0, 0);
+-      if (obj) {
+-              ACPI_FREE(obj);
+-              nfit_mem->has_lsr = 1;
++      if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
++                      && acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
+               dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
++              nfit_mem->has_lsr = true;
+       }
+-      obj = acpi_label_write(adev_dimm->handle, 0, 0, NULL);
+-      if (obj) {
+-              ACPI_FREE(obj);
+-              nfit_mem->has_lsw = 1;
++      if (nfit_mem->has_lsr && acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
+               dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
++              nfit_mem->has_lsw = true;
+       }
+       return 0;
+@@ -1839,10 +1840,10 @@ static int acpi_nfit_register_dimms(stru
+                       cmd_mask |= nfit_mem->dsm_mask & NVDIMM_STANDARD_CMDMASK;
+               }
+-              if (nfit_mem->has_lsi)
++              if (nfit_mem->has_lsr) {
+                       set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
+-              if (nfit_mem->has_lsr)
+                       set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
++              }
+               if (nfit_mem->has_lsw)
+                       set_bit(ND_CMD_SET_CONFIG_DATA, &cmd_mask);
+--- a/drivers/acpi/nfit/nfit.h
++++ b/drivers/acpi/nfit/nfit.h
+@@ -171,9 +171,8 @@ struct nfit_mem {
+       struct resource *flush_wpq;
+       unsigned long dsm_mask;
+       int family;
+-      u32 has_lsi:1;
+-      u32 has_lsr:1;
+-      u32 has_lsw:1;
++      bool has_lsr;
++      bool has_lsw;
+ };
+ struct acpi_nfit_desc {
diff --git a/queue-4.16/acpi-video-add-quirk-to-force-acpi-video-backlight-on-samsung-670z5e.patch b/queue-4.16/acpi-video-add-quirk-to-force-acpi-video-backlight-on-samsung-670z5e.patch
new file mode 100644 (file)
index 0000000..2a43a40
--- /dev/null
@@ -0,0 +1,41 @@
+From bbf038618a24d72e2efc19146ef421bb1e1eda1a Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 19 Mar 2018 18:01:45 +0100
+Subject: ACPI / video: Add quirk to force acpi-video backlight on Samsung 670Z5E
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit bbf038618a24d72e2efc19146ef421bb1e1eda1a upstream.
+
+Just like many other Samsung models, the 670Z5E needs to use the acpi-video
+backlight interface rather then the native one for backlight control to
+work, add a quirk for this.
+
+Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1557060
+Cc: All applicable <stable@vger.kernel.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/video_detect.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -220,6 +220,15 @@ static const struct dmi_system_id video_
+               },
+       },
+       {
++       /* https://bugzilla.redhat.com/show_bug.cgi?id=1557060 */
++       .callback = video_detect_force_video,
++       .ident = "SAMSUNG 670Z5E",
++       .matches = {
++              DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
++              DMI_MATCH(DMI_PRODUCT_NAME, "670Z5E"),
++              },
++      },
++      {
+        /* https://bugzilla.redhat.com/show_bug.cgi?id=1094948 */
+        .callback = video_detect_force_video,
+        .ident = "SAMSUNG 730U3E/740U3E",
diff --git a/queue-4.16/cifs-add-sha512-secmech.patch b/queue-4.16/cifs-add-sha512-secmech.patch
new file mode 100644 (file)
index 0000000..1a136aa
--- /dev/null
@@ -0,0 +1,133 @@
+From 5fcd7f3f966f37f3f9a215af4cc1597fe338d0d5 Mon Sep 17 00:00:00 2001
+From: Aurelien Aptel <aaptel@suse.com>
+Date: Fri, 16 Feb 2018 19:19:28 +0100
+Subject: CIFS: add sha512 secmech
+
+From: Aurelien Aptel <aaptel@suse.com>
+
+commit 5fcd7f3f966f37f3f9a215af4cc1597fe338d0d5 upstream.
+
+* prepare for SMB3.11 pre-auth integrity
+* enable sha512 when SMB311 is enabled in Kconfig
+* add sha512 as a soft dependency
+
+Signed-off-by: Aurelien Aptel <aaptel@suse.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+CC: Stable <stable@vger.kernel.org>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/Kconfig         |    1 +
+ fs/cifs/cifsencrypt.c   |    7 +++++++
+ fs/cifs/cifsfs.c        |    1 +
+ fs/cifs/cifsglob.h      |    2 ++
+ fs/cifs/smb2proto.h     |    3 +++
+ fs/cifs/smb2transport.c |   30 ++++++++++++++++++++++++++++++
+ 6 files changed, 44 insertions(+)
+
+--- a/fs/cifs/Kconfig
++++ b/fs/cifs/Kconfig
+@@ -189,6 +189,7 @@ config CIFS_NFSD_EXPORT
+ config CIFS_SMB311
+       bool "SMB3.1.1 network file system support (Experimental)"
+       depends on CIFS
++      select CRYPTO_SHA512
+       help
+         This enables experimental support for the newest, SMB3.1.1, dialect.
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -829,6 +829,11 @@ cifs_crypto_secmech_release(struct TCP_S
+               server->secmech.md5 = NULL;
+       }
++      if (server->secmech.md5) {
++              crypto_free_shash(server->secmech.sha512);
++              server->secmech.sha512 = NULL;
++      }
++
+       if (server->secmech.hmacmd5) {
+               crypto_free_shash(server->secmech.hmacmd5);
+               server->secmech.hmacmd5 = NULL;
+@@ -852,4 +857,6 @@ cifs_crypto_secmech_release(struct TCP_S
+       server->secmech.sdeschmacmd5 = NULL;
+       kfree(server->secmech.sdescmd5);
+       server->secmech.sdescmd5 = NULL;
++      kfree(server->secmech.sdescsha512);
++      server->secmech.sdescsha512 = NULL;
+ }
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -1486,6 +1486,7 @@ MODULE_SOFTDEP("pre: nls");
+ MODULE_SOFTDEP("pre: aes");
+ MODULE_SOFTDEP("pre: cmac");
+ MODULE_SOFTDEP("pre: sha256");
++MODULE_SOFTDEP("pre: sha512");
+ MODULE_SOFTDEP("pre: aead2");
+ MODULE_SOFTDEP("pre: ccm");
+ module_init(init_cifs)
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -130,10 +130,12 @@ struct cifs_secmech {
+       struct crypto_shash *md5; /* md5 hash function */
+       struct crypto_shash *hmacsha256; /* hmac-sha256 hash function */
+       struct crypto_shash *cmacaes; /* block-cipher based MAC function */
++      struct crypto_shash *sha512; /* sha512 hash function */
+       struct sdesc *sdeschmacmd5;  /* ctxt to generate ntlmv2 hash, CR1 */
+       struct sdesc *sdescmd5; /* ctxt to generate cifs/smb signature */
+       struct sdesc *sdeschmacsha256;  /* ctxt to generate smb2 signature */
+       struct sdesc *sdesccmacaes;  /* ctxt to generate smb3 signature */
++      struct sdesc *sdescsha512; /* ctxt to generate smb3.11 signing key */
+       struct crypto_aead *ccmaesencrypt; /* smb3 encryption aead */
+       struct crypto_aead *ccmaesdecrypt; /* smb3 decryption aead */
+ };
+--- a/fs/cifs/smb2proto.h
++++ b/fs/cifs/smb2proto.h
+@@ -202,4 +202,7 @@ extern int smb3_validate_negotiate(const
+ extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
+                                       enum securityEnum);
++#ifdef CONFIG_CIFS_SMB311
++extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server);
++#endif
+ #endif                        /* _SMB2PROTO_H */
+--- a/fs/cifs/smb2transport.c
++++ b/fs/cifs/smb2transport.c
+@@ -70,6 +70,36 @@ err:
+       return rc;
+ }
++#ifdef CONFIG_CIFS_SMB311
++int
++smb311_crypto_shash_allocate(struct TCP_Server_Info *server)
++{
++      struct cifs_secmech *p = &server->secmech;
++      int rc = 0;
++
++      rc = cifs_alloc_hash("hmac(sha256)",
++                           &p->hmacsha256,
++                           &p->sdeschmacsha256);
++      if (rc)
++              return rc;
++
++      rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
++      if (rc)
++              goto err;
++
++      rc = cifs_alloc_hash("sha512", &p->sha512, &p->sdescsha512);
++      if (rc)
++              goto err;
++
++      return 0;
++
++err:
++      cifs_free_hash(&p->cmacaes, &p->sdesccmacaes);
++      cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
++      return rc;
++}
++#endif
++
+ static struct cifs_ses *
+ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
+ {
diff --git a/queue-4.16/cifs-fix-memory-leak-in-smb2_open.patch b/queue-4.16/cifs-fix-memory-leak-in-smb2_open.patch
new file mode 100644 (file)
index 0000000..bb6c6e1
--- /dev/null
@@ -0,0 +1,44 @@
+From b7a73c84eb96dabd6bb8e9d7c56f796d83efee8e Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+Date: Tue, 13 Feb 2018 15:42:30 +1100
+Subject: cifs: fix memory leak in SMB2_open()
+
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+
+commit b7a73c84eb96dabd6bb8e9d7c56f796d83efee8e upstream.
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2pdu.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1738,8 +1738,10 @@ SMB2_open(const unsigned int xid, struct
+               rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
+                                                &name_len,
+                                                tcon->treeName, path);
+-              if (rc)
++              if (rc) {
++                      cifs_small_buf_release(req);
+                       return rc;
++              }
+               req->NameLength = cpu_to_le16(name_len * 2);
+               uni_path_len = copy_size;
+               path = copy_path;
+@@ -1750,8 +1752,10 @@ SMB2_open(const unsigned int xid, struct
+               if (uni_path_len % 8 != 0) {
+                       copy_size = roundup(uni_path_len, 8);
+                       copy_path = kzalloc(copy_size, GFP_KERNEL);
+-                      if (!copy_path)
++                      if (!copy_path) {
++                              cifs_small_buf_release(req);
+                               return -ENOMEM;
++                      }
+                       memcpy((char *)copy_path, (const char *)path,
+                              uni_path_len);
+                       uni_path_len = copy_size;
diff --git a/queue-4.16/cifs-fix-sha512-check-in-cifs_crypto_secmech_release.patch b/queue-4.16/cifs-fix-sha512-check-in-cifs_crypto_secmech_release.patch
new file mode 100644 (file)
index 0000000..e447e53
--- /dev/null
@@ -0,0 +1,35 @@
+From 70e80655f58e17a2e38e577e1b4fa7a8c99619a0 Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
+Date: Mon, 19 Feb 2018 11:11:13 -0600
+Subject: CIFS: fix sha512 check in cifs_crypto_secmech_release
+
+From: Gustavo A. R. Silva <gustavo@embeddedor.com>
+
+commit 70e80655f58e17a2e38e577e1b4fa7a8c99619a0 upstream.
+
+It seems this is a copy-paste error and that the proper variable to use
+in this particular case is _sha512_ instead of _md5_.
+
+Addresses-Coverity-ID: 1465358 ("Copy-paste error")
+Fixes: 1c6614d229e7 ("CIFS: add sha512 secmech")
+Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
+Reviewed-by: Aurelien Aptel <aaptel@suse.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsencrypt.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -829,7 +829,7 @@ cifs_crypto_secmech_release(struct TCP_S
+               server->secmech.md5 = NULL;
+       }
+-      if (server->secmech.md5) {
++      if (server->secmech.sha512) {
+               crypto_free_shash(server->secmech.sha512);
+               server->secmech.sha512 = NULL;
+       }
diff --git a/queue-4.16/cifs-implement-v3.11-preauth-integrity.patch b/queue-4.16/cifs-implement-v3.11-preauth-integrity.patch
new file mode 100644 (file)
index 0000000..7dd59b5
--- /dev/null
@@ -0,0 +1,237 @@
+From 8bd68c6e47abff34e412a0c68cecb4a36bf0198b Mon Sep 17 00:00:00 2001
+From: Aurelien Aptel <aaptel@suse.com>
+Date: Fri, 16 Feb 2018 19:19:29 +0100
+Subject: CIFS: implement v3.11 preauth integrity
+
+From: Aurelien Aptel <aaptel@suse.com>
+
+commit 8bd68c6e47abff34e412a0c68cecb4a36bf0198b upstream.
+
+SMB3.11 clients must implement pre-authentification integrity.
+
+* new mechanism to certify requests/responses happening before Tree
+  Connect.
+* supersedes VALIDATE_NEGOTIATE
+* fixes signing for SMB3.11
+
+Signed-off-by: Aurelien Aptel <aaptel@suse.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+CC: Stable <stable@vger.kernel.org>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsglob.h  |    5 ++--
+ fs/cifs/smb2misc.c  |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ fs/cifs/smb2pdu.c   |   25 ++++++++++++++++++++
+ fs/cifs/smb2pdu.h   |    1 
+ fs/cifs/smb2proto.h |    2 +
+ fs/cifs/transport.c |   17 +++++++++++++
+ 6 files changed, 112 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -675,7 +675,8 @@ struct TCP_Server_Info {
+       unsigned int    max_read;
+       unsigned int    max_write;
+ #ifdef CONFIG_CIFS_SMB311
+-      __u8    preauth_sha_hash[64]; /* save initital negprot hash */
++       /* save initital negprot hash */
++      __u8    preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
+ #endif /* 3.1.1 */
+       struct delayed_work reconnect; /* reconnect workqueue job */
+       struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
+@@ -864,7 +865,7 @@ struct cifs_ses {
+       __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
+       __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
+ #ifdef CONFIG_CIFS_SMB311
+-      __u8 preauth_sha_hash[64];
++      __u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
+ #endif /* 3.1.1 */
+ };
+--- a/fs/cifs/smb2misc.c
++++ b/fs/cifs/smb2misc.c
+@@ -706,3 +706,67 @@ smb2_handle_cancelled_mid(char *buffer,
+       return 0;
+ }
++
++#ifdef CONFIG_CIFS_SMB311
++/**
++ * smb311_update_preauth_hash - update @ses hash with the packet data in @iov
++ *
++ * Assumes @iov does not contain the rfc1002 length and iov[0] has the
++ * SMB2 header.
++ */
++int
++smb311_update_preauth_hash(struct cifs_ses *ses, struct kvec *iov, int nvec)
++{
++      int i, rc;
++      struct sdesc *d;
++      struct smb2_sync_hdr *hdr;
++
++      if (ses->server->tcpStatus == CifsGood) {
++              /* skip non smb311 connections */
++              if (ses->server->dialect != SMB311_PROT_ID)
++                      return 0;
++
++              /* skip last sess setup response */
++              hdr = (struct smb2_sync_hdr *)iov[0].iov_base;
++              if (hdr->Flags & SMB2_FLAGS_SIGNED)
++                      return 0;
++      }
++
++      rc = smb311_crypto_shash_allocate(ses->server);
++      if (rc)
++              return rc;
++
++      d = ses->server->secmech.sdescsha512;
++      rc = crypto_shash_init(&d->shash);
++      if (rc) {
++              cifs_dbg(VFS, "%s: could not init sha512 shash\n", __func__);
++              return rc;
++      }
++
++      rc = crypto_shash_update(&d->shash, ses->preauth_sha_hash,
++                               SMB2_PREAUTH_HASH_SIZE);
++      if (rc) {
++              cifs_dbg(VFS, "%s: could not update sha512 shash\n", __func__);
++              return rc;
++      }
++
++      for (i = 0; i < nvec; i++) {
++              rc = crypto_shash_update(&d->shash,
++                                       iov[i].iov_base, iov[i].iov_len);
++              if (rc) {
++                      cifs_dbg(VFS, "%s: could not update sha512 shash\n",
++                               __func__);
++                      return rc;
++              }
++      }
++
++      rc = crypto_shash_final(&d->shash, ses->preauth_sha_hash);
++      if (rc) {
++              cifs_dbg(VFS, "%s: could not finalize sha512 shash\n",
++                       __func__);
++              return rc;
++      }
++
++      return 0;
++}
++#endif
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -453,6 +453,10 @@ SMB2_negotiate(const unsigned int xid, s
+               return rc;
+       req->sync_hdr.SessionId = 0;
++#ifdef CONFIG_CIFS_SMB311
++      memset(server->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
++      memset(ses->preauth_sha_hash, 0, SMB2_PREAUTH_HASH_SIZE);
++#endif
+       if (strcmp(ses->server->vals->version_string,
+                  SMB3ANY_VERSION_STRING) == 0) {
+@@ -564,6 +568,15 @@ SMB2_negotiate(const unsigned int xid, s
+       /* BB: add check that dialect was valid given dialect(s) we asked for */
++#ifdef CONFIG_CIFS_SMB311
++      /*
++       * Keep a copy of the hash after negprot. This hash will be
++       * the starting hash value for all sessions made from this
++       * server.
++       */
++      memcpy(server->preauth_sha_hash, ses->preauth_sha_hash,
++             SMB2_PREAUTH_HASH_SIZE);
++#endif
+       /* SMB2 only has an extended negflavor */
+       server->negflavor = CIFS_NEGFLAVOR_EXTENDED;
+       /* set it to the maximum buffer size value we can send with 1 credit */
+@@ -621,6 +634,10 @@ int smb3_validate_negotiate(const unsign
+               return 0;
+ #endif
++      /* In SMB3.11 preauth integrity supersedes validate negotiate */
++      if (tcon->ses->server->dialect == SMB311_PROT_ID)
++              return 0;
++
+       /*
+        * validation ioctl must be signed, so no point sending this if we
+        * can not sign it (ie are not known user).  Even if signing is not
+@@ -1148,6 +1165,14 @@ SMB2_sess_setup(const unsigned int xid,
+       sess_data->buf0_type = CIFS_NO_BUFFER;
+       sess_data->nls_cp = (struct nls_table *) nls_cp;
++#ifdef CONFIG_CIFS_SMB311
++      /*
++       * Initialize the session hash with the server one.
++       */
++      memcpy(ses->preauth_sha_hash, ses->server->preauth_sha_hash,
++             SMB2_PREAUTH_HASH_SIZE);
++#endif
++
+       while (sess_data->func)
+               sess_data->func(sess_data);
+--- a/fs/cifs/smb2pdu.h
++++ b/fs/cifs/smb2pdu.h
+@@ -264,6 +264,7 @@ struct smb2_negotiate_req {
+ #define SMB311_SALT_SIZE                      32
+ /* Hash Algorithm Types */
+ #define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
++#define SMB2_PREAUTH_HASH_SIZE 64
+ struct smb2_preauth_neg_context {
+       __le16  ContextType; /* 1 */
+--- a/fs/cifs/smb2proto.h
++++ b/fs/cifs/smb2proto.h
+@@ -204,5 +204,7 @@ extern enum securityEnum smb2_select_sec
+                                       enum securityEnum);
+ #ifdef CONFIG_CIFS_SMB311
+ extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server);
++extern int smb311_update_preauth_hash(struct cifs_ses *ses,
++                                    struct kvec *iov, int nvec);
+ #endif
+ #endif                        /* _SMB2PROTO_H */
+--- a/fs/cifs/transport.c
++++ b/fs/cifs/transport.c
+@@ -37,6 +37,7 @@
+ #include "cifsglob.h"
+ #include "cifsproto.h"
+ #include "cifs_debug.h"
++#include "smb2proto.h"
+ #include "smbdirect.h"
+ /* Max number of iovectors we can use off the stack when sending requests. */
+@@ -751,6 +752,12 @@ cifs_send_recv(const unsigned int xid, s
+       if (rc < 0)
+               goto out;
++#ifdef CONFIG_CIFS_SMB311
++      if (ses->status == CifsNew)
++              smb311_update_preauth_hash(ses, rqst->rq_iov+1,
++                                         rqst->rq_nvec-1);
++#endif
++
+       if (timeout == CIFS_ASYNC_OP)
+               goto out;
+@@ -789,6 +796,16 @@ cifs_send_recv(const unsigned int xid, s
+       else
+               *resp_buf_type = CIFS_SMALL_BUFFER;
++#ifdef CONFIG_CIFS_SMB311
++      if (ses->status == CifsNew) {
++              struct kvec iov = {
++                      .iov_base = buf + 4,
++                      .iov_len = get_rfc1002_length(buf)
++              };
++              smb311_update_preauth_hash(ses, &iov, 1);
++      }
++#endif
++
+       credits = ses->server->ops->get_credits(midQ);
+       rc = ses->server->ops->check_receive(midQ, ses->server,
diff --git a/queue-4.16/cifs-refactor-crypto-shash-sdesc-allocation-free.patch b/queue-4.16/cifs-refactor-crypto-shash-sdesc-allocation-free.patch
new file mode 100644 (file)
index 0000000..0793f96
--- /dev/null
@@ -0,0 +1,397 @@
+From 82fb82be05585426405667dd5f0510aa953ba439 Mon Sep 17 00:00:00 2001
+From: Aurelien Aptel <aaptel@suse.com>
+Date: Fri, 16 Feb 2018 19:19:27 +0100
+Subject: CIFS: refactor crypto shash/sdesc allocation&free
+
+From: Aurelien Aptel <aaptel@suse.com>
+
+commit 82fb82be05585426405667dd5f0510aa953ba439 upstream.
+
+shash and sdesc and always allocated and freed together.
+* abstract this in new functions cifs_alloc_hash() and cifs_free_hash().
+* make smb2/3 crypto allocation independent from each other.
+
+Signed-off-by: Aurelien Aptel <aaptel@suse.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsencrypt.c   |   78 ++++--------------------------------------------
+ fs/cifs/cifsproto.h     |    5 +++
+ fs/cifs/link.c          |   25 +++------------
+ fs/cifs/misc.c          |   54 +++++++++++++++++++++++++++++++++
+ fs/cifs/smb2transport.c |   75 +++++++++-------------------------------------
+ fs/cifs/smbencrypt.c    |   25 +++------------
+ 6 files changed, 91 insertions(+), 171 deletions(-)
+
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -36,37 +36,6 @@
+ #include <crypto/skcipher.h>
+ #include <crypto/aead.h>
+-static int
+-cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server)
+-{
+-      int rc;
+-      unsigned int size;
+-
+-      if (server->secmech.sdescmd5 != NULL)
+-              return 0; /* already allocated */
+-
+-      server->secmech.md5 = crypto_alloc_shash("md5", 0, 0);
+-      if (IS_ERR(server->secmech.md5)) {
+-              cifs_dbg(VFS, "could not allocate crypto md5\n");
+-              rc = PTR_ERR(server->secmech.md5);
+-              server->secmech.md5 = NULL;
+-              return rc;
+-      }
+-
+-      size = sizeof(struct shash_desc) +
+-                      crypto_shash_descsize(server->secmech.md5);
+-      server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL);
+-      if (!server->secmech.sdescmd5) {
+-              crypto_free_shash(server->secmech.md5);
+-              server->secmech.md5 = NULL;
+-              return -ENOMEM;
+-      }
+-      server->secmech.sdescmd5->shash.tfm = server->secmech.md5;
+-      server->secmech.sdescmd5->shash.flags = 0x0;
+-
+-      return 0;
+-}
+-
+ int __cifs_calc_signature(struct smb_rqst *rqst,
+                       struct TCP_Server_Info *server, char *signature,
+                       struct shash_desc *shash)
+@@ -132,13 +101,10 @@ static int cifs_calc_signature(struct sm
+       if (!rqst->rq_iov || !signature || !server)
+               return -EINVAL;
+-      if (!server->secmech.sdescmd5) {
+-              rc = cifs_crypto_shash_md5_allocate(server);
+-              if (rc) {
+-                      cifs_dbg(VFS, "%s: Can't alloc md5 crypto\n", __func__);
+-                      return -1;
+-              }
+-      }
++      rc = cifs_alloc_hash("md5", &server->secmech.md5,
++                           &server->secmech.sdescmd5);
++      if (rc)
++              return -1;
+       rc = crypto_shash_init(&server->secmech.sdescmd5->shash);
+       if (rc) {
+@@ -663,37 +629,6 @@ CalcNTLMv2_response(const struct cifs_se
+       return rc;
+ }
+-static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server)
+-{
+-      int rc;
+-      unsigned int size;
+-
+-      /* check if already allocated */
+-      if (server->secmech.sdeschmacmd5)
+-              return 0;
+-
+-      server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0);
+-      if (IS_ERR(server->secmech.hmacmd5)) {
+-              cifs_dbg(VFS, "could not allocate crypto hmacmd5\n");
+-              rc = PTR_ERR(server->secmech.hmacmd5);
+-              server->secmech.hmacmd5 = NULL;
+-              return rc;
+-      }
+-
+-      size = sizeof(struct shash_desc) +
+-                      crypto_shash_descsize(server->secmech.hmacmd5);
+-      server->secmech.sdeschmacmd5 = kmalloc(size, GFP_KERNEL);
+-      if (!server->secmech.sdeschmacmd5) {
+-              crypto_free_shash(server->secmech.hmacmd5);
+-              server->secmech.hmacmd5 = NULL;
+-              return -ENOMEM;
+-      }
+-      server->secmech.sdeschmacmd5->shash.tfm = server->secmech.hmacmd5;
+-      server->secmech.sdeschmacmd5->shash.flags = 0x0;
+-
+-      return 0;
+-}
+-
+ int
+ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
+ {
+@@ -757,9 +692,10 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, c
+       mutex_lock(&ses->server->srv_mutex);
+-      rc = crypto_hmacmd5_alloc(ses->server);
++      rc = cifs_alloc_hash("hmac(md5)",
++                           &ses->server->secmech.hmacmd5,
++                           &ses->server->secmech.sdeschmacmd5);
+       if (rc) {
+-              cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
+               goto unlock;
+       }
+--- a/fs/cifs/cifsproto.h
++++ b/fs/cifs/cifsproto.h
+@@ -542,4 +542,9 @@ enum securityEnum cifs_select_sectype(st
+ struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
+ void cifs_aio_ctx_release(struct kref *refcount);
+ int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
++
++int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
++                  struct sdesc **sdesc);
++void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
++
+ #endif                        /* _CIFSPROTO_H */
+--- a/fs/cifs/link.c
++++ b/fs/cifs/link.c
+@@ -50,25 +50,12 @@ static int
+ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
+ {
+       int rc;
+-      unsigned int size;
+-      struct crypto_shash *md5;
+-      struct sdesc *sdescmd5;
++      struct crypto_shash *md5 = NULL;
++      struct sdesc *sdescmd5 = NULL;
+-      md5 = crypto_alloc_shash("md5", 0, 0);
+-      if (IS_ERR(md5)) {
+-              rc = PTR_ERR(md5);
+-              cifs_dbg(VFS, "%s: Crypto md5 allocation error %d\n",
+-                       __func__, rc);
+-              return rc;
+-      }
+-      size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
+-      sdescmd5 = kmalloc(size, GFP_KERNEL);
+-      if (!sdescmd5) {
+-              rc = -ENOMEM;
++      rc = cifs_alloc_hash("md5", &md5, &sdescmd5);
++      if (rc)
+               goto symlink_hash_err;
+-      }
+-      sdescmd5->shash.tfm = md5;
+-      sdescmd5->shash.flags = 0x0;
+       rc = crypto_shash_init(&sdescmd5->shash);
+       if (rc) {
+@@ -85,9 +72,7 @@ symlink_hash(unsigned int link_len, cons
+               cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
+ symlink_hash_err:
+-      crypto_free_shash(md5);
+-      kfree(sdescmd5);
+-
++      cifs_free_hash(&md5, &sdescmd5);
+       return rc;
+ }
+--- a/fs/cifs/misc.c
++++ b/fs/cifs/misc.c
+@@ -848,3 +848,57 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *
+       iov_iter_bvec(&ctx->iter, ITER_BVEC | rw, ctx->bv, npages, ctx->len);
+       return 0;
+ }
++
++/**
++ * cifs_alloc_hash - allocate hash and hash context together
++ *
++ * The caller has to make sure @sdesc is initialized to either NULL or
++ * a valid context. Both can be freed via cifs_free_hash().
++ */
++int
++cifs_alloc_hash(const char *name,
++              struct crypto_shash **shash, struct sdesc **sdesc)
++{
++      int rc = 0;
++      size_t size;
++
++      if (*sdesc != NULL)
++              return 0;
++
++      *shash = crypto_alloc_shash(name, 0, 0);
++      if (IS_ERR(*shash)) {
++              cifs_dbg(VFS, "could not allocate crypto %s\n", name);
++              rc = PTR_ERR(*shash);
++              *shash = NULL;
++              *sdesc = NULL;
++              return rc;
++      }
++
++      size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash);
++      *sdesc = kmalloc(size, GFP_KERNEL);
++      if (*sdesc == NULL) {
++              cifs_dbg(VFS, "no memory left to allocate crypto %s\n", name);
++              crypto_free_shash(*shash);
++              *shash = NULL;
++              return -ENOMEM;
++      }
++
++      (*sdesc)->shash.tfm = *shash;
++      (*sdesc)->shash.flags = 0x0;
++      return 0;
++}
++
++/**
++ * cifs_free_hash - free hash and hash context together
++ *
++ * Freeing a NULL hash or context is safe.
++ */
++void
++cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
++{
++      kfree(*sdesc);
++      *sdesc = NULL;
++      if (*shash)
++              crypto_free_shash(*shash);
++      *shash = NULL;
++}
+--- a/fs/cifs/smb2transport.c
++++ b/fs/cifs/smb2transport.c
+@@ -43,76 +43,31 @@
+ static int
+ smb2_crypto_shash_allocate(struct TCP_Server_Info *server)
+ {
+-      int rc;
+-      unsigned int size;
+-
+-      if (server->secmech.sdeschmacsha256 != NULL)
+-              return 0; /* already allocated */
+-
+-      server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0);
+-      if (IS_ERR(server->secmech.hmacsha256)) {
+-              cifs_dbg(VFS, "could not allocate crypto hmacsha256\n");
+-              rc = PTR_ERR(server->secmech.hmacsha256);
+-              server->secmech.hmacsha256 = NULL;
+-              return rc;
+-      }
+-
+-      size = sizeof(struct shash_desc) +
+-                      crypto_shash_descsize(server->secmech.hmacsha256);
+-      server->secmech.sdeschmacsha256 = kmalloc(size, GFP_KERNEL);
+-      if (!server->secmech.sdeschmacsha256) {
+-              crypto_free_shash(server->secmech.hmacsha256);
+-              server->secmech.hmacsha256 = NULL;
+-              return -ENOMEM;
+-      }
+-      server->secmech.sdeschmacsha256->shash.tfm = server->secmech.hmacsha256;
+-      server->secmech.sdeschmacsha256->shash.flags = 0x0;
+-
+-      return 0;
++      return cifs_alloc_hash("hmac(sha256)",
++                             &server->secmech.hmacsha256,
++                             &server->secmech.sdeschmacsha256);
+ }
+ static int
+ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
+ {
+-      unsigned int size;
++      struct cifs_secmech *p = &server->secmech;
+       int rc;
+-      if (server->secmech.sdesccmacaes != NULL)
+-              return 0;  /* already allocated */
+-
+-      rc = smb2_crypto_shash_allocate(server);
++      rc = cifs_alloc_hash("hmac(sha256)",
++                           &p->hmacsha256,
++                           &p->sdeschmacsha256);
+       if (rc)
+-              return rc;
+-
+-      server->secmech.cmacaes = crypto_alloc_shash("cmac(aes)", 0, 0);
+-      if (IS_ERR(server->secmech.cmacaes)) {
+-              cifs_dbg(VFS, "could not allocate crypto cmac-aes");
+-              kfree(server->secmech.sdeschmacsha256);
+-              server->secmech.sdeschmacsha256 = NULL;
+-              crypto_free_shash(server->secmech.hmacsha256);
+-              server->secmech.hmacsha256 = NULL;
+-              rc = PTR_ERR(server->secmech.cmacaes);
+-              server->secmech.cmacaes = NULL;
+-              return rc;
+-      }
++              goto err;
+-      size = sizeof(struct shash_desc) +
+-                      crypto_shash_descsize(server->secmech.cmacaes);
+-      server->secmech.sdesccmacaes = kmalloc(size, GFP_KERNEL);
+-      if (!server->secmech.sdesccmacaes) {
+-              cifs_dbg(VFS, "%s: Can't alloc cmacaes\n", __func__);
+-              kfree(server->secmech.sdeschmacsha256);
+-              server->secmech.sdeschmacsha256 = NULL;
+-              crypto_free_shash(server->secmech.hmacsha256);
+-              crypto_free_shash(server->secmech.cmacaes);
+-              server->secmech.hmacsha256 = NULL;
+-              server->secmech.cmacaes = NULL;
+-              return -ENOMEM;
+-      }
+-      server->secmech.sdesccmacaes->shash.tfm = server->secmech.cmacaes;
+-      server->secmech.sdesccmacaes->shash.flags = 0x0;
++      rc = cifs_alloc_hash("cmac(aes)", &p->cmacaes, &p->sdesccmacaes);
++      if (rc)
++              goto err;
+       return 0;
++err:
++      cifs_free_hash(&p->hmacsha256, &p->sdeschmacsha256);
++      return rc;
+ }
+ static struct cifs_ses *
+@@ -457,7 +412,7 @@ smb3_calc_signature(struct smb_rqst *rqs
+               cifs_dbg(VFS, "%s: Could not init cmac aes\n", __func__);
+               return rc;
+       }
+-      
++
+       rc = __cifs_calc_signature(rqst, server, sigptr,
+                                  &server->secmech.sdesccmacaes->shash);
+--- a/fs/cifs/smbencrypt.c
++++ b/fs/cifs/smbencrypt.c
+@@ -121,25 +121,12 @@ int
+ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len)
+ {
+       int rc;
+-      unsigned int size;
+-      struct crypto_shash *md4;
+-      struct sdesc *sdescmd4;
++      struct crypto_shash *md4 = NULL;
++      struct sdesc *sdescmd4 = NULL;
+-      md4 = crypto_alloc_shash("md4", 0, 0);
+-      if (IS_ERR(md4)) {
+-              rc = PTR_ERR(md4);
+-              cifs_dbg(VFS, "%s: Crypto md4 allocation error %d\n",
+-                       __func__, rc);
+-              return rc;
+-      }
+-      size = sizeof(struct shash_desc) + crypto_shash_descsize(md4);
+-      sdescmd4 = kmalloc(size, GFP_KERNEL);
+-      if (!sdescmd4) {
+-              rc = -ENOMEM;
++      rc = cifs_alloc_hash("md4", &md4, &sdescmd4);
++      if (rc)
+               goto mdfour_err;
+-      }
+-      sdescmd4->shash.tfm = md4;
+-      sdescmd4->shash.flags = 0x0;
+       rc = crypto_shash_init(&sdescmd4->shash);
+       if (rc) {
+@@ -156,9 +143,7 @@ mdfour(unsigned char *md4_hash, unsigned
+               cifs_dbg(VFS, "%s: Could not generate md4 hash\n", __func__);
+ mdfour_err:
+-      crypto_free_shash(md4);
+-      kfree(sdescmd4);
+-
++      cifs_free_hash(&md4, &sdescmd4);
+       return rc;
+ }
diff --git a/queue-4.16/cifs-smbd-avoid-reconnect-lockup.patch b/queue-4.16/cifs-smbd-avoid-reconnect-lockup.patch
new file mode 100644 (file)
index 0000000..67f4646
--- /dev/null
@@ -0,0 +1,65 @@
+From 48f238a79f668f8ff013024d83010de551833d7f Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Fri, 30 Mar 2018 15:16:35 -0700
+Subject: cifs: smbd: avoid reconnect lockup
+
+From: Long Li <longli@microsoft.com>
+
+commit 48f238a79f668f8ff013024d83010de551833d7f upstream.
+
+During transport reconnect, other processes may have registered memory
+and blocked on transport. This creates a deadlock situation because the
+transport resources can't be freed, and reconnect is blocked.
+
+Fix this by returning to upper layer on timeout. Before returning,
+transport status is set to reconnecting so other processes will release
+memory registration resources.
+
+Upper layer will retry the reconnect. This is not in fast I/O path so
+setting the timeout to 5 seconds.
+
+Signed-off-by: Long Li <longli@microsoft.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smbdirect.c |   12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/fs/cifs/smbdirect.c
++++ b/fs/cifs/smbdirect.c
+@@ -1498,8 +1498,8 @@ int smbd_reconnect(struct TCP_Server_Inf
+       log_rdma_event(INFO, "reconnecting rdma session\n");
+       if (!server->smbd_conn) {
+-              log_rdma_event(ERR, "rdma session already destroyed\n");
+-              return -EINVAL;
++              log_rdma_event(INFO, "rdma session already destroyed\n");
++              goto create_conn;
+       }
+       /*
+@@ -1512,15 +1512,19 @@ int smbd_reconnect(struct TCP_Server_Inf
+       }
+       /* wait until the transport is destroyed */
+-      wait_event(server->smbd_conn->wait_destroy,
+-              server->smbd_conn->transport_status == SMBD_DESTROYED);
++      if (!wait_event_timeout(server->smbd_conn->wait_destroy,
++              server->smbd_conn->transport_status == SMBD_DESTROYED, 5*HZ))
++              return -EAGAIN;
+       destroy_workqueue(server->smbd_conn->workqueue);
+       kfree(server->smbd_conn);
++create_conn:
+       log_rdma_event(INFO, "creating rdma session\n");
+       server->smbd_conn = smbd_get_connection(
+               server, (struct sockaddr *) &server->dstaddr);
++      log_rdma_event(INFO, "created rdma session info=%p\n",
++              server->smbd_conn);
+       return server->smbd_conn ? 0 : -ENOENT;
+ }
diff --git a/queue-4.16/cifs-smbd-disconnect-transport-on-rdma-errors.patch b/queue-4.16/cifs-smbd-disconnect-transport-on-rdma-errors.patch
new file mode 100644 (file)
index 0000000..d60f854
--- /dev/null
@@ -0,0 +1,59 @@
+From 21a4e14aaedbc85f203d37e56cb26235b22b43f6 Mon Sep 17 00:00:00 2001
+From: Long Li <longli@microsoft.com>
+Date: Fri, 30 Mar 2018 15:16:36 -0700
+Subject: cifs: smbd: disconnect transport on RDMA errors
+
+From: Long Li <longli@microsoft.com>
+
+commit 21a4e14aaedbc85f203d37e56cb26235b22b43f6 upstream.
+
+On RDMA errors, transport should disconnect the RDMA CM connection. This
+will notify the upper layer, and it will attempt transport reconnect.
+
+Signed-off-by: Long Li <longli@microsoft.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smbdirect.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/smbdirect.c
++++ b/fs/cifs/smbdirect.c
+@@ -862,6 +862,8 @@ static int smbd_post_send_negotiate_req(
+       ib_dma_unmap_single(info->id->device, request->sge[0].addr,
+               request->sge[0].length, DMA_TO_DEVICE);
++      smbd_disconnect_rdma_connection(info);
++
+ dma_mapping_failed:
+       mempool_free(request, info->request_mempool);
+       return rc;
+@@ -1061,6 +1063,7 @@ static int smbd_post_send(struct smbd_co
+                       if (atomic_dec_and_test(&info->send_pending))
+                               wake_up(&info->wait_send_pending);
+               }
++              smbd_disconnect_rdma_connection(info);
+       } else
+               /* Reset timer for idle connection after packet is sent */
+               mod_delayed_work(info->workqueue, &info->idle_timer_work,
+@@ -1202,7 +1205,7 @@ static int smbd_post_recv(
+       if (rc) {
+               ib_dma_unmap_single(info->id->device, response->sge.addr,
+                                   response->sge.length, DMA_FROM_DEVICE);
+-
++              smbd_disconnect_rdma_connection(info);
+               log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc);
+       }
+@@ -2546,6 +2549,8 @@ dma_map_error:
+       if (atomic_dec_and_test(&info->mr_used_count))
+               wake_up(&info->wait_for_mr_cleanup);
++      smbd_disconnect_rdma_connection(info);
++
+       return NULL;
+ }
diff --git a/queue-4.16/fix-smb3-encryption-breakage-when-config_debug_sg-y.patch b/queue-4.16/fix-smb3-encryption-breakage-when-config_debug_sg-y.patch
new file mode 100644 (file)
index 0000000..376874d
--- /dev/null
@@ -0,0 +1,63 @@
+From 262916bc69faf90104aa784d55e10760a4199594 Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+Date: Tue, 20 Feb 2018 12:45:21 +1100
+Subject: fix smb3-encryption breakage when CONFIG_DEBUG_SG=y
+
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+
+commit 262916bc69faf90104aa784d55e10760a4199594 upstream.
+
+We can not use the standard sg_set_buf() fucntion since when
+CONFIG_DEBUG_SG=y this adds a check that will BUG_ON for cifs.ko
+when we pass it an object from the stack.
+
+Create a new wrapper smb2_sg_set_buf() which avoids doing that particular check
+and use it for smb3 encryption instead.
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -2066,6 +2066,15 @@ fill_transform_hdr(struct smb2_transform
+       inc_rfc1001_len(tr_hdr, orig_len);
+ }
++/* We can not use the normal sg_set_buf() as we will sometimes pass a
++ * stack object as buf.
++ */
++static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
++                                 unsigned int buflen)
++{
++      sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
++}
++
+ static struct scatterlist *
+ init_sg(struct smb_rqst *rqst, u8 *sign)
+ {
+@@ -2080,16 +2089,16 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
+               return NULL;
+       sg_init_table(sg, sg_len);
+-      sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
++      smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
+       for (i = 1; i < rqst->rq_nvec; i++)
+-              sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
++              smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
+                                               rqst->rq_iov[i].iov_len);
+       for (j = 0; i < sg_len - 1; i++, j++) {
+               unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
+                                                       : rqst->rq_tailsz;
+               sg_set_page(&sg[i], rqst->rq_pages[j], len, 0);
+       }
+-      sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
++      smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
+       return sg;
+ }
diff --git a/queue-4.16/hid-i2c-hid-fix-size-check-and-type-usage.patch b/queue-4.16/hid-i2c-hid-fix-size-check-and-type-usage.patch
new file mode 100644 (file)
index 0000000..f64a03f
--- /dev/null
@@ -0,0 +1,59 @@
+From ac75a041048b8c1f7418e27621ca5efda8571043 Mon Sep 17 00:00:00 2001
+From: Aaron Ma <aaron.ma@canonical.com>
+Date: Mon, 8 Jan 2018 10:41:40 +0800
+Subject: HID: i2c-hid: fix size check and type usage
+
+From: Aaron Ma <aaron.ma@canonical.com>
+
+commit ac75a041048b8c1f7418e27621ca5efda8571043 upstream.
+
+When convert char array with signed int, if the inbuf[x] is negative then
+upper bits will be set to 1. Fix this by using u8 instead of char.
+
+ret_size has to be at least 3, hid_input_report use it after minus 2 bytes.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Aaron Ma <aaron.ma@canonical.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/i2c-hid/i2c-hid.c |   13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/drivers/hid/i2c-hid/i2c-hid.c
++++ b/drivers/hid/i2c-hid/i2c-hid.c
+@@ -144,10 +144,10 @@ struct i2c_hid {
+                                                  * register of the HID
+                                                  * descriptor. */
+       unsigned int            bufsize;        /* i2c buffer size */
+-      char                    *inbuf;         /* Input buffer */
+-      char                    *rawbuf;        /* Raw Input buffer */
+-      char                    *cmdbuf;        /* Command buffer */
+-      char                    *argsbuf;       /* Command arguments buffer */
++      u8                      *inbuf;         /* Input buffer */
++      u8                      *rawbuf;        /* Raw Input buffer */
++      u8                      *cmdbuf;        /* Command buffer */
++      u8                      *argsbuf;       /* Command arguments buffer */
+       unsigned long           flags;          /* device flags */
+       unsigned long           quirks;         /* Various quirks */
+@@ -455,7 +455,8 @@ out_unlock:
+ static void i2c_hid_get_input(struct i2c_hid *ihid)
+ {
+-      int ret, ret_size;
++      int ret;
++      u32 ret_size;
+       int size = le16_to_cpu(ihid->hdesc.wMaxInputLength);
+       if (size > ihid->bufsize)
+@@ -480,7 +481,7 @@ static void i2c_hid_get_input(struct i2c
+               return;
+       }
+-      if (ret_size > size) {
++      if ((ret_size > size) || (ret_size <= 2)) {
+               dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
+                       __func__, size, ret_size);
+               return;
diff --git a/queue-4.16/i2c-i801-restore-configuration-at-shutdown.patch b/queue-4.16/i2c-i801-restore-configuration-at-shutdown.patch
new file mode 100644 (file)
index 0000000..ee2f6cf
--- /dev/null
@@ -0,0 +1,50 @@
+From f7f6d915a10f7f2bce17e3b1b7d3376562395a28 Mon Sep 17 00:00:00 2001
+From: Jean Delvare <jdelvare@suse.de>
+Date: Wed, 11 Apr 2018 18:05:34 +0200
+Subject: i2c: i801: Restore configuration at shutdown
+
+From: Jean Delvare <jdelvare@suse.de>
+
+commit f7f6d915a10f7f2bce17e3b1b7d3376562395a28 upstream.
+
+On some systems, the BIOS expects certain SMBus register values to
+match the hardware defaults. Restore these configuration registers at
+shutdown time to avoid confusing the BIOS. This avoids hard-locking
+such systems upon reboot.
+
+Signed-off-by: Jean Delvare <jdelvare@suse.de>
+Tested-by: Jason Andryuk <jandryuk@gmail.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/busses/i2c-i801.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/i2c/busses/i2c-i801.c
++++ b/drivers/i2c/busses/i2c-i801.c
+@@ -1701,6 +1701,15 @@ static void i801_remove(struct pci_dev *
+        */
+ }
++static void i801_shutdown(struct pci_dev *dev)
++{
++      struct i801_priv *priv = pci_get_drvdata(dev);
++
++      /* Restore config registers to avoid hard hang on some systems */
++      i801_disable_host_notify(priv);
++      pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
++}
++
+ #ifdef CONFIG_PM
+ static int i801_suspend(struct device *dev)
+ {
+@@ -1730,6 +1739,7 @@ static struct pci_driver i801_driver = {
+       .id_table       = i801_ids,
+       .probe          = i801_probe,
+       .remove         = i801_remove,
++      .shutdown       = i801_shutdown,
+       .driver         = {
+               .pm     = &i801_pm_ops,
+       },
diff --git a/queue-4.16/i2c-i801-save-register-smbslvcmd-value-only-once.patch b/queue-4.16/i2c-i801-save-register-smbslvcmd-value-only-once.patch
new file mode 100644 (file)
index 0000000..ccf7268
--- /dev/null
@@ -0,0 +1,49 @@
+From a086bb8317303dd74725dca933b9b29575159382 Mon Sep 17 00:00:00 2001
+From: Jean Delvare <jdelvare@suse.de>
+Date: Wed, 11 Apr 2018 18:03:31 +0200
+Subject: i2c: i801: Save register SMBSLVCMD value only once
+
+From: Jean Delvare <jdelvare@suse.de>
+
+commit a086bb8317303dd74725dca933b9b29575159382 upstream.
+
+Saving the original value of register SMBSLVCMD in
+i801_enable_host_notify() doesn't work, because this function is
+called not only at probe time but also at resume time. Do it in
+i801_probe() instead, so that the saved value is not overwritten at
+resume time.
+
+Signed-off-by: Jean Delvare <jdelvare@suse.de>
+Fixes: 22e94bd6779e ("i2c: i801: store and restore the SLVCMD register at load and unload")
+Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
+Tested-by: Jason Andryuk <jandryuk@gmail.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+Cc: stable@vger.kernel.org     # v4.10+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i2c/busses/i2c-i801.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/i2c/busses/i2c-i801.c
++++ b/drivers/i2c/busses/i2c-i801.c
+@@ -966,8 +966,6 @@ static void i801_enable_host_notify(stru
+       if (!(priv->features & FEATURE_HOST_NOTIFY))
+               return;
+-      priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
+-
+       if (!(SMBSLVCMD_HST_NTFY_INTREN & priv->original_slvcmd))
+               outb_p(SMBSLVCMD_HST_NTFY_INTREN | priv->original_slvcmd,
+                      SMBSLVCMD(priv));
+@@ -1615,6 +1613,10 @@ static int i801_probe(struct pci_dev *de
+               outb_p(inb_p(SMBAUXCTL(priv)) &
+                      ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
++      /* Remember original Host Notify setting */
++      if (priv->features & FEATURE_HOST_NOTIFY)
++              priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
++
+       /* Default timeout in interrupt mode: 200 ms */
+       priv->adapter.timeout = HZ / 5;
diff --git a/queue-4.16/regmap-fix-reversed-bounds-check-in-regmap_raw_write.patch b/queue-4.16/regmap-fix-reversed-bounds-check-in-regmap_raw_write.patch
new file mode 100644 (file)
index 0000000..f9960f7
--- /dev/null
@@ -0,0 +1,39 @@
+From f00e71091ab92eba52122332586c6ecaa9cd1a56 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Thu, 8 Feb 2018 10:23:44 +0300
+Subject: regmap: Fix reversed bounds check in regmap_raw_write()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit f00e71091ab92eba52122332586c6ecaa9cd1a56 upstream.
+
+We're supposed to be checking that "val_len" is not too large but
+instead we check if it is smaller than the max.
+
+The only function affected would be regmap_i2c_smbus_i2c_write() in
+drivers/base/regmap/regmap-i2c.c.  Strangely that function has its own
+limit check which returns an error if (count >= I2C_SMBUS_BLOCK_MAX) so
+it doesn't look like it has ever been able to do anything except return
+an error.
+
+Fixes: c335931ed9d2 ("regmap: Add raw_write/read checks for max_raw_write/read sizes")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/regmap/regmap.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -1831,7 +1831,7 @@ int regmap_raw_write(struct regmap *map,
+               return -EINVAL;
+       if (val_len % map->format.val_bytes)
+               return -EINVAL;
+-      if (map->max_raw_write && map->max_raw_write > val_len)
++      if (map->max_raw_write && map->max_raw_write < val_len)
+               return -E2BIG;
+       map->lock(map->lock_arg);
index ad365e849b109d64404732b82eb73035a5ea0720..88306e9dddba54c5d4ca4934563432e1ae9ecee6 100644 (file)
@@ -33,3 +33,25 @@ media-vivid-check-if-the-cec_adapter-is-valid.patch
 media-vb2-core-finish-buffers-at-the-end-of-the-stream.patch
 media-vsp1-fix-brx-conditional-path-in-wpf.patch
 x86-xen-delay-get_cpu_cap-until-stack-canary-is-established.patch
+regmap-fix-reversed-bounds-check-in-regmap_raw_write.patch
+acpi-video-add-quirk-to-force-acpi-video-backlight-on-samsung-670z5e.patch
+acpi-hotplug-pci-check-presence-of-slot-itself-in-get_slot_status.patch
+acpi-nfit-rework-nvdimm-leaf-method-detection.patch
+usb-gadget-f_midi-fixing-a-possible-double-free-in-f_midi.patch
+usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch
+usb-dwc3-prevent-setting-prtcap-to-otg-from-debugfs.patch
+usb-dwc3-pci-properly-cleanup-resource.patch
+usb-dwc3-gadget-never-call-complete-from-ep_queue.patch
+cifs-fix-memory-leak-in-smb2_open.patch
+fix-smb3-encryption-breakage-when-config_debug_sg-y.patch
+tree-connect-for-smb3.1.1-must-be-signed-for-non-encrypted-shares.patch
+cifs-smbd-avoid-reconnect-lockup.patch
+cifs-smbd-disconnect-transport-on-rdma-errors.patch
+smb3-fix-root-directory-when-server-returns-inode-number-of-zero.patch
+hid-i2c-hid-fix-size-check-and-type-usage.patch
+i2c-i801-save-register-smbslvcmd-value-only-once.patch
+i2c-i801-restore-configuration-at-shutdown.patch
+cifs-refactor-crypto-shash-sdesc-allocation-free.patch
+cifs-add-sha512-secmech.patch
+cifs-implement-v3.11-preauth-integrity.patch
+cifs-fix-sha512-check-in-cifs_crypto_secmech_release.patch
diff --git a/queue-4.16/smb3-fix-root-directory-when-server-returns-inode-number-of-zero.patch b/queue-4.16/smb3-fix-root-directory-when-server-returns-inode-number-of-zero.patch
new file mode 100644 (file)
index 0000000..b0f8f31
--- /dev/null
@@ -0,0 +1,98 @@
+From 7ea884c77e5c97f1e0a1a422d961d27f78ca2745 Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+Date: Sat, 31 Mar 2018 18:13:38 -0500
+Subject: smb3: Fix root directory when server returns inode number of zero
+
+From: Steve French <stfrench@microsoft.com>
+
+commit 7ea884c77e5c97f1e0a1a422d961d27f78ca2745 upstream.
+
+Some servers return inode number zero for the root directory, which
+causes ls to display incorrect data (missing "." and "..").
+
+If the server returns zero for the inode number of the root directory,
+fake an inode number for it.
+
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsglob.h |    1 +
+ fs/cifs/inode.c    |   33 +++++++++++++++++++++++++++++++++
+ 2 files changed, 34 insertions(+)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -1466,6 +1466,7 @@ struct dfs_info3_param {
+ #define CIFS_FATTR_NEED_REVAL         0x4
+ #define CIFS_FATTR_INO_COLLISION      0x8
+ #define CIFS_FATTR_UNKNOWN_NLINK      0x10
++#define CIFS_FATTR_FAKE_ROOT_INO      0x20
+ struct cifs_fattr {
+       u32             cf_flags;
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -707,6 +707,18 @@ cgfi_exit:
+       return rc;
+ }
++/* Simple function to return a 64 bit hash of string.  Rarely called */
++static __u64 simple_hashstr(const char *str)
++{
++      const __u64 hash_mult =  1125899906842597L; /* a big enough prime */
++      __u64 hash = 0;
++
++      while (*str)
++              hash = (hash + (__u64) *str++) * hash_mult;
++
++      return hash;
++}
++
+ int
+ cifs_get_inode_info(struct inode **inode, const char *full_path,
+                   FILE_ALL_INFO *data, struct super_block *sb, int xid,
+@@ -816,6 +828,14 @@ cifs_get_inode_info(struct inode **inode
+                                                tmprc);
+                                       fattr.cf_uniqueid = iunique(sb, ROOT_I);
+                                       cifs_autodisable_serverino(cifs_sb);
++                              } else if ((fattr.cf_uniqueid == 0) &&
++                                              strlen(full_path) == 0) {
++                                      /* some servers ret bad root ino ie 0 */
++                                      cifs_dbg(FYI, "Invalid (0) inodenum\n");
++                                      fattr.cf_flags |=
++                                              CIFS_FATTR_FAKE_ROOT_INO;
++                                      fattr.cf_uniqueid =
++                                              simple_hashstr(tcon->treeName);
+                               }
+                       }
+               } else
+@@ -832,6 +852,16 @@ cifs_get_inode_info(struct inode **inode
+                               &fattr.cf_uniqueid, data);
+                       if (tmprc)
+                               fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
++                      else if ((fattr.cf_uniqueid == 0) &&
++                                      strlen(full_path) == 0) {
++                              /*
++                               * Reuse existing root inode num since
++                               * inum zero for root causes ls of . and .. to
++                               * not be returned
++                               */
++                              cifs_dbg(FYI, "Srv ret 0 inode num for root\n");
++                              fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
++                      }
+               } else
+                       fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
+       }
+@@ -893,6 +923,9 @@ cifs_get_inode_info(struct inode **inode
+       }
+ cgii_exit:
++      if ((*inode) && ((*inode)->i_ino == 0))
++              cifs_dbg(FYI, "inode number of zero returned\n");
++
+       kfree(buf);
+       cifs_put_tlink(tlink);
+       return rc;
diff --git a/queue-4.16/tree-connect-for-smb3.1.1-must-be-signed-for-non-encrypted-shares.patch b/queue-4.16/tree-connect-for-smb3.1.1-must-be-signed-for-non-encrypted-shares.patch
new file mode 100644 (file)
index 0000000..b6a7d62
--- /dev/null
@@ -0,0 +1,37 @@
+From 6188f28bf608ddecc2377663b0f2f709440c19ba Mon Sep 17 00:00:00 2001
+From: Steve French <smfrench@gmail.com>
+Date: Tue, 13 Mar 2018 02:29:36 -0500
+Subject: Tree connect for SMB3.1.1 must be signed for non-encrypted shares
+
+From: Steve French <smfrench@gmail.com>
+
+commit 6188f28bf608ddecc2377663b0f2f709440c19ba upstream.
+
+SMB3.1.1 tree connect was only being signed when signing was mandatory
+but needs to always be signed (for non-guest users).
+
+See MS-SMB2 section 3.2.4.1.1
+
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2pdu.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1280,6 +1280,11 @@ SMB2_tcon(const unsigned int xid, struct
+       iov[1].iov_base = unc_path;
+       iov[1].iov_len = unc_path_len;
++      /* 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 */
++      if ((ses->server->dialect == SMB311_PROT_ID) &&
++          !encryption_required(tcon))
++              req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
++
+       rc = smb2_send_recv(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov);
+       cifs_small_buf_release(req);
+       rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
diff --git a/queue-4.16/usb-dwc3-gadget-never-call-complete-from-ep_queue.patch b/queue-4.16/usb-dwc3-gadget-never-call-complete-from-ep_queue.patch
new file mode 100644 (file)
index 0000000..88fd18c
--- /dev/null
@@ -0,0 +1,123 @@
+From c91815b596245fd7da349ecc43c8def670d2269e Mon Sep 17 00:00:00 2001
+From: Felipe Balbi <felipe.balbi@linux.intel.com>
+Date: Mon, 26 Mar 2018 13:14:47 +0300
+Subject: usb: dwc3: gadget: never call ->complete() from ->ep_queue()
+
+From: Felipe Balbi <felipe.balbi@linux.intel.com>
+
+commit c91815b596245fd7da349ecc43c8def670d2269e upstream.
+
+This is a requirement which has always existed but, somehow, wasn't
+reflected in the documentation and problems weren't found until now
+when Tuba Yavuz found a possible deadlock happening between dwc3 and
+f_hid. She described the situation as follows:
+
+spin_lock_irqsave(&hidg->write_spinlock, flags); // first acquire
+/* we our function has been disabled by host */
+if (!hidg->req) {
+       free_ep_req(hidg->in_ep, hidg->req);
+       goto try_again;
+}
+
+[...]
+
+status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
+=>
+       [...]
+       => usb_gadget_giveback_request
+               =>
+               f_hidg_req_complete
+                       =>
+                       spin_lock_irqsave(&hidg->write_spinlock, flags); // second acquire
+
+Note that this happens because dwc3 would call ->complete() on a
+failed usb_ep_queue() due to failed Start Transfer command. This is,
+anyway, a theoretical situation because dwc3 currently uses "No
+Response Update Transfer" command for Bulk and Interrupt endpoints.
+
+It's still good to make this case impossible to happen even if the "No
+Reponse Update Transfer" command is changed.
+
+Reported-by: Tuba Yavuz <tuba@ece.ufl.edu>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c |   43 +++++++++++++++++++++++++------------------
+ 1 file changed, 25 insertions(+), 18 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -166,18 +166,8 @@ static void dwc3_ep_inc_deq(struct dwc3_
+       dwc3_ep_inc_trb(&dep->trb_dequeue);
+ }
+-/**
+- * dwc3_gadget_giveback - call struct usb_request's ->complete callback
+- * @dep: The endpoint to whom the request belongs to
+- * @req: The request we're giving back
+- * @status: completion code for the request
+- *
+- * Must be called with controller's lock held and interrupts disabled. This
+- * function will unmap @req and call its ->complete() callback to notify upper
+- * layers that it has completed.
+- */
+-void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
+-              int status)
++void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
++              struct dwc3_request *req, int status)
+ {
+       struct dwc3                     *dwc = dep->dwc;
+@@ -190,18 +180,35 @@ void dwc3_gadget_giveback(struct dwc3_ep
+       if (req->trb)
+               usb_gadget_unmap_request_by_dev(dwc->sysdev,
+-                                              &req->request, req->direction);
++                              &req->request, req->direction);
+       req->trb = NULL;
+-
+       trace_dwc3_gadget_giveback(req);
++      if (dep->number > 1)
++              pm_runtime_put(dwc->dev);
++}
++
++/**
++ * dwc3_gadget_giveback - call struct usb_request's ->complete callback
++ * @dep: The endpoint to whom the request belongs to
++ * @req: The request we're giving back
++ * @status: completion code for the request
++ *
++ * Must be called with controller's lock held and interrupts disabled. This
++ * function will unmap @req and call its ->complete() callback to notify upper
++ * layers that it has completed.
++ */
++void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
++              int status)
++{
++      struct dwc3                     *dwc = dep->dwc;
++
++      dwc3_gadget_del_and_unmap_request(dep, req, status);
++
+       spin_unlock(&dwc->lock);
+       usb_gadget_giveback_request(&dep->endpoint, &req->request);
+       spin_lock(&dwc->lock);
+-
+-      if (dep->number > 1)
+-              pm_runtime_put(dwc->dev);
+ }
+ /**
+@@ -1227,7 +1234,7 @@ static int __dwc3_gadget_kick_transfer(s
+               if (req->trb)
+                       memset(req->trb, 0, sizeof(struct dwc3_trb));
+               dep->queued_requests--;
+-              dwc3_gadget_giveback(dep, req, ret);
++              dwc3_gadget_del_and_unmap_request(dep, req, ret);
+               return ret;
+       }
diff --git a/queue-4.16/usb-dwc3-pci-properly-cleanup-resource.patch b/queue-4.16/usb-dwc3-pci-properly-cleanup-resource.patch
new file mode 100644 (file)
index 0000000..fad57fa
--- /dev/null
@@ -0,0 +1,33 @@
+From cabdf83dadfb3d83eec31e0f0638a92dbd716435 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Mon, 19 Mar 2018 13:07:35 -0700
+Subject: usb: dwc3: pci: Properly cleanup resource
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit cabdf83dadfb3d83eec31e0f0638a92dbd716435 upstream.
+
+Platform device is allocated before adding resources. Make sure to
+properly cleanup on error case.
+
+Cc: <stable@vger.kernel.org>
+Fixes: f1c7e7108109 ("usb: dwc3: convert to pcim_enable_device()")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/dwc3-pci.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -222,7 +222,7 @@ static int dwc3_pci_probe(struct pci_dev
+       ret = platform_device_add_resources(dwc->dwc3, res, ARRAY_SIZE(res));
+       if (ret) {
+               dev_err(dev, "couldn't add resources to dwc3 device\n");
+-              return ret;
++              goto err;
+       }
+       dwc->pci = pci;
diff --git a/queue-4.16/usb-dwc3-prevent-setting-prtcap-to-otg-from-debugfs.patch b/queue-4.16/usb-dwc3-prevent-setting-prtcap-to-otg-from-debugfs.patch
new file mode 100644 (file)
index 0000000..9c8dea3
--- /dev/null
@@ -0,0 +1,34 @@
+From daaecc6541d014dca073473ec8a4120c0babbeb4 Mon Sep 17 00:00:00 2001
+From: Roger Quadros <rogerq@ti.com>
+Date: Tue, 27 Feb 2018 12:54:37 +0200
+Subject: usb: dwc3: prevent setting PRTCAP to OTG from debugfs
+
+From: Roger Quadros <rogerq@ti.com>
+
+commit daaecc6541d014dca073473ec8a4120c0babbeb4 upstream.
+
+We don't support PRTCAP == OTG yet, so prevent user from
+setting it via debugfs.
+
+Fixes: 41ce1456e1db ("usb: dwc3: core: make dwc3_set_mode() work properly")
+Cc: <stable@vger.kernel.org> # v4.12+
+Signed-off-by: Roger Quadros <rogerq@ti.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -119,6 +119,9 @@ static void __dwc3_set_mode(struct work_
+       if (dwc->dr_mode != USB_DR_MODE_OTG)
+               return;
++      if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG)
++              return;
++
+       switch (dwc->current_dr_role) {
+       case DWC3_GCTL_PRTCAP_HOST:
+               dwc3_host_exit(dwc);
diff --git a/queue-4.16/usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch b/queue-4.16/usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch
new file mode 100644 (file)
index 0000000..030e2c3
--- /dev/null
@@ -0,0 +1,60 @@
+From 64627388b50158fd24d6ad88132525b95a5ef573 Mon Sep 17 00:00:00 2001
+From: Zhengjun Xing <zhengjun.xing@linux.intel.com>
+Date: Wed, 21 Mar 2018 13:29:42 +0800
+Subject: USB:fix USB3 devices behind USB3 hubs not resuming at hibernate thaw
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhengjun Xing <zhengjun.xing@linux.intel.com>
+
+commit 64627388b50158fd24d6ad88132525b95a5ef573 upstream.
+
+USB3 hubs don't support global suspend.
+
+USB3 specification 10.10, Enhanced SuperSpeed hubs only support selective
+suspend and resume, they do not support global suspend/resume where the
+hub downstream facing ports states are not affected.
+
+When system enters hibernation it first enters freeze process where only
+the root hub enters suspend, usb_port_suspend() is not called for other
+devices, and suspend status flags are not set for them. Other devices are
+expected to suspend globally. Some external USB3 hubs will suspend the
+downstream facing port at global suspend. These devices won't be resumed
+at thaw as the suspend status flag is not set.
+
+A USB3 removable hard disk connected through a USB3 hub that won't resume
+at thaw will fail to synchronize SCSI cache, return “cmd cmplt err -71”
+error, and needs a 60 seconds timeout which causing system hang for 60s
+before the USB host reset the port for the USB3 removable hard disk to
+recover.
+
+Fix this by always calling usb_port_suspend() during freeze for USB3
+devices.
+
+Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/generic.c |    9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -210,8 +210,13 @@ static int generic_suspend(struct usb_de
+       if (!udev->parent)
+               rc = hcd_bus_suspend(udev, msg);
+-      /* Non-root devices don't need to do anything for FREEZE or PRETHAW */
+-      else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
++      /*
++       * Non-root USB2 devices don't need to do anything for FREEZE
++       * or PRETHAW. USB3 devices don't support global suspend and
++       * needs to be selectively suspended.
++       */
++      else if ((msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW)
++               && (udev->speed < USB_SPEED_SUPER))
+               rc = 0;
+       else
+               rc = usb_port_suspend(udev, msg);
diff --git a/queue-4.16/usb-gadget-f_midi-fixing-a-possible-double-free-in-f_midi.patch b/queue-4.16/usb-gadget-f_midi-fixing-a-possible-double-free-in-f_midi.patch
new file mode 100644 (file)
index 0000000..ae745fd
--- /dev/null
@@ -0,0 +1,68 @@
+From 7fafcfdf6377b18b2a726ea554d6e593ba44349f Mon Sep 17 00:00:00 2001
+From: "Yavuz, Tuba" <tuba@ece.ufl.edu>
+Date: Fri, 23 Mar 2018 17:00:38 +0000
+Subject: USB: gadget: f_midi: fixing a possible double-free in f_midi
+
+From: Yavuz, Tuba <tuba@ece.ufl.edu>
+
+commit 7fafcfdf6377b18b2a726ea554d6e593ba44349f upstream.
+
+It looks like there is a possibility of a double-free vulnerability on an
+error path of the f_midi_set_alt function in the f_midi driver. If the
+path is feasible then free_ep_req gets called twice:
+
+         req->complete = f_midi_complete;
+         err = usb_ep_queue(midi->out_ep, req, GFP_ATOMIC);
+            => ...
+             usb_gadget_giveback_request
+               =>
+                 f_midi_complete (CALLBACK)
+                   (inside f_midi_complete, for various cases of status)
+                   free_ep_req(ep, req); // first kfree
+         if (err) {
+                 ERROR(midi, "%s: couldn't enqueue request: %d\n",
+                             midi->out_ep->name, err);
+                 free_ep_req(midi->out_ep, req); // second kfree
+                 return err;
+         }
+
+The double-free possibility was introduced with commit ad0d1a058eac
+("usb: gadget: f_midi: fix leak on failed to enqueue out requests").
+
+Found by MOXCAFE tool.
+
+Signed-off-by: Tuba Yavuz <tuba@ece.ufl.edu>
+Fixes: ad0d1a058eac ("usb: gadget: f_midi: fix leak on failed to enqueue out requests")
+Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_midi.c |    3 ++-
+ drivers/usb/gadget/u_f.h             |    2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_midi.c
++++ b/drivers/usb/gadget/function/f_midi.c
+@@ -404,7 +404,8 @@ static int f_midi_set_alt(struct usb_fun
+               if (err) {
+                       ERROR(midi, "%s: couldn't enqueue request: %d\n",
+                                   midi->out_ep->name, err);
+-                      free_ep_req(midi->out_ep, req);
++                      if (req->buf != NULL)
++                              free_ep_req(midi->out_ep, req);
+                       return err;
+               }
+       }
+--- a/drivers/usb/gadget/u_f.h
++++ b/drivers/usb/gadget/u_f.h
+@@ -61,7 +61,9 @@ struct usb_request *alloc_ep_req(struct
+ /* Frees a usb_request previously allocated by alloc_ep_req() */
+ static inline void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+ {
++      WARN_ON(req->buf == NULL);
+       kfree(req->buf);
++      req->buf = NULL;
+       usb_ep_free_request(ep, req);
+ }