]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Jan 2020 13:46:42 +0000 (14:46 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Jan 2020 13:46:42 +0000 (14:46 +0100)
added patches:
scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch
usb-serial-ch341-handle-unbound-port-at-reset_resume.patch
usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch
usb-serial-opticon-fix-control-message-timeouts.patch
usb-serial-quatech2-handle-unbound-ports.patch
usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch
usb-serial-suppress-driver-bind-attributes.patch

queue-4.4/scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/usb-serial-ch341-handle-unbound-port-at-reset_resume.patch [new file with mode: 0644]
queue-4.4/usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch [new file with mode: 0644]
queue-4.4/usb-serial-opticon-fix-control-message-timeouts.patch [new file with mode: 0644]
queue-4.4/usb-serial-quatech2-handle-unbound-ports.patch [new file with mode: 0644]
queue-4.4/usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch [new file with mode: 0644]
queue-4.4/usb-serial-suppress-driver-bind-attributes.patch [new file with mode: 0644]

diff --git a/queue-4.4/scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch b/queue-4.4/scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch
new file mode 100644 (file)
index 0000000..d92c417
--- /dev/null
@@ -0,0 +1,577 @@
+From 28d76df18f0ad5bcf5fa48510b225f0ed262a99b Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Tue, 14 Jan 2020 15:34:14 +0300
+Subject: scsi: mptfusion: Fix double fetch bug in ioctl
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 28d76df18f0ad5bcf5fa48510b225f0ed262a99b upstream.
+
+Tom Hatskevich reported that we look up "iocp" then, in the called
+functions we do a second copy_from_user() and look it up again.
+The problem that could cause is:
+
+drivers/message/fusion/mptctl.c
+   674          /* All of these commands require an interrupt or
+   675           * are unknown/illegal.
+   676           */
+   677          if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0)
+                                               ^^^^
+We take this lock.
+
+   678                  return ret;
+   679
+   680          if (cmd == MPTFWDOWNLOAD)
+   681                  ret = mptctl_fw_download(arg);
+                                                 ^^^
+Then the user memory changes and we look up "iocp" again but a different
+one so now we are holding the incorrect lock and have a race condition.
+
+   682          else if (cmd == MPTCOMMAND)
+   683                  ret = mptctl_mpt_command(arg);
+
+The security impact of this bug is not as bad as it could have been
+because these operations are all privileged and root already has
+enormous destructive power.  But it's still worth fixing.
+
+This patch passes the "iocp" pointer to the functions to avoid the
+second lookup.  That deletes 100 lines of code from the driver so
+it's a nice clean up as well.
+
+Link: https://lore.kernel.org/r/20200114123414.GA7957@kadam
+Reported-by: Tom Hatskevich <tom2001tom.23@gmail.com>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/message/fusion/mptctl.c |  213 +++++++++-------------------------------
+ 1 file changed, 50 insertions(+), 163 deletions(-)
+
+--- a/drivers/message/fusion/mptctl.c
++++ b/drivers/message/fusion/mptctl.c
+@@ -100,19 +100,19 @@ struct buflist {
+  * Function prototypes. Called from OS entry point mptctl_ioctl.
+  * arg contents specific to function.
+  */
+-static int mptctl_fw_download(unsigned long arg);
+-static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
+-static int mptctl_gettargetinfo(unsigned long arg);
+-static int mptctl_readtest(unsigned long arg);
+-static int mptctl_mpt_command(unsigned long arg);
+-static int mptctl_eventquery(unsigned long arg);
+-static int mptctl_eventenable(unsigned long arg);
+-static int mptctl_eventreport(unsigned long arg);
+-static int mptctl_replace_fw(unsigned long arg);
+-
+-static int mptctl_do_reset(unsigned long arg);
+-static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
+-static int mptctl_hp_targetinfo(unsigned long arg);
++static int mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_getiocinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
++static int mptctl_gettargetinfo(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_readtest(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_mpt_command(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_eventquery(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_eventenable(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_eventreport(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_replace_fw(MPT_ADAPTER *iocp, unsigned long arg);
++
++static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg);
++static int mptctl_hp_hostinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
++static int mptctl_hp_targetinfo(MPT_ADAPTER *iocp, unsigned long arg);
+ static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+ static void mptctl_remove(struct pci_dev *);
+@@ -123,8 +123,8 @@ static long compat_mpctl_ioctl(struct fi
+ /*
+  * Private function calls.
+  */
+-static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
+-static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
++static int mptctl_do_mpt_command(MPT_ADAPTER *iocp, struct mpt_ioctl_command karg, void __user *mfPtr);
++static int mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen);
+ static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
+               struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
+ static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
+@@ -656,19 +656,19 @@ __mptctl_ioctl(struct file *file, unsign
+        * by TM and FW reloads.
+        */
+       if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) {
+-              return mptctl_getiocinfo(arg, _IOC_SIZE(cmd));
++              return mptctl_getiocinfo(iocp, arg, _IOC_SIZE(cmd));
+       } else if (cmd == MPTTARGETINFO) {
+-              return mptctl_gettargetinfo(arg);
++              return mptctl_gettargetinfo(iocp, arg);
+       } else if (cmd == MPTTEST) {
+-              return mptctl_readtest(arg);
++              return mptctl_readtest(iocp, arg);
+       } else if (cmd == MPTEVENTQUERY) {
+-              return mptctl_eventquery(arg);
++              return mptctl_eventquery(iocp, arg);
+       } else if (cmd == MPTEVENTENABLE) {
+-              return mptctl_eventenable(arg);
++              return mptctl_eventenable(iocp, arg);
+       } else if (cmd == MPTEVENTREPORT) {
+-              return mptctl_eventreport(arg);
++              return mptctl_eventreport(iocp, arg);
+       } else if (cmd == MPTFWREPLACE) {
+-              return mptctl_replace_fw(arg);
++              return mptctl_replace_fw(iocp, arg);
+       }
+       /* All of these commands require an interrupt or
+@@ -678,15 +678,15 @@ __mptctl_ioctl(struct file *file, unsign
+               return ret;
+       if (cmd == MPTFWDOWNLOAD)
+-              ret = mptctl_fw_download(arg);
++              ret = mptctl_fw_download(iocp, arg);
+       else if (cmd == MPTCOMMAND)
+-              ret = mptctl_mpt_command(arg);
++              ret = mptctl_mpt_command(iocp, arg);
+       else if (cmd == MPTHARDRESET)
+-              ret = mptctl_do_reset(arg);
++              ret = mptctl_do_reset(iocp, arg);
+       else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
+-              ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
++              ret = mptctl_hp_hostinfo(iocp, arg, _IOC_SIZE(cmd));
+       else if (cmd == HP_GETTARGETINFO)
+-              ret = mptctl_hp_targetinfo(arg);
++              ret = mptctl_hp_targetinfo(iocp, arg);
+       else
+               ret = -EINVAL;
+@@ -705,11 +705,10 @@ mptctl_ioctl(struct file *file, unsigned
+       return ret;
+ }
+-static int mptctl_do_reset(unsigned long arg)
++static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg)
+ {
+       struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
+       struct mpt_ioctl_diag_reset krinfo;
+-      MPT_ADAPTER             *iocp;
+       if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - "
+@@ -718,12 +717,6 @@ static int mptctl_do_reset(unsigned long
+               return -EFAULT;
+       }
+-      if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
+-              printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
+-                              __FILE__, __LINE__, krinfo.hdr.iocnum);
+-              return -ENODEV; /* (-6) No such device or address */
+-      }
+-
+       dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n",
+           iocp->name));
+@@ -754,7 +747,7 @@ static int mptctl_do_reset(unsigned long
+  *            -ENOMSG if FW upload returned bad status
+  */
+ static int
+-mptctl_fw_download(unsigned long arg)
++mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg)
+ {
+       struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
+       struct mpt_fw_xfer       kfwdl;
+@@ -766,7 +759,7 @@ mptctl_fw_download(unsigned long arg)
+               return -EFAULT;
+       }
+-      return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
++      return mptctl_do_fw_download(iocp, kfwdl.bufp, kfwdl.fwlen);
+ }
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+@@ -784,11 +777,10 @@ mptctl_fw_download(unsigned long arg)
+  *            -ENOMSG if FW upload returned bad status
+  */
+ static int
+-mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
++mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen)
+ {
+       FWDownload_t            *dlmsg;
+       MPT_FRAME_HDR           *mf;
+-      MPT_ADAPTER             *iocp;
+       FWDownloadTCSGE_t       *ptsge;
+       MptSge_t                *sgl, *sgIn;
+       char                    *sgOut;
+@@ -808,17 +800,10 @@ mptctl_do_fw_download(int ioc, char __us
+       pFWDownloadReply_t       ReplyMsg = NULL;
+       unsigned long            timeleft;
+-      if (mpt_verify_adapter(ioc, &iocp) < 0) {
+-              printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
+-                               ioc);
+-              return -ENODEV; /* (-6) No such device or address */
+-      } else {
+-
+-              /*  Valid device. Get a message frame and construct the FW download message.
+-              */
+-              if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+-                      return -EAGAIN;
+-      }
++      /*  Valid device. Get a message frame and construct the FW download message.
++      */
++      if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
++              return -EAGAIN;
+       dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
+           "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
+@@ -826,8 +811,6 @@ mptctl_do_fw_download(int ioc, char __us
+           iocp->name, ufwbuf));
+       dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
+           iocp->name, (int)fwlen));
+-      dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc   = %04xh\n",
+-          iocp->name, ioc));
+       dlmsg = (FWDownload_t*) mf;
+       ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
+@@ -1238,13 +1221,11 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_
+  *            -ENODEV  if no such device/adapter
+  */
+ static int
+-mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
++mptctl_getiocinfo (MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
+ {
+       struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_iocinfo *karg;
+-      MPT_ADAPTER             *ioc;
+       struct pci_dev          *pdev;
+-      int                     iocnum;
+       unsigned int            port;
+       int                     cim_rev;
+       struct scsi_device      *sdev;
+@@ -1272,14 +1253,6 @@ mptctl_getiocinfo (unsigned long arg, un
+               return PTR_ERR(karg);
+       }
+-      if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              kfree(karg);
+-              return -ENODEV;
+-      }
+-
+       /* Verify the data transfer size is correct. */
+       if (karg->hdr.maxDataSize != data_size) {
+               printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
+@@ -1385,15 +1358,13 @@ mptctl_getiocinfo (unsigned long arg, un
+  *            -ENODEV  if no such device/adapter
+  */
+ static int
+-mptctl_gettargetinfo (unsigned long arg)
++mptctl_gettargetinfo (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_targetinfo karg;
+-      MPT_ADAPTER             *ioc;
+       VirtDevice              *vdevice;
+       char                    *pmem;
+       int                     *pdata;
+-      int                     iocnum;
+       int                     numDevices = 0;
+       int                     lun;
+       int                     maxWordsLeft;
+@@ -1408,13 +1379,6 @@ mptctl_gettargetinfo (unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+-
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n",
+           ioc->name));
+       /* Get the port number and set the maximum number of bytes
+@@ -1510,12 +1474,10 @@ mptctl_gettargetinfo (unsigned long arg)
+  *            -ENODEV  if no such device/adapter
+  */
+ static int
+-mptctl_readtest (unsigned long arg)
++mptctl_readtest (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       struct mpt_ioctl_test __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_test    karg;
+-      MPT_ADAPTER *ioc;
+-      int iocnum;
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - "
+@@ -1524,13 +1486,6 @@ mptctl_readtest (unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+-
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n",
+           ioc->name));
+       /* Fill in the data and return the structure to the calling
+@@ -1571,12 +1526,10 @@ mptctl_readtest (unsigned long arg)
+  *            -ENODEV  if no such device/adapter
+  */
+ static int
+-mptctl_eventquery (unsigned long arg)
++mptctl_eventquery (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_eventquery      karg;
+-      MPT_ADAPTER *ioc;
+-      int iocnum;
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - "
+@@ -1585,13 +1538,6 @@ mptctl_eventquery (unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+-
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n",
+           ioc->name));
+       karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
+@@ -1610,12 +1556,10 @@ mptctl_eventquery (unsigned long arg)
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static int
+-mptctl_eventenable (unsigned long arg)
++mptctl_eventenable (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_eventenable     karg;
+-      MPT_ADAPTER *ioc;
+-      int iocnum;
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
+               printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - "
+@@ -1624,13 +1568,6 @@ mptctl_eventenable (unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+-
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n",
+           ioc->name));
+       if (ioc->events == NULL) {
+@@ -1658,12 +1595,10 @@ mptctl_eventenable (unsigned long arg)
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static int
+-mptctl_eventreport (unsigned long arg)
++mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_eventreport     karg;
+-      MPT_ADAPTER              *ioc;
+-      int                      iocnum;
+       int                      numBytes, maxEvents, max;
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
+@@ -1673,12 +1608,6 @@ mptctl_eventreport (unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
+           ioc->name));
+@@ -1712,12 +1641,10 @@ mptctl_eventreport (unsigned long arg)
+ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+ static int
+-mptctl_replace_fw (unsigned long arg)
++mptctl_replace_fw (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_replace_fw      karg;
+-      MPT_ADAPTER              *ioc;
+-      int                      iocnum;
+       int                      newFwSize;
+       if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
+@@ -1727,13 +1654,6 @@ mptctl_replace_fw (unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+-
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n",
+           ioc->name));
+       /* If caching FW, Free the old FW image
+@@ -1780,12 +1700,10 @@ mptctl_replace_fw (unsigned long arg)
+  *            -ENOMEM if memory allocation error
+  */
+ static int
+-mptctl_mpt_command (unsigned long arg)
++mptctl_mpt_command (MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       struct mpt_ioctl_command __user *uarg = (void __user *) arg;
+       struct mpt_ioctl_command  karg;
+-      MPT_ADAPTER     *ioc;
+-      int             iocnum;
+       int             rc;
+@@ -1796,14 +1714,7 @@ mptctl_mpt_command (unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+-
+-      rc = mptctl_do_mpt_command (karg, &uarg->MF);
++      rc = mptctl_do_mpt_command (ioc, karg, &uarg->MF);
+       return rc;
+ }
+@@ -1821,9 +1732,8 @@ mptctl_mpt_command (unsigned long arg)
+  *            -EPERM if SCSI I/O and target is untagged
+  */
+ static int
+-mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
++mptctl_do_mpt_command (MPT_ADAPTER *ioc, struct mpt_ioctl_command karg, void __user *mfPtr)
+ {
+-      MPT_ADAPTER     *ioc;
+       MPT_FRAME_HDR   *mf = NULL;
+       MPIHeader_t     *hdr;
+       char            *psge;
+@@ -1832,7 +1742,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+       dma_addr_t      dma_addr_in;
+       dma_addr_t      dma_addr_out;
+       int             sgSize = 0;     /* Num SG elements */
+-      int             iocnum, flagsLength;
++      int             flagsLength;
+       int             sz, rc = 0;
+       int             msgContext;
+       u16             req_idx;
+@@ -1847,13 +1757,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_
+       bufIn.kptr = bufOut.kptr = NULL;
+       bufIn.len = bufOut.len = 0;
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+-
+       spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
+       if (ioc->ioc_reset_in_progress) {
+               spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
+@@ -2418,17 +2321,15 @@ done_free_mem:
+  *            -ENOMEM if memory allocation error
+  */
+ static int
+-mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
++mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
+ {
+       hp_host_info_t  __user *uarg = (void __user *) arg;
+-      MPT_ADAPTER             *ioc;
+       struct pci_dev          *pdev;
+       char                    *pbuf=NULL;
+       dma_addr_t              buf_dma;
+       hp_host_info_t          karg;
+       CONFIGPARMS             cfg;
+       ConfigPageHeader_t      hdr;
+-      int                     iocnum;
+       int                     rc, cim_rev;
+       ToolboxIstwiReadWriteRequest_t  *IstwiRWRequest;
+       MPT_FRAME_HDR           *mf = NULL;
+@@ -2452,12 +2353,6 @@ mptctl_hp_hostinfo(unsigned long arg, un
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-          (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
+           ioc->name));
+@@ -2670,15 +2565,13 @@ retry_wait:
+  *            -ENOMEM if memory allocation error
+  */
+ static int
+-mptctl_hp_targetinfo(unsigned long arg)
++mptctl_hp_targetinfo(MPT_ADAPTER *ioc, unsigned long arg)
+ {
+       hp_target_info_t __user *uarg = (void __user *) arg;
+       SCSIDevicePage0_t       *pg0_alloc;
+       SCSIDevicePage3_t       *pg3_alloc;
+-      MPT_ADAPTER             *ioc;
+       MPT_SCSI_HOST           *hd = NULL;
+       hp_target_info_t        karg;
+-      int                     iocnum;
+       int                     data_sz;
+       dma_addr_t              page_dma;
+       CONFIGPARMS             cfg;
+@@ -2692,12 +2585,6 @@ mptctl_hp_targetinfo(unsigned long arg)
+               return -EFAULT;
+       }
+-      if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
+-              (ioc == NULL)) {
+-              printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
+-                              __FILE__, __LINE__, iocnum);
+-              return -ENODEV;
+-      }
+       if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
+               return -EINVAL;
+       dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
+@@ -2865,7 +2752,7 @@ compat_mptfwxfer_ioctl(struct file *filp
+       kfw.fwlen = kfw32.fwlen;
+       kfw.bufp = compat_ptr(kfw32.bufp);
+-      ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
++      ret = mptctl_do_fw_download(iocp, kfw.bufp, kfw.fwlen);
+       mutex_unlock(&iocp->ioctl_cmds.mutex);
+@@ -2919,7 +2806,7 @@ compat_mpt_command(struct file *filp, un
+       /* Pass new structure to do_mpt_command
+        */
+-      ret = mptctl_do_mpt_command (karg, &uarg->MF);
++      ret = mptctl_do_mpt_command (iocp, karg, &uarg->MF);
+       mutex_unlock(&iocp->ioctl_cmds.mutex);
index f490716f9c70fb0bf2c4873a95cc1b3820621999..ea71f595498d6679983b1774f64754a7d2997faa 100644 (file)
@@ -40,3 +40,10 @@ ocfs2-call-journal-flush-to-mark-journal-as-empty-af.patch
 alsa-seq-fix-racy-access-for-queue-timer-in-proc-read.patch
 fix-built-in-early-load-intel-microcode-alignment.patch
 block-fix-an-integer-overflow-in-logical-block-size.patch
+usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch
+usb-serial-opticon-fix-control-message-timeouts.patch
+usb-serial-suppress-driver-bind-attributes.patch
+usb-serial-ch341-handle-unbound-port-at-reset_resume.patch
+usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch
+usb-serial-quatech2-handle-unbound-ports.patch
+scsi-mptfusion-fix-double-fetch-bug-in-ioctl.patch
diff --git a/queue-4.4/usb-serial-ch341-handle-unbound-port-at-reset_resume.patch b/queue-4.4/usb-serial-ch341-handle-unbound-port-at-reset_resume.patch
new file mode 100644 (file)
index 0000000..b665e00
--- /dev/null
@@ -0,0 +1,40 @@
+From 4d5ef53f75c22d28f490bcc5c771fcc610a9afa4 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 10:50:22 +0100
+Subject: USB: serial: ch341: handle unbound port at reset_resume
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 4d5ef53f75c22d28f490bcc5c771fcc610a9afa4 upstream.
+
+Check for NULL port data in reset_resume() to avoid dereferencing a NULL
+pointer in case the port device isn't bound to a driver (e.g. after a
+failed control request at port probe).
+
+Fixes: 1ded7ea47b88 ("USB: ch341 serial: fix port number changed after resume")
+Cc: stable <stable@vger.kernel.org>     # 2.6.30
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/ch341.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/ch341.c
++++ b/drivers/usb/serial/ch341.c
+@@ -555,9 +555,13 @@ static int ch341_tiocmget(struct tty_str
+ static int ch341_reset_resume(struct usb_serial *serial)
+ {
+       struct usb_serial_port *port = serial->port[0];
+-      struct ch341_private *priv = usb_get_serial_port_data(port);
++      struct ch341_private *priv;
+       int ret;
++      priv = usb_get_serial_port_data(port);
++      if (!priv)
++              return 0;
++
+       /* reconfigure ch341 serial port after bus-reset */
+       ch341_configure(serial->dev, priv);
diff --git a/queue-4.4/usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch b/queue-4.4/usb-serial-io_edgeport-add-missing-active-port-sanity-check.patch
new file mode 100644 (file)
index 0000000..fa17999
--- /dev/null
@@ -0,0 +1,67 @@
+From 1568c58d11a7c851bd09341aeefd6a1c308ac40d Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 10:50:24 +0100
+Subject: USB: serial: io_edgeport: add missing active-port sanity check
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 1568c58d11a7c851bd09341aeefd6a1c308ac40d upstream.
+
+The driver receives the active port number from the device, but never
+made sure that the port number was valid. This could lead to a
+NULL-pointer dereference or memory corruption in case a device sends
+data for an invalid port.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/io_edgeport.c |   12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -1666,7 +1666,8 @@ static void edge_break(struct tty_struct
+ static void process_rcvd_data(struct edgeport_serial *edge_serial,
+                               unsigned char *buffer, __u16 bufferLength)
+ {
+-      struct device *dev = &edge_serial->serial->dev->dev;
++      struct usb_serial *serial = edge_serial->serial;
++      struct device *dev = &serial->dev->dev;
+       struct usb_serial_port *port;
+       struct edgeport_port *edge_port;
+       __u16 lastBufferLength;
+@@ -1771,9 +1772,8 @@ static void process_rcvd_data(struct edg
+                       /* spit this data back into the tty driver if this
+                          port is open */
+-                      if (rxLen) {
+-                              port = edge_serial->serial->port[
+-                                                      edge_serial->rxPort];
++                      if (rxLen && edge_serial->rxPort < serial->num_ports) {
++                              port = serial->port[edge_serial->rxPort];
+                               edge_port = usb_get_serial_port_data(port);
+                               if (edge_port->open) {
+                                       dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
+@@ -1783,8 +1783,8 @@ static void process_rcvd_data(struct edg
+                                                       rxLen);
+                                       edge_port->port->icount.rx += rxLen;
+                               }
+-                              buffer += rxLen;
+                       }
++                      buffer += rxLen;
+                       break;
+               case EXPECT_HDR3:       /* Expect 3rd byte of status header */
+@@ -1819,6 +1819,8 @@ static void process_rcvd_status(struct e
+       __u8 code = edge_serial->rxStatusCode;
+       /* switch the port pointer to the one being currently talked about */
++      if (edge_serial->rxPort >= edge_serial->serial->num_ports)
++              return;
+       port = edge_serial->serial->port[edge_serial->rxPort];
+       edge_port = usb_get_serial_port_data(port);
+       if (edge_port == NULL) {
diff --git a/queue-4.4/usb-serial-opticon-fix-control-message-timeouts.patch b/queue-4.4/usb-serial-opticon-fix-control-message-timeouts.patch
new file mode 100644 (file)
index 0000000..a057c00
--- /dev/null
@@ -0,0 +1,39 @@
+From 5e28055f340275a8616eee88ef19186631b4d136 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 13 Jan 2020 18:22:13 +0100
+Subject: USB: serial: opticon: fix control-message timeouts
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 5e28055f340275a8616eee88ef19186631b4d136 upstream.
+
+The driver was issuing synchronous uninterruptible control requests
+without using a timeout. This could lead to the driver hanging
+on open() or tiocmset() due to a malfunctioning (or malicious) device
+until the device is physically disconnected.
+
+The USB upper limit of five seconds per request should be more than
+enough.
+
+Fixes: 309a057932ab ("USB: opticon: add rts and cts support")
+Cc: stable <stable@vger.kernel.org>     # 2.6.39
+Cc: Martin Jansen <martin.jansen@opticon.com>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/opticon.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/serial/opticon.c
++++ b/drivers/usb/serial/opticon.c
+@@ -116,7 +116,7 @@ static int send_control_msg(struct usb_s
+       retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               requesttype,
+                               USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+-                              0, 0, buffer, 1, 0);
++                              0, 0, buffer, 1, USB_CTRL_SET_TIMEOUT);
+       kfree(buffer);
+       if (retval < 0)
diff --git a/queue-4.4/usb-serial-quatech2-handle-unbound-ports.patch b/queue-4.4/usb-serial-quatech2-handle-unbound-ports.patch
new file mode 100644 (file)
index 0000000..f677ead
--- /dev/null
@@ -0,0 +1,52 @@
+From 9715a43eea77e42678a1002623f2d9a78f5b81a1 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 17 Jan 2020 15:35:26 +0100
+Subject: USB: serial: quatech2: handle unbound ports
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 9715a43eea77e42678a1002623f2d9a78f5b81a1 upstream.
+
+Check for NULL port data in the modem- and line-status handlers to avoid
+dereferencing a NULL pointer in the unlikely case where a port device
+isn't bound to a driver (e.g. after an allocation failure on port
+probe).
+
+Note that the other (stubbed) event handlers qt2_process_xmit_empty()
+and qt2_process_flush() would need similar sanity checks in case they
+are ever implemented.
+
+Fixes: f7a33e608d9a ("USB: serial: add quatech2 usb to serial driver")
+Cc: stable <stable@vger.kernel.org>     # 3.5
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/quatech2.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/usb/serial/quatech2.c
++++ b/drivers/usb/serial/quatech2.c
+@@ -872,7 +872,10 @@ static void qt2_update_msr(struct usb_se
+       u8 newMSR = (u8) *ch;
+       unsigned long flags;
++      /* May be called from qt2_process_read_urb() for an unbound port. */
+       port_priv = usb_get_serial_port_data(port);
++      if (!port_priv)
++              return;
+       spin_lock_irqsave(&port_priv->lock, flags);
+       port_priv->shadowMSR = newMSR;
+@@ -900,7 +903,10 @@ static void qt2_update_lsr(struct usb_se
+       unsigned long flags;
+       u8 newLSR = (u8) *ch;
++      /* May be called from qt2_process_read_urb() for an unbound port. */
+       port_priv = usb_get_serial_port_data(port);
++      if (!port_priv)
++              return;
+       if (newLSR & UART_LSR_BI)
+               newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
diff --git a/queue-4.4/usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch b/queue-4.4/usb-serial-simple-add-motorola-solutions-tetra-mtp3xxx-and-mtp85xx.patch
new file mode 100644 (file)
index 0000000..04300ca
--- /dev/null
@@ -0,0 +1,211 @@
+From 260e41ac4dd3e5acb90be624c03ba7f019615b75 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jer=C3=B3nimo=20Borque?= <jeronimo@borque.com.ar>
+Date: Thu, 9 Jan 2020 12:23:34 -0300
+Subject: USB: serial: simple: Add Motorola Solutions TETRA MTP3xxx and MTP85xx
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jerónimo Borque <jeronimo@borque.com.ar>
+
+commit 260e41ac4dd3e5acb90be624c03ba7f019615b75 upstream.
+
+Add device-ids for the Motorola Solutions TETRA radios MTP3xxx series
+and MTP85xx series
+
+$ lsusb -vd 0cad:
+
+Bus 001 Device 009: ID 0cad:9015 Motorola CGISS TETRA PEI interface
+Device Descriptor:
+  bLength                18
+  bDescriptorType         1
+  bcdUSB               2.00
+  bDeviceClass            0
+  bDeviceSubClass         0
+  bDeviceProtocol         0
+  bMaxPacketSize0        64
+  idVendor           0x0cad Motorola CGISS
+  idProduct          0x9015
+  bcdDevice           24.16
+  iManufacturer           1
+  iProduct                2
+  iSerial                 0
+  bNumConfigurations      1
+  Configuration Descriptor:
+    bLength                 9
+    bDescriptorType         2
+    wTotalLength       0x0037
+    bNumInterfaces          2
+    bConfigurationValue     1
+    iConfiguration          3
+    bmAttributes         0x80
+      (Bus Powered)
+    MaxPower              500mA
+    Interface Descriptor:
+      bLength                 9
+      bDescriptorType         4
+      bInterfaceNumber        0
+      bAlternateSetting       0
+      bNumEndpoints           2
+      bInterfaceClass       255 Vendor Specific Class
+      bInterfaceSubClass      0
+      bInterfaceProtocol      0
+      iInterface              0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x81  EP 1 IN
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0040  1x 64 bytes
+        bInterval               0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x01  EP 1 OUT
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0040  1x 64 bytes
+        bInterval               0
+    Interface Descriptor:
+      bLength                 9
+      bDescriptorType         4
+      bInterfaceNumber        1
+      bAlternateSetting       0
+      bNumEndpoints           2
+      bInterfaceClass       255 Vendor Specific Class
+      bInterfaceSubClass      0
+      bInterfaceProtocol      0
+      iInterface              0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x82  EP 2 IN
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0040  1x 64 bytes
+        bInterval               0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x02  EP 2 OUT
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0040  1x 64 bytes
+        bInterval               0
+
+Bus 001 Device 010: ID 0cad:9013 Motorola CGISS TETRA PEI interface
+Device Descriptor:
+  bLength                18
+  bDescriptorType         1
+  bcdUSB               2.00
+  bDeviceClass            0
+  bDeviceSubClass         0
+  bDeviceProtocol         0
+  bMaxPacketSize0        64
+  idVendor           0x0cad Motorola CGISS
+  idProduct          0x9013
+  bcdDevice           24.16
+  iManufacturer           1
+  iProduct                2
+  iSerial                 0
+  bNumConfigurations      1
+  Configuration Descriptor:
+    bLength                 9
+    bDescriptorType         2
+    wTotalLength       0x0037
+    bNumInterfaces          2
+    bConfigurationValue     1
+    iConfiguration          3
+    bmAttributes         0x80
+      (Bus Powered)
+    MaxPower              500mA
+    Interface Descriptor:
+      bLength                 9
+      bDescriptorType         4
+      bInterfaceNumber        0
+      bAlternateSetting       0
+      bNumEndpoints           2
+      bInterfaceClass       255 Vendor Specific Class
+      bInterfaceSubClass      0
+      bInterfaceProtocol      0
+      iInterface              0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x81  EP 1 IN
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0200  1x 512 bytes
+        bInterval               0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x01  EP 1 OUT
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0200  1x 512 bytes
+        bInterval               0
+    Interface Descriptor:
+      bLength                 9
+      bDescriptorType         4
+      bInterfaceNumber        1
+      bAlternateSetting       0
+      bNumEndpoints           2
+      bInterfaceClass       255 Vendor Specific Class
+      bInterfaceSubClass      0
+      bInterfaceProtocol      0
+      iInterface              0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x82  EP 2 IN
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0200  1x 512 bytes
+        bInterval               0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x02  EP 2 OUT
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0200  1x 512 bytes
+        bInterval               0
+
+Signed-off-by: Jerónimo Borque <jeronimo@borque.com.ar>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/usb-serial-simple.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/usb-serial-simple.c
++++ b/drivers/usb/serial/usb-serial-simple.c
+@@ -89,6 +89,8 @@ DEVICE(moto_modem, MOTO_IDS);
+ #define MOTOROLA_TETRA_IDS()                  \
+       { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
+       { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
++      { USB_DEVICE(0x0cad, 0x9013) }, /* MTP3xxx */ \
++      { USB_DEVICE(0x0cad, 0x9015) }, /* MTP85xx */ \
+       { USB_DEVICE(0x0cad, 0x9016) }  /* TPG2200 */
+ DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
diff --git a/queue-4.4/usb-serial-suppress-driver-bind-attributes.patch b/queue-4.4/usb-serial-suppress-driver-bind-attributes.patch
new file mode 100644 (file)
index 0000000..fdc47d0
--- /dev/null
@@ -0,0 +1,41 @@
+From fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Thu, 16 Jan 2020 17:07:05 +0100
+Subject: USB: serial: suppress driver bind attributes
+
+From: Johan Hovold <johan@kernel.org>
+
+commit fdb838efa31e1ed9a13ae6ad0b64e30fdbd00570 upstream.
+
+USB-serial drivers must not be unbound from their ports before the
+corresponding USB driver is unbound from the parent interface so
+suppress the bind and unbind attributes.
+
+Unbinding a serial driver while it's port is open is a sure way to
+trigger a crash as any driver state is released on unbind while port
+hangup is handled on the parent USB interface level. Drivers for
+multiport devices where ports share a resource such as an interrupt
+endpoint also generally cannot handle individual ports going away.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/usb-serial.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/serial/usb-serial.c
++++ b/drivers/usb/serial/usb-serial.c
+@@ -1350,6 +1350,9 @@ static int usb_serial_register(struct us
+               return -EINVAL;
+       }
++      /* Prevent individual ports from being unbound. */
++      driver->driver.suppress_bind_attrs = true;
++
+       usb_serial_operations_init(driver);
+       /* Add this device to our list of devices */