]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Feb 2018 16:30:29 +0000 (17:30 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Feb 2018 16:30:29 +0000 (17:30 +0100)
added patches:
cifs-fix-autonegotiate-security-settings-mismatch.patch
cifs-fix-missing-put_xid-in-cifs_file_strict_mmap.patch
cifs-zero-sensitive-data-when-freeing.patch
dccp-cve-2017-8824-use-after-free-in-dccp-code.patch
media-dvb-usb-v2-lmedm04-improve-logic-checking-of-warm-start.patch
media-dvb-usb-v2-lmedm04-move-ts2020-attach-to-dm04_lme2510_tuner.patch
posix-timer-properly-check-sigevent-sigev_notify.patch
usb-usbip-fix-possible-deadlocks-reported-by-lockdep.patch
usbip-fix-potential-format-overflow-in-userspace-tools.patch
usbip-fix-stub_rx-get_pipe-to-validate-endpoint-number.patch
usbip-fix-stub_rx-harden-cmd_submit-path-to-handle-malicious-input.patch
usbip-prevent-leaking-socket-pointer-address-in-messages.patch
usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch
usbip-stub-stop-printing-kernel-pointer-addresses-in-messages.patch
usbip-vhci-hcd-add-usb3-superspeed-support.patch
usbip-vhci-stop-printing-kernel-pointer-addresses-in-messages.patch

17 files changed:
queue-3.18/cifs-fix-autonegotiate-security-settings-mismatch.patch [new file with mode: 0644]
queue-3.18/cifs-fix-missing-put_xid-in-cifs_file_strict_mmap.patch [new file with mode: 0644]
queue-3.18/cifs-zero-sensitive-data-when-freeing.patch [new file with mode: 0644]
queue-3.18/dccp-cve-2017-8824-use-after-free-in-dccp-code.patch [new file with mode: 0644]
queue-3.18/media-dvb-usb-v2-lmedm04-improve-logic-checking-of-warm-start.patch [new file with mode: 0644]
queue-3.18/media-dvb-usb-v2-lmedm04-move-ts2020-attach-to-dm04_lme2510_tuner.patch [new file with mode: 0644]
queue-3.18/posix-timer-properly-check-sigevent-sigev_notify.patch [new file with mode: 0644]
queue-3.18/series
queue-3.18/usb-usbip-fix-possible-deadlocks-reported-by-lockdep.patch [new file with mode: 0644]
queue-3.18/usbip-fix-potential-format-overflow-in-userspace-tools.patch [new file with mode: 0644]
queue-3.18/usbip-fix-stub_rx-get_pipe-to-validate-endpoint-number.patch [new file with mode: 0644]
queue-3.18/usbip-fix-stub_rx-harden-cmd_submit-path-to-handle-malicious-input.patch [new file with mode: 0644]
queue-3.18/usbip-prevent-leaking-socket-pointer-address-in-messages.patch [new file with mode: 0644]
queue-3.18/usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch [new file with mode: 0644]
queue-3.18/usbip-stub-stop-printing-kernel-pointer-addresses-in-messages.patch [new file with mode: 0644]
queue-3.18/usbip-vhci-hcd-add-usb3-superspeed-support.patch [new file with mode: 0644]
queue-3.18/usbip-vhci-stop-printing-kernel-pointer-addresses-in-messages.patch [new file with mode: 0644]

diff --git a/queue-3.18/cifs-fix-autonegotiate-security-settings-mismatch.patch b/queue-3.18/cifs-fix-autonegotiate-security-settings-mismatch.patch
new file mode 100644 (file)
index 0000000..be3f3d7
--- /dev/null
@@ -0,0 +1,47 @@
+From 9aca7e454415f7878b28524e76bebe1170911a88 Mon Sep 17 00:00:00 2001
+From: Daniel N Pettersson <danielnp@axis.com>
+Date: Thu, 11 Jan 2018 16:00:12 +0100
+Subject: cifs: Fix autonegotiate security settings mismatch
+
+From: Daniel N Pettersson <danielnp@axis.com>
+
+commit 9aca7e454415f7878b28524e76bebe1170911a88 upstream.
+
+Autonegotiation gives a security settings mismatch error if the SMB
+server selects an SMBv3 dialect that isn't SMB3.02. The exact error is
+"protocol revalidation - security settings mismatch".
+This can be tested using Samba v4.2 or by setting the global Samba
+setting max protocol = SMB3_00.
+
+The check that fails in smb3_validate_negotiate is the dialect
+verification of the negotiate info response. This is because it tries
+to verify against the protocol_id in the global smbdefault_values. The
+protocol_id in smbdefault_values is SMB3.02.
+In SMB2_negotiate the protocol_id in smbdefault_values isn't updated,
+it is global so it probably shouldn't be, but server->dialect is.
+
+This patch changes the check in smb3_validate_negotiate to use
+server->dialect instead of server->vals->protocol_id. The patch works
+with autonegotiate and when using a specific version in the vers mount
+option.
+
+Signed-off-by: Daniel N Pettersson <danielnp@axis.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2pdu.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -507,8 +507,7 @@ int smb3_validate_negotiate(const unsign
+       }
+       /* check validate negotiate info response matches what we got earlier */
+-      if (pneg_rsp->Dialect !=
+-                      cpu_to_le16(tcon->ses->server->vals->protocol_id))
++      if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect))
+               goto vneg_out;
+       if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode))
diff --git a/queue-3.18/cifs-fix-missing-put_xid-in-cifs_file_strict_mmap.patch b/queue-3.18/cifs-fix-missing-put_xid-in-cifs_file_strict_mmap.patch
new file mode 100644 (file)
index 0000000..14a370b
--- /dev/null
@@ -0,0 +1,74 @@
+From f04a703c3d613845ae3141bfaf223489de8ab3eb Mon Sep 17 00:00:00 2001
+From: Matthew Wilcox <mawilcox@microsoft.com>
+Date: Fri, 15 Dec 2017 12:48:32 -0800
+Subject: cifs: Fix missing put_xid in cifs_file_strict_mmap
+
+From: Matthew Wilcox <mawilcox@microsoft.com>
+
+commit f04a703c3d613845ae3141bfaf223489de8ab3eb upstream.
+
+If cifs_zap_mapping() returned an error, we would return without putting
+the xid that we got earlier.  Restructure cifs_file_strict_mmap() and
+cifs_file_mmap() to be more similar to each other and have a single
+point of return that always puts the xid.
+
+Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/file.c |   26 ++++++++++++--------------
+ 1 file changed, 12 insertions(+), 14 deletions(-)
+
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -3261,20 +3261,18 @@ static struct vm_operations_struct cifs_
+ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+-      int rc, xid;
++      int xid, rc = 0;
+       struct inode *inode = file_inode(file);
+       xid = get_xid();
+-      if (!CIFS_CACHE_READ(CIFS_I(inode))) {
++      if (!CIFS_CACHE_READ(CIFS_I(inode)))
+               rc = cifs_zap_mapping(inode);
+-              if (rc)
+-                      return rc;
+-      }
+-
+-      rc = generic_file_mmap(file, vma);
+-      if (rc == 0)
++      if (!rc)
++              rc = generic_file_mmap(file, vma);
++      if (!rc)
+               vma->vm_ops = &cifs_file_vm_ops;
++
+       free_xid(xid);
+       return rc;
+ }
+@@ -3284,16 +3282,16 @@ int cifs_file_mmap(struct file *file, st
+       int rc, xid;
+       xid = get_xid();
++
+       rc = cifs_revalidate_file(file);
+-      if (rc) {
++      if (rc)
+               cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
+                        rc);
+-              free_xid(xid);
+-              return rc;
+-      }
+-      rc = generic_file_mmap(file, vma);
+-      if (rc == 0)
++      if (!rc)
++              rc = generic_file_mmap(file, vma);
++      if (!rc)
+               vma->vm_ops = &cifs_file_vm_ops;
++
+       free_xid(xid);
+       return rc;
+ }
diff --git a/queue-3.18/cifs-zero-sensitive-data-when-freeing.patch b/queue-3.18/cifs-zero-sensitive-data-when-freeing.patch
new file mode 100644 (file)
index 0000000..5840aa3
--- /dev/null
@@ -0,0 +1,96 @@
+From 97f4b7276b829a8927ac903a119bef2f963ccc58 Mon Sep 17 00:00:00 2001
+From: Aurelien Aptel <aaptel@suse.com>
+Date: Thu, 25 Jan 2018 15:59:39 +0100
+Subject: CIFS: zero sensitive data when freeing
+
+From: Aurelien Aptel <aaptel@suse.com>
+
+commit 97f4b7276b829a8927ac903a119bef2f963ccc58 upstream.
+
+also replaces memset()+kfree() by kzfree().
+
+Signed-off-by: Aurelien Aptel <aaptel@suse.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsencrypt.c |    3 +--
+ fs/cifs/connect.c     |    6 +++---
+ fs/cifs/misc.c        |   14 ++++----------
+ 3 files changed, 8 insertions(+), 15 deletions(-)
+
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -303,9 +303,8 @@ int calc_lanman_hash(const char *passwor
+ {
+       int i;
+       int rc;
+-      char password_with_pad[CIFS_ENCPWD_SIZE];
++      char password_with_pad[CIFS_ENCPWD_SIZE] = {0};
+-      memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
+       if (password)
+               strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -1650,7 +1650,7 @@ cifs_parse_mount_options(const char *mou
+                       tmp_end++;
+                       if (!(tmp_end < end && tmp_end[1] == delim)) {
+                               /* No it is not. Set the password to NULL */
+-                              kfree(vol->password);
++                              kzfree(vol->password);
+                               vol->password = NULL;
+                               break;
+                       }
+@@ -1688,7 +1688,7 @@ cifs_parse_mount_options(const char *mou
+                                       options = end;
+                       }
+-                      kfree(vol->password);
++                      kzfree(vol->password);
+                       /* Now build new password string */
+                       temp_len = strlen(value);
+                       vol->password = kzalloc(temp_len+1, GFP_KERNEL);
+@@ -4046,7 +4046,7 @@ cifs_construct_tcon(struct cifs_sb_info
+               reset_cifs_unix_caps(0, tcon, NULL, vol_info);
+ out:
+       kfree(vol_info->username);
+-      kfree(vol_info->password);
++      kzfree(vol_info->password);
+       kfree(vol_info);
+       return tcon;
+--- a/fs/cifs/misc.c
++++ b/fs/cifs/misc.c
+@@ -99,14 +99,11 @@ sesInfoFree(struct cifs_ses *buf_to_free
+       kfree(buf_to_free->serverOS);
+       kfree(buf_to_free->serverDomain);
+       kfree(buf_to_free->serverNOS);
+-      if (buf_to_free->password) {
+-              memset(buf_to_free->password, 0, strlen(buf_to_free->password));
+-              kfree(buf_to_free->password);
+-      }
++      kzfree(buf_to_free->password);
+       kfree(buf_to_free->user_name);
+       kfree(buf_to_free->domainName);
+-      kfree(buf_to_free->auth_key.response);
+-      kfree(buf_to_free);
++      kzfree(buf_to_free->auth_key.response);
++      kzfree(buf_to_free);
+ }
+ struct cifs_tcon *
+@@ -136,10 +133,7 @@ tconInfoFree(struct cifs_tcon *buf_to_fr
+       }
+       atomic_dec(&tconInfoAllocCount);
+       kfree(buf_to_free->nativeFileSystem);
+-      if (buf_to_free->password) {
+-              memset(buf_to_free->password, 0, strlen(buf_to_free->password));
+-              kfree(buf_to_free->password);
+-      }
++      kzfree(buf_to_free->password);
+       kfree(buf_to_free);
+ }
diff --git a/queue-3.18/dccp-cve-2017-8824-use-after-free-in-dccp-code.patch b/queue-3.18/dccp-cve-2017-8824-use-after-free-in-dccp-code.patch
new file mode 100644 (file)
index 0000000..9bf5883
--- /dev/null
@@ -0,0 +1,43 @@
+From 69c64866ce072dea1d1e59a0d61e0f66c0dffb76 Mon Sep 17 00:00:00 2001
+From: Mohamed Ghannam <simo.ghannam@gmail.com>
+Date: Tue, 5 Dec 2017 20:58:35 +0000
+Subject: dccp: CVE-2017-8824: use-after-free in DCCP code
+
+From: Mohamed Ghannam <simo.ghannam@gmail.com>
+
+commit 69c64866ce072dea1d1e59a0d61e0f66c0dffb76 upstream.
+
+Whenever the sock object is in DCCP_CLOSED state,
+dccp_disconnect() must free dccps_hc_tx_ccid and
+dccps_hc_rx_ccid and set to NULL.
+
+Signed-off-by: Mohamed Ghannam <simo.ghannam@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/dccp/proto.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/dccp/proto.c
++++ b/net/dccp/proto.c
+@@ -259,6 +259,7 @@ int dccp_disconnect(struct sock *sk, int
+ {
+       struct inet_connection_sock *icsk = inet_csk(sk);
+       struct inet_sock *inet = inet_sk(sk);
++      struct dccp_sock *dp = dccp_sk(sk);
+       int err = 0;
+       const int old_state = sk->sk_state;
+@@ -278,6 +279,10 @@ int dccp_disconnect(struct sock *sk, int
+               sk->sk_err = ECONNRESET;
+       dccp_clear_xmit_timers(sk);
++      ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
++      ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
++      dp->dccps_hc_rx_ccid = NULL;
++      dp->dccps_hc_tx_ccid = NULL;
+       __skb_queue_purge(&sk->sk_receive_queue);
+       __skb_queue_purge(&sk->sk_write_queue);
diff --git a/queue-3.18/media-dvb-usb-v2-lmedm04-improve-logic-checking-of-warm-start.patch b/queue-3.18/media-dvb-usb-v2-lmedm04-improve-logic-checking-of-warm-start.patch
new file mode 100644 (file)
index 0000000..b4ba247
--- /dev/null
@@ -0,0 +1,88 @@
+From 3d932ee27e852e4904647f15b64dedca51187ad7 Mon Sep 17 00:00:00 2001
+From: Malcolm Priestley <tvboxspy@gmail.com>
+Date: Tue, 26 Sep 2017 17:10:20 -0400
+Subject: media: dvb-usb-v2: lmedm04: Improve logic checking of warm start
+
+From: Malcolm Priestley <tvboxspy@gmail.com>
+
+commit 3d932ee27e852e4904647f15b64dedca51187ad7 upstream.
+
+Warm start has no check as whether a genuine device has
+connected and proceeds to next execution path.
+
+Check device should read 0x47 at offset of 2 on USB descriptor read
+and it is the amount requested of 6 bytes.
+
+Fix for
+kasan: CONFIG_KASAN_INLINE enabled
+kasan: GPF could be caused by NULL-ptr deref or user memory access as
+
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/dvb-usb-v2/lmedm04.c |   26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
+@@ -438,18 +438,23 @@ static int lme2510_pid_filter(struct dvb
+ static int lme2510_return_status(struct dvb_usb_device *d)
+ {
+-      int ret = 0;
++      int ret;
+       u8 *data;
+-      data = kzalloc(10, GFP_KERNEL);
++      data = kzalloc(6, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+-      ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+-                      0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
+-      info("Firmware Status: %x (%x)", ret , data[2]);
++      ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
++                            0x06, 0x80, 0x0302, 0x00,
++                            data, 0x6, 200);
++      if (ret != 6)
++              ret = -EINVAL;
++      else
++              ret = data[2];
++
++      info("Firmware Status: %6ph", data);
+-      ret = (ret < 0) ? -ENODEV : data[2];
+       kfree(data);
+       return ret;
+ }
+@@ -1231,6 +1236,7 @@ static int lme2510_get_adapter_count(str
+ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name)
+ {
+       struct lme2510_state *st = d->priv;
++      int status;
+       usb_reset_configuration(d->udev);
+@@ -1239,12 +1245,16 @@ static int lme2510_identify_state(struct
+       st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware;
+-      if (lme2510_return_status(d) == 0x44) {
++      status = lme2510_return_status(d);
++      if (status == 0x44) {
+               *name = lme_firmware_switch(d, 0);
+               return COLD;
+       }
+-      return 0;
++      if (status != 0x47)
++              return -EINVAL;
++
++      return WARM;
+ }
+ static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
diff --git a/queue-3.18/media-dvb-usb-v2-lmedm04-move-ts2020-attach-to-dm04_lme2510_tuner.patch b/queue-3.18/media-dvb-usb-v2-lmedm04-move-ts2020-attach-to-dm04_lme2510_tuner.patch
new file mode 100644 (file)
index 0000000..2a4ae54
--- /dev/null
@@ -0,0 +1,72 @@
+From 7bf7a7116ed313c601307f7e585419369926ab05 Mon Sep 17 00:00:00 2001
+From: Malcolm Priestley <tvboxspy@gmail.com>
+Date: Tue, 26 Sep 2017 17:10:21 -0400
+Subject: media: dvb-usb-v2: lmedm04: move ts2020 attach to dm04_lme2510_tuner
+
+From: Malcolm Priestley <tvboxspy@gmail.com>
+
+commit 7bf7a7116ed313c601307f7e585419369926ab05 upstream.
+
+When the tuner was split from m88rs2000 the attach function is in wrong
+place.
+
+Move to dm04_lme2510_tuner to trap errors on failure and removing
+a call to lme_coldreset.
+
+Prevents driver starting up without any tuner connected.
+
+Fixes to trap for ts2020 fail.
+LME2510(C): FE Found M88RS2000
+ts2020: probe of 0-0060 failed with error -11
+...
+LME2510(C): TUN Found RS2000 tuner
+kasan: CONFIG_KASAN_INLINE enabled
+kasan: GPF could be caused by NULL-ptr deref or user memory access
+general protection fault: 0000 [#1] PREEMPT SMP KASAN
+
+Reported-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
+Tested-by: Andrey Konovalov <andreyknvl@google.com>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
+Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/media/usb/dvb-usb-v2/lmedm04.c |   13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
++++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
+@@ -1118,8 +1118,6 @@ static int dm04_lme2510_frontend_attach(
+               if (adap->fe[0]) {
+                       info("FE Found M88RS2000");
+-                      dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config,
+-                                      &d->i2c_adap);
+                       st->i2c_tuner_gate_w = 5;
+                       st->i2c_tuner_gate_r = 5;
+                       st->i2c_tuner_addr = 0x60;
+@@ -1182,17 +1180,18 @@ static int dm04_lme2510_tuner(struct dvb
+                       ret = st->tuner_config;
+               break;
+       case TUNER_RS2000:
+-              ret = st->tuner_config;
++              if (dvb_attach(ts2020_attach, adap->fe[0],
++                             &ts2020_config, &d->i2c_adap))
++                      ret = st->tuner_config;
+               break;
+       default:
+               break;
+       }
+-      if (ret)
++      if (ret) {
+               info("TUN Found %s tuner", tun_msg[ret]);
+-      else {
+-              info("TUN No tuner found --- resetting device");
+-              lme_coldreset(d);
++      } else {
++              info("TUN No tuner found");
+               return -ENODEV;
+       }
diff --git a/queue-3.18/posix-timer-properly-check-sigevent-sigev_notify.patch b/queue-3.18/posix-timer-properly-check-sigevent-sigev_notify.patch
new file mode 100644 (file)
index 0000000..e64904f
--- /dev/null
@@ -0,0 +1,110 @@
+From cef31d9af908243421258f1df35a4a644604efbe Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Fri, 15 Dec 2017 10:32:03 +0100
+Subject: posix-timer: Properly check sigevent->sigev_notify
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+commit cef31d9af908243421258f1df35a4a644604efbe upstream.
+
+timer_create() specifies via sigevent->sigev_notify the signal delivery for
+the new timer. The valid modes are SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD
+and (SIGEV_SIGNAL | SIGEV_THREAD_ID).
+
+The sanity check in good_sigevent() is only checking the valid combination
+for the SIGEV_THREAD_ID bit, i.e. SIGEV_SIGNAL, but if SIGEV_THREAD_ID is
+not set it accepts any random value.
+
+This has no real effects on the posix timer and signal delivery code, but
+it affects show_timer() which handles the output of /proc/$PID/timers. That
+function uses a string array to pretty print sigev_notify. The access to
+that array has no bound checks, so random sigev_notify cause access beyond
+the array bounds.
+
+Add proper checks for the valid notify modes and remove the SIGEV_THREAD_ID
+masking from various code pathes as SIGEV_NONE can never be set in
+combination with SIGEV_THREAD_ID.
+
+Reported-by: Eric Biggers <ebiggers3@gmail.com>
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Reported-by: Alexey Dobriyan <adobriyan@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: John Stultz <john.stultz@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/time/posix-timers.c |   34 +++++++++++++++++++---------------
+ 1 file changed, 19 insertions(+), 15 deletions(-)
+
+--- a/kernel/time/posix-timers.c
++++ b/kernel/time/posix-timers.c
+@@ -500,17 +500,22 @@ static struct pid *good_sigevent(sigeven
+ {
+       struct task_struct *rtn = current->group_leader;
+-      if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
+-              (!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) ||
+-               !same_thread_group(rtn, current) ||
+-               (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
++      switch (event->sigev_notify) {
++      case SIGEV_SIGNAL | SIGEV_THREAD_ID:
++              rtn = find_task_by_vpid(event->sigev_notify_thread_id);
++              if (!rtn || !same_thread_group(rtn, current))
++                      return NULL;
++              /* FALLTHRU */
++      case SIGEV_SIGNAL:
++      case SIGEV_THREAD:
++              if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX)
++                      return NULL;
++              /* FALLTHRU */
++      case SIGEV_NONE:
++              return task_pid(rtn);
++      default:
+               return NULL;
+-
+-      if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) &&
+-          ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX)))
+-              return NULL;
+-
+-      return task_pid(rtn);
++      }
+ }
+ void posix_timers_register_clock(const clockid_t clock_id,
+@@ -738,8 +743,7 @@ common_timer_get(struct k_itimer *timr,
+       /* interval timer ? */
+       if (iv.tv64)
+               cur_setting->it_interval = ktime_to_timespec(iv);
+-      else if (!hrtimer_active(timer) &&
+-               (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
++      else if (!hrtimer_active(timer) && timr->it_sigev_notify != SIGEV_NONE)
+               return;
+       now = timer->base->get_time();
+@@ -750,7 +754,7 @@ common_timer_get(struct k_itimer *timr,
+        * expiry is > now.
+        */
+       if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
+-          (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
++                      timr->it_sigev_notify == SIGEV_NONE))
+               timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
+       remaining = ktime_sub(hrtimer_get_expires(timer), now);
+@@ -760,7 +764,7 @@ common_timer_get(struct k_itimer *timr,
+                * A single shot SIGEV_NONE timer must return 0, when
+                * it is expired !
+                */
+-              if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
++              if (timr->it_sigev_notify != SIGEV_NONE)
+                       cur_setting->it_value.tv_nsec = 1;
+       } else
+               cur_setting->it_value = ktime_to_timespec(remaining);
+@@ -858,7 +862,7 @@ common_timer_set(struct k_itimer *timr,
+       timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
+       /* SIGEV_NONE timers are not queued ! See common_timer_get */
+-      if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
++      if (timr->it_sigev_notify == SIGEV_NONE) {
+               /* Setup correct expiry time for relative timers */
+               if (mode == HRTIMER_MODE_REL) {
+                       hrtimer_add_expires(timer, timer->base->get_time());
index 05033e53de276ac3f8a37c3e06653c589d72b41e..4c60f07ed5e3e806e3393f5c6bcd89fffb5003df 100644 (file)
@@ -8,3 +8,19 @@ arm-exynos_defconfig-enable-options-to-mount-a-rootfs-via-nfs.patch
 arm-exynos_defconfig-enable-nfsv4-client.patch
 keys-encrypted-fix-buffer-overread-in-valid_master_desc.patch
 ipv4-map-neigh-lookup-keys-in-__ipv4_neigh_lookup_noref.patch
+cifs-fix-missing-put_xid-in-cifs_file_strict_mmap.patch
+cifs-fix-autonegotiate-security-settings-mismatch.patch
+cifs-zero-sensitive-data-when-freeing.patch
+posix-timer-properly-check-sigevent-sigev_notify.patch
+usbip-fix-stub_rx-get_pipe-to-validate-endpoint-number.patch
+usbip-fix-stub_rx-harden-cmd_submit-path-to-handle-malicious-input.patch
+usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch
+usbip-fix-potential-format-overflow-in-userspace-tools.patch
+usb-usbip-fix-possible-deadlocks-reported-by-lockdep.patch
+usbip-vhci-hcd-add-usb3-superspeed-support.patch
+usbip-prevent-leaking-socket-pointer-address-in-messages.patch
+usbip-stub-stop-printing-kernel-pointer-addresses-in-messages.patch
+usbip-vhci-stop-printing-kernel-pointer-addresses-in-messages.patch
+dccp-cve-2017-8824-use-after-free-in-dccp-code.patch
+media-dvb-usb-v2-lmedm04-improve-logic-checking-of-warm-start.patch
+media-dvb-usb-v2-lmedm04-move-ts2020-attach-to-dm04_lme2510_tuner.patch
diff --git a/queue-3.18/usb-usbip-fix-possible-deadlocks-reported-by-lockdep.patch b/queue-3.18/usb-usbip-fix-possible-deadlocks-reported-by-lockdep.patch
new file mode 100644 (file)
index 0000000..f84d817
--- /dev/null
@@ -0,0 +1,626 @@
+From 21619792d1eca7e772ca190ba68588e57f29595b Mon Sep 17 00:00:00 2001
+From: Andrew Goodbody <andrew.goodbody@cambrionix.com>
+Date: Tue, 2 Feb 2016 17:36:39 +0000
+Subject: usb: usbip: Fix possible deadlocks reported by lockdep
+
+From: Andrew Goodbody <andrew.goodbody@cambrionix.com>
+
+commit 21619792d1eca7e772ca190ba68588e57f29595b upstream.
+
+Change spin_lock calls to spin_lock_irqsave to prevent
+attmpted recursive lock taking in interrupt context.
+
+This patch fixes Bug 109351
+  https://bugzilla.kernel.org/show_bug.cgi?id=109351
+
+Signed-off-by: Andrew Goodbody <andrew.goodbody@cambrionix.com>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/usbip/usbip_event.c |    5 +-
+ drivers/usb/usbip/vhci_hcd.c    |   88 +++++++++++++++++++++++-----------------
+ drivers/usb/usbip/vhci_rx.c     |   30 +++++++------
+ drivers/usb/usbip/vhci_sysfs.c  |   19 +++++---
+ drivers/usb/usbip/vhci_tx.c     |   14 +++---
+ 5 files changed, 91 insertions(+), 65 deletions(-)
+
+--- a/drivers/usb/usbip/usbip_event.c
++++ b/drivers/usb/usbip/usbip_event.c
+@@ -117,11 +117,12 @@ EXPORT_SYMBOL_GPL(usbip_event_add);
+ int usbip_event_happened(struct usbip_device *ud)
+ {
+       int happened = 0;
++      unsigned long flags;
+-      spin_lock(&ud->lock);
++      spin_lock_irqsave(&ud->lock, flags);
+       if (ud->event != 0)
+               happened = 1;
+-      spin_unlock(&ud->lock);
++      spin_unlock_irqrestore(&ud->lock, flags);
+       return happened;
+ }
+--- a/drivers/usb/usbip/vhci_hcd.c
++++ b/drivers/usb/usbip/vhci_hcd.c
+@@ -121,9 +121,11 @@ static void dump_port_status_diff(u32 pr
+ void rh_port_connect(int rhport, enum usb_device_speed speed)
+ {
++      unsigned long   flags;
++
+       usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport);
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION
+               | (1 << USB_PORT_FEAT_C_CONNECTION);
+@@ -139,22 +141,24 @@ void rh_port_connect(int rhport, enum us
+               break;
+       }
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
+ }
+ static void rh_port_disconnect(int rhport)
+ {
++      unsigned long   flags;
++
+       usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport);
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
+       the_controller->port_status[rhport] |=
+                                       (1 << USB_PORT_FEAT_C_CONNECTION);
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
+ }
+@@ -182,13 +186,14 @@ static int vhci_hub_status(struct usb_hc
+       int             retval;
+       int             rhport;
+       int             changed = 0;
++      unsigned long   flags;
+       retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8);
+       memset(buf, 0, retval);
+       vhci = hcd_to_vhci(hcd);
+-      spin_lock(&vhci->lock);
++      spin_lock_irqsave(&vhci->lock, flags);
+       if (!HCD_HW_ACCESSIBLE(hcd)) {
+               usbip_dbg_vhci_rh("hw accessible flag not on?\n");
+               goto done;
+@@ -209,7 +214,7 @@ static int vhci_hub_status(struct usb_hc
+               usb_hcd_resume_root_hub(hcd);
+ done:
+-      spin_unlock(&vhci->lock);
++      spin_unlock_irqrestore(&vhci->lock, flags);
+       return changed ? retval : 0;
+ }
+@@ -230,6 +235,7 @@ static int vhci_hub_control(struct usb_h
+       struct vhci_hcd *dum;
+       int             retval = 0;
+       int             rhport;
++      unsigned long   flags;
+       u32 prev_port_status[VHCI_NPORTS];
+@@ -248,7 +254,7 @@ static int vhci_hub_control(struct usb_h
+       dum = hcd_to_vhci(hcd);
+-      spin_lock(&dum->lock);
++      spin_lock_irqsave(&dum->lock, flags);
+       /* store old status and compare now and old later */
+       if (usbip_dbg_flag_vhci_rh) {
+@@ -402,7 +408,7 @@ static int vhci_hub_control(struct usb_h
+       }
+       usbip_dbg_vhci_rh(" bye\n");
+-      spin_unlock(&dum->lock);
++      spin_unlock_irqrestore(&dum->lock, flags);
+       return retval;
+ }
+@@ -425,6 +431,7 @@ static void vhci_tx_urb(struct urb *urb)
+ {
+       struct vhci_device *vdev = get_vdev(urb->dev);
+       struct vhci_priv *priv;
++      unsigned long flags;
+       if (!vdev) {
+               pr_err("could not get virtual device");
+@@ -437,7 +444,7 @@ static void vhci_tx_urb(struct urb *urb)
+               return;
+       }
+-      spin_lock(&vdev->priv_lock);
++      spin_lock_irqsave(&vdev->priv_lock, flags);
+       priv->seqnum = atomic_inc_return(&the_controller->seqnum);
+       if (priv->seqnum == 0xffff)
+@@ -451,7 +458,7 @@ static void vhci_tx_urb(struct urb *urb)
+       list_add_tail(&priv->list, &vdev->priv_tx);
+       wake_up(&vdev->waitq_tx);
+-      spin_unlock(&vdev->priv_lock);
++      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+ }
+ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+@@ -460,6 +467,7 @@ static int vhci_urb_enqueue(struct usb_h
+       struct device *dev = &urb->dev->dev;
+       int ret = 0;
+       struct vhci_device *vdev;
++      unsigned long flags;
+       usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
+                         hcd, urb, mem_flags);
+@@ -467,11 +475,11 @@ static int vhci_urb_enqueue(struct usb_h
+       /* patch to usb_sg_init() is in 2.5.60 */
+       BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       if (urb->status != -EINPROGRESS) {
+               dev_err(dev, "URB already unlinked!, status %d\n", urb->status);
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               return urb->status;
+       }
+@@ -483,7 +491,7 @@ static int vhci_urb_enqueue(struct usb_h
+           vdev->ud.status == VDEV_ST_ERROR) {
+               dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport);
+               spin_unlock(&vdev->ud.lock);
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               return -ENODEV;
+       }
+       spin_unlock(&vdev->ud.lock);
+@@ -558,14 +566,14 @@ static int vhci_urb_enqueue(struct usb_h
+ out:
+       vhci_tx_urb(urb);
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       return 0;
+ no_need_xmit:
+       usb_hcd_unlink_urb_from_ep(hcd, urb);
+ no_need_unlink:
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+       return ret;
+ }
+@@ -620,16 +628,17 @@ static int vhci_urb_dequeue(struct usb_h
+ {
+       struct vhci_priv *priv;
+       struct vhci_device *vdev;
++      unsigned long flags;
+       pr_info("dequeue a urb %p\n", urb);
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       priv = urb->hcpriv;
+       if (!priv) {
+               /* URB was never linked! or will be soon given back by
+                * vhci_rx. */
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               return 0;
+       }
+@@ -638,7 +647,7 @@ static int vhci_urb_dequeue(struct usb_h
+               ret = usb_hcd_check_unlink_urb(hcd, urb, status);
+               if (ret) {
+-                      spin_unlock(&the_controller->lock);
++                      spin_unlock_irqrestore(&the_controller->lock, flags);
+                       return ret;
+               }
+       }
+@@ -666,10 +675,10 @@ static int vhci_urb_dequeue(struct usb_h
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+                                    urb->status);
+-              spin_lock(&the_controller->lock);
++              spin_lock_irqsave(&the_controller->lock, flags);
+       } else {
+               /* tcp connection is alive */
+@@ -681,7 +690,7 @@ static int vhci_urb_dequeue(struct usb_h
+               unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC);
+               if (!unlink) {
+                       spin_unlock(&vdev->priv_lock);
+-                      spin_unlock(&the_controller->lock);
++                      spin_unlock_irqrestore(&the_controller->lock, flags);
+                       usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
+                       return -ENOMEM;
+               }
+@@ -702,7 +711,7 @@ static int vhci_urb_dequeue(struct usb_h
+               spin_unlock(&vdev->priv_lock);
+       }
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       usbip_dbg_vhci_hc("leave\n");
+       return 0;
+@@ -711,8 +720,9 @@ static int vhci_urb_dequeue(struct usb_h
+ static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
+ {
+       struct vhci_unlink *unlink, *tmp;
++      unsigned long flags;
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       spin_lock(&vdev->priv_lock);
+       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
+@@ -746,19 +756,19 @@ static void vhci_device_unlink_cleanup(s
+               list_del(&unlink->list);
+               spin_unlock(&vdev->priv_lock);
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+                                    urb->status);
+-              spin_lock(&the_controller->lock);
++              spin_lock_irqsave(&the_controller->lock, flags);
+               spin_lock(&vdev->priv_lock);
+               kfree(unlink);
+       }
+       spin_unlock(&vdev->priv_lock);
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+ }
+ /*
+@@ -825,8 +835,9 @@ static void vhci_shutdown_connection(str
+ static void vhci_device_reset(struct usbip_device *ud)
+ {
+       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
++      unsigned long flags;
+-      spin_lock(&ud->lock);
++      spin_lock_irqsave(&ud->lock, flags);
+       vdev->speed  = 0;
+       vdev->devid  = 0;
+@@ -841,14 +852,16 @@ static void vhci_device_reset(struct usb
+       }
+       ud->status = VDEV_ST_NULL;
+-      spin_unlock(&ud->lock);
++      spin_unlock_irqrestore(&ud->lock, flags);
+ }
+ static void vhci_device_unusable(struct usbip_device *ud)
+ {
+-      spin_lock(&ud->lock);
++      unsigned long flags;
++
++      spin_lock_irqsave(&ud->lock, flags);
+       ud->status = VDEV_ST_ERROR;
+-      spin_unlock(&ud->lock);
++      spin_unlock_irqrestore(&ud->lock, flags);
+ }
+ static void vhci_device_init(struct vhci_device *vdev)
+@@ -938,12 +951,13 @@ static int vhci_get_frame_number(struct
+ static int vhci_bus_suspend(struct usb_hcd *hcd)
+ {
+       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
++      unsigned long flags;
+       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+-      spin_lock(&vhci->lock);
++      spin_lock_irqsave(&vhci->lock, flags);
+       hcd->state = HC_STATE_SUSPENDED;
+-      spin_unlock(&vhci->lock);
++      spin_unlock_irqrestore(&vhci->lock, flags);
+       return 0;
+ }
+@@ -952,15 +966,16 @@ static int vhci_bus_resume(struct usb_hc
+ {
+       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+       int rc = 0;
++      unsigned long flags;
+       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+-      spin_lock(&vhci->lock);
++      spin_lock_irqsave(&vhci->lock, flags);
+       if (!HCD_HW_ACCESSIBLE(hcd))
+               rc = -ESHUTDOWN;
+       else
+               hcd->state = HC_STATE_RUNNING;
+-      spin_unlock(&vhci->lock);
++      spin_unlock_irqrestore(&vhci->lock, flags);
+       return rc;
+ }
+@@ -1058,17 +1073,18 @@ static int vhci_hcd_suspend(struct platf
+       int rhport = 0;
+       int connected = 0;
+       int ret = 0;
++      unsigned long flags;
+       hcd = platform_get_drvdata(pdev);
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       for (rhport = 0; rhport < VHCI_NPORTS; rhport++)
+               if (the_controller->port_status[rhport] &
+                   USB_PORT_STAT_CONNECTION)
+                       connected += 1;
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       if (connected > 0) {
+               dev_info(&pdev->dev,
+--- a/drivers/usb/usbip/vhci_rx.c
++++ b/drivers/usb/usbip/vhci_rx.c
+@@ -72,10 +72,11 @@ static void vhci_recv_ret_submit(struct
+ {
+       struct usbip_device *ud = &vdev->ud;
+       struct urb *urb;
++      unsigned long flags;
+-      spin_lock(&vdev->priv_lock);
++      spin_lock_irqsave(&vdev->priv_lock, flags);
+       urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
+-      spin_unlock(&vdev->priv_lock);
++      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+       if (!urb) {
+               pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
+@@ -104,9 +105,9 @@ static void vhci_recv_ret_submit(struct
+       usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+@@ -117,8 +118,9 @@ static struct vhci_unlink *dequeue_pendi
+                                                 struct usbip_header *pdu)
+ {
+       struct vhci_unlink *unlink, *tmp;
++      unsigned long flags;
+-      spin_lock(&vdev->priv_lock);
++      spin_lock_irqsave(&vdev->priv_lock, flags);
+       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
+               pr_info("unlink->seqnum %lu\n", unlink->seqnum);
+@@ -127,12 +129,12 @@ static struct vhci_unlink *dequeue_pendi
+                                         unlink->seqnum);
+                       list_del(&unlink->list);
+-                      spin_unlock(&vdev->priv_lock);
++                      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+                       return unlink;
+               }
+       }
+-      spin_unlock(&vdev->priv_lock);
++      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+       return NULL;
+ }
+@@ -142,6 +144,7 @@ static void vhci_recv_ret_unlink(struct
+ {
+       struct vhci_unlink *unlink;
+       struct urb *urb;
++      unsigned long flags;
+       usbip_dump_header(pdu);
+@@ -152,9 +155,9 @@ static void vhci_recv_ret_unlink(struct
+               return;
+       }
+-      spin_lock(&vdev->priv_lock);
++      spin_lock_irqsave(&vdev->priv_lock, flags);
+       urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
+-      spin_unlock(&vdev->priv_lock);
++      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+       if (!urb) {
+               /*
+@@ -171,9 +174,9 @@ static void vhci_recv_ret_unlink(struct
+               urb->status = pdu->u.ret_unlink.status;
+               pr_info("urb->status %d\n", urb->status);
+-              spin_lock(&the_controller->lock);
++              spin_lock_irqsave(&the_controller->lock, flags);
+               usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+                                    urb->status);
+@@ -185,10 +188,11 @@ static void vhci_recv_ret_unlink(struct
+ static int vhci_priv_tx_empty(struct vhci_device *vdev)
+ {
+       int empty = 0;
++      unsigned long flags;
+-      spin_lock(&vdev->priv_lock);
++      spin_lock_irqsave(&vdev->priv_lock, flags);
+       empty = list_empty(&vdev->priv_rx);
+-      spin_unlock(&vdev->priv_lock);
++      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+       return empty;
+ }
+--- a/drivers/usb/usbip/vhci_sysfs.c
++++ b/drivers/usb/usbip/vhci_sysfs.c
+@@ -32,10 +32,11 @@ static ssize_t status_show(struct device
+ {
+       char *s = out;
+       int i = 0;
++      unsigned long flags;
+       BUG_ON(!the_controller || !out);
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       /*
+        * output example:
+@@ -73,7 +74,7 @@ static ssize_t status_show(struct device
+               spin_unlock(&vdev->ud.lock);
+       }
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       return out - s;
+ }
+@@ -83,11 +84,12 @@ static DEVICE_ATTR_RO(status);
+ static int vhci_port_disconnect(__u32 rhport)
+ {
+       struct vhci_device *vdev;
++      unsigned long flags;
+       usbip_dbg_vhci_sysfs("enter\n");
+       /* lock */
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       vdev = port_to_vdev(rhport);
+@@ -97,14 +99,14 @@ static int vhci_port_disconnect(__u32 rh
+               /* unlock */
+               spin_unlock(&vdev->ud.lock);
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               return -EINVAL;
+       }
+       /* unlock */
+       spin_unlock(&vdev->ud.lock);
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
+@@ -180,6 +182,7 @@ static ssize_t store_attach(struct devic
+       int sockfd = 0;
+       __u32 rhport = 0, devid = 0, speed = 0;
+       int err;
++      unsigned long flags;
+       /*
+        * @rhport: port number of vhci_hcd
+@@ -205,14 +208,14 @@ static ssize_t store_attach(struct devic
+       /* now need lock until setting vdev status as used */
+       /* begin a lock */
+-      spin_lock(&the_controller->lock);
++      spin_lock_irqsave(&the_controller->lock, flags);
+       vdev = port_to_vdev(rhport);
+       spin_lock(&vdev->ud.lock);
+       if (vdev->ud.status != VDEV_ST_NULL) {
+               /* end of the lock */
+               spin_unlock(&vdev->ud.lock);
+-              spin_unlock(&the_controller->lock);
++              spin_unlock_irqrestore(&the_controller->lock, flags);
+               sockfd_put(socket);
+@@ -231,7 +234,7 @@ static ssize_t store_attach(struct devic
+       vdev->ud.status     = VDEV_ST_NOTASSIGNED;
+       spin_unlock(&vdev->ud.lock);
+-      spin_unlock(&the_controller->lock);
++      spin_unlock_irqrestore(&the_controller->lock, flags);
+       /* end the lock */
+       vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
+--- a/drivers/usb/usbip/vhci_tx.c
++++ b/drivers/usb/usbip/vhci_tx.c
+@@ -47,16 +47,17 @@ static void setup_cmd_submit_pdu(struct
+ static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev)
+ {
+       struct vhci_priv *priv, *tmp;
++      unsigned long flags;
+-      spin_lock(&vdev->priv_lock);
++      spin_lock_irqsave(&vdev->priv_lock, flags);
+       list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
+               list_move_tail(&priv->list, &vdev->priv_rx);
+-              spin_unlock(&vdev->priv_lock);
++              spin_unlock_irqrestore(&vdev->priv_lock, flags);
+               return priv;
+       }
+-      spin_unlock(&vdev->priv_lock);
++      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+       return NULL;
+ }
+@@ -136,16 +137,17 @@ static int vhci_send_cmd_submit(struct v
+ static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev)
+ {
+       struct vhci_unlink *unlink, *tmp;
++      unsigned long flags;
+-      spin_lock(&vdev->priv_lock);
++      spin_lock_irqsave(&vdev->priv_lock, flags);
+       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
+               list_move_tail(&unlink->list, &vdev->unlink_rx);
+-              spin_unlock(&vdev->priv_lock);
++              spin_unlock_irqrestore(&vdev->priv_lock, flags);
+               return unlink;
+       }
+-      spin_unlock(&vdev->priv_lock);
++      spin_unlock_irqrestore(&vdev->priv_lock, flags);
+       return NULL;
+ }
diff --git a/queue-3.18/usbip-fix-potential-format-overflow-in-userspace-tools.patch b/queue-3.18/usbip-fix-potential-format-overflow-in-userspace-tools.patch
new file mode 100644 (file)
index 0000000..f3f956f
--- /dev/null
@@ -0,0 +1,107 @@
+From e5dfa3f902b9a642ae8c6997d57d7c41e384a90b Mon Sep 17 00:00:00 2001
+From: Jonathan Dieter <jdieter@lesbg.com>
+Date: Mon, 27 Feb 2017 10:31:03 +0200
+Subject: usbip: Fix potential format overflow in userspace tools
+
+From: Jonathan Dieter <jdieter@lesbg.com>
+
+commit e5dfa3f902b9a642ae8c6997d57d7c41e384a90b upstream.
+
+The usbip userspace tools call sprintf()/snprintf() and don't check for
+the return value which can lead the paths to overflow, truncating the
+final file in the path.
+
+More urgently, GCC 7 now warns that these aren't checked with
+-Wformat-overflow, and with -Werror enabled in configure.ac, that makes
+these tools unbuildable.
+
+This patch fixes these problems by replacing sprintf() with snprintf() in
+one place and adding checks for the return value of snprintf().
+
+Reviewed-by: Peter Senna Tschudin <peter.senna@gmail.com>
+Signed-off-by: Jonathan Dieter <jdieter@lesbg.com>
+Acked-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ tools/usb/usbip/libsrc/usbip_common.c      |    9 ++++++++-
+ tools/usb/usbip/libsrc/usbip_host_driver.c |   27 ++++++++++++++++++++++-----
+ 2 files changed, 30 insertions(+), 6 deletions(-)
+
+--- a/tools/usb/usbip/libsrc/usbip_common.c
++++ b/tools/usb/usbip/libsrc/usbip_common.c
+@@ -215,9 +215,16 @@ int read_usb_interface(struct usbip_usb_
+                      struct usbip_usb_interface *uinf)
+ {
+       char busid[SYSFS_BUS_ID_SIZE];
++      int size;
+       struct udev_device *sif;
+-      sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i);
++      size = snprintf(busid, sizeof(busid), "%s:%d.%d",
++                      udev->busid, udev->bConfigurationValue, i);
++      if (size < 0 || (unsigned int)size >= sizeof(busid)) {
++              err("busid length %i >= %lu or < 0", size,
++                  (unsigned long)sizeof(busid));
++              return -1;
++      }
+       sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
+       if (!sif) {
+--- a/tools/usb/usbip/libsrc/usbip_host_driver.c
++++ b/tools/usb/usbip/libsrc/usbip_host_driver.c
+@@ -39,13 +39,19 @@ struct udev *udev_context;
+ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
+ {
+       char status_attr_path[SYSFS_PATH_MAX];
++      int size;
+       int fd;
+       int length;
+       char status;
+       int value = 0;
+-      snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
+-               udev->path);
++      size = snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
++                      udev->path);
++      if (size < 0 || (unsigned int)size >= sizeof(status_attr_path)) {
++              err("usbip_status path length %i >= %lu or < 0", size,
++                  (unsigned long)sizeof(status_attr_path));
++              return -1;
++      }
+       fd = open(status_attr_path, O_RDONLY);
+       if (fd < 0) {
+@@ -225,6 +231,7 @@ int usbip_host_export_device(struct usbi
+ {
+       char attr_name[] = "usbip_sockfd";
+       char sockfd_attr_path[SYSFS_PATH_MAX];
++      int size;
+       char sockfd_buff[30];
+       int ret;
+@@ -244,10 +251,20 @@ int usbip_host_export_device(struct usbi
+       }
+       /* only the first interface is true */
+-      snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
+-               edev->udev.path, attr_name);
++      size = snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
++                      edev->udev.path, attr_name);
++      if (size < 0 || (unsigned int)size >= sizeof(sockfd_attr_path)) {
++              err("exported device path length %i >= %lu or < 0", size,
++                  (unsigned long)sizeof(sockfd_attr_path));
++              return -1;
++      }
+-      snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
++      size = snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
++      if (size < 0 || (unsigned int)size >= sizeof(sockfd_buff)) {
++              err("socket length %i >= %lu or < 0", size,
++                  (unsigned long)sizeof(sockfd_buff));
++              return -1;
++      }
+       ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
+                                   strlen(sockfd_buff));
diff --git a/queue-3.18/usbip-fix-stub_rx-get_pipe-to-validate-endpoint-number.patch b/queue-3.18/usbip-fix-stub_rx-get_pipe-to-validate-endpoint-number.patch
new file mode 100644 (file)
index 0000000..b9cfda1
--- /dev/null
@@ -0,0 +1,71 @@
+From 635f545a7e8be7596b9b2b6a43cab6bbd5a88e43 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <shuahkh@osg.samsung.com>
+Date: Thu, 7 Dec 2017 14:16:47 -0700
+Subject: usbip: fix stub_rx: get_pipe() to validate endpoint number
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 635f545a7e8be7596b9b2b6a43cab6bbd5a88e43 upstream.
+
+get_pipe() routine doesn't validate the input endpoint number
+and uses to reference ep_in and ep_out arrays. Invalid endpoint
+number can trigger BUG(). Range check the epnum and returning
+error instead of calling BUG().
+
+Change caller stub_recv_cmd_submit() to handle the get_pipe()
+error return.
+
+Reported-by: Secunia Research <vuln@secunia.com>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/usb/usbip/stub_rx.c |   16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/usbip/stub_rx.c
++++ b/drivers/usb/usbip/stub_rx.c
+@@ -347,15 +347,15 @@ static int get_pipe(struct stub_device *
+       struct usb_host_endpoint *ep;
+       struct usb_endpoint_descriptor *epd = NULL;
++      if (epnum < 0 || epnum > 15)
++              goto err_ret;
++
+       if (dir == USBIP_DIR_IN)
+               ep = udev->ep_in[epnum & 0x7f];
+       else
+               ep = udev->ep_out[epnum & 0x7f];
+-      if (!ep) {
+-              dev_err(&sdev->interface->dev, "no such endpoint?, %d\n",
+-                      epnum);
+-              BUG();
+-      }
++      if (!ep)
++              goto err_ret;
+       epd = &ep->desc;
+       if (usb_endpoint_xfer_control(epd)) {
+@@ -386,9 +386,10 @@ static int get_pipe(struct stub_device *
+                       return usb_rcvisocpipe(udev, epnum);
+       }
++err_ret:
+       /* NOT REACHED */
+       dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum);
+-      return 0;
++      return -1;
+ }
+ static void masking_bogus_flags(struct urb *urb)
+@@ -454,6 +455,9 @@ static void stub_recv_cmd_submit(struct
+       struct usb_device *udev = sdev->udev;
+       int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction);
++      if (pipe == -1)
++              return;
++
+       priv = stub_priv_alloc(sdev, pdu);
+       if (!priv)
+               return;
diff --git a/queue-3.18/usbip-fix-stub_rx-harden-cmd_submit-path-to-handle-malicious-input.patch b/queue-3.18/usbip-fix-stub_rx-harden-cmd_submit-path-to-handle-malicious-input.patch
new file mode 100644 (file)
index 0000000..a0861de
--- /dev/null
@@ -0,0 +1,95 @@
+From c6688ef9f29762e65bce325ef4acd6c675806366 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <shuahkh@osg.samsung.com>
+Date: Thu, 7 Dec 2017 14:16:48 -0700
+Subject: usbip: fix stub_rx: harden CMD_SUBMIT path to handle malicious input
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit c6688ef9f29762e65bce325ef4acd6c675806366 upstream.
+
+Harden CMD_SUBMIT path to handle malicious input that could trigger
+large memory allocations. Add checks to validate transfer_buffer_length
+and number_of_packets to protect against bad input requesting for
+unbounded memory allocations. Validate early in get_pipe() and return
+failure.
+
+Reported-by: Secunia Research <vuln@secunia.com>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/usb/usbip/stub_rx.c |   30 +++++++++++++++++++++++++++---
+ 1 file changed, 27 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/usbip/stub_rx.c
++++ b/drivers/usb/usbip/stub_rx.c
+@@ -341,11 +341,13 @@ static struct stub_priv *stub_priv_alloc
+       return priv;
+ }
+-static int get_pipe(struct stub_device *sdev, int epnum, int dir)
++static int get_pipe(struct stub_device *sdev, struct usbip_header *pdu)
+ {
+       struct usb_device *udev = sdev->udev;
+       struct usb_host_endpoint *ep;
+       struct usb_endpoint_descriptor *epd = NULL;
++      int epnum = pdu->base.ep;
++      int dir = pdu->base.direction;
+       if (epnum < 0 || epnum > 15)
+               goto err_ret;
+@@ -358,6 +360,7 @@ static int get_pipe(struct stub_device *
+               goto err_ret;
+       epd = &ep->desc;
++
+       if (usb_endpoint_xfer_control(epd)) {
+               if (dir == USBIP_DIR_OUT)
+                       return usb_sndctrlpipe(udev, epnum);
+@@ -380,6 +383,27 @@ static int get_pipe(struct stub_device *
+       }
+       if (usb_endpoint_xfer_isoc(epd)) {
++              /* validate packet size and number of packets */
++              unsigned int maxp, packets, bytes;
++
++#define USB_EP_MAXP_MULT_SHIFT  11
++#define USB_EP_MAXP_MULT_MASK   (3 << USB_EP_MAXP_MULT_SHIFT)
++#define USB_EP_MAXP_MULT(m) \
++      (((m) & USB_EP_MAXP_MULT_MASK) >> USB_EP_MAXP_MULT_SHIFT)
++
++              maxp = usb_endpoint_maxp(epd);
++              maxp *= (USB_EP_MAXP_MULT(
++                              __le16_to_cpu(epd->wMaxPacketSize)) + 1);
++              bytes = pdu->u.cmd_submit.transfer_buffer_length;
++              packets = DIV_ROUND_UP(bytes, maxp);
++
++              if (pdu->u.cmd_submit.number_of_packets < 0 ||
++                  pdu->u.cmd_submit.number_of_packets > packets) {
++                      dev_err(&sdev->udev->dev,
++                              "CMD_SUBMIT: isoc invalid num packets %d\n",
++                              pdu->u.cmd_submit.number_of_packets);
++                      return -1;
++              }
+               if (dir == USBIP_DIR_OUT)
+                       return usb_sndisocpipe(udev, epnum);
+               else
+@@ -388,7 +412,7 @@ static int get_pipe(struct stub_device *
+ err_ret:
+       /* NOT REACHED */
+-      dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum);
++      dev_err(&sdev->udev->dev, "CMD_SUBMIT: invalid epnum %d\n", epnum);
+       return -1;
+ }
+@@ -453,7 +477,7 @@ static void stub_recv_cmd_submit(struct
+       struct stub_priv *priv;
+       struct usbip_device *ud = &sdev->ud;
+       struct usb_device *udev = sdev->udev;
+-      int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction);
++      int pipe = get_pipe(sdev, pdu);
+       if (pipe == -1)
+               return;
diff --git a/queue-3.18/usbip-prevent-leaking-socket-pointer-address-in-messages.patch b/queue-3.18/usbip-prevent-leaking-socket-pointer-address-in-messages.patch
new file mode 100644 (file)
index 0000000..96cc3ae
--- /dev/null
@@ -0,0 +1,82 @@
+From 90120d15f4c397272aaf41077960a157fc4212bf Mon Sep 17 00:00:00 2001
+From: Shuah Khan <shuahkh@osg.samsung.com>
+Date: Fri, 15 Dec 2017 10:50:09 -0700
+Subject: usbip: prevent leaking socket pointer address in messages
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 90120d15f4c397272aaf41077960a157fc4212bf upstream.
+
+usbip driver is leaking socket pointer address in messages. Remove
+the messages that aren't useful and print sockfd in the ones that
+are useful for debugging.
+
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/usbip/stub_dev.c     |    3 +--
+ drivers/usb/usbip/usbip_common.c |   15 ++++-----------
+ drivers/usb/usbip/vhci_hcd.c     |    2 +-
+ 3 files changed, 6 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/usbip/stub_dev.c
++++ b/drivers/usb/usbip/stub_dev.c
+@@ -163,8 +163,7 @@ static void stub_shutdown_connection(str
+        * step 1?
+        */
+       if (ud->tcp_socket) {
+-              dev_dbg(&sdev->udev->dev, "shutdown tcp_socket %p\n",
+-                      ud->tcp_socket);
++              dev_dbg(&sdev->udev->dev, "shutdown sockfd %d\n", ud->sockfd);
+               kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
+       }
+--- a/drivers/usb/usbip/usbip_common.c
++++ b/drivers/usb/usbip/usbip_common.c
+@@ -317,18 +317,14 @@ int usbip_recv(struct socket *sock, void
+       struct msghdr msg;
+       struct kvec iov;
+       int total = 0;
+-
+       /* for blocks of if (usbip_dbg_flag_xmit) */
+       char *bp = buf;
+       int osize = size;
+-      usbip_dbg_xmit("enter\n");
+-
+-      if (!sock || !buf || !size) {
+-              pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf,
+-                     size);
++      if (!sock || !buf || !size)
+               return -EINVAL;
+-      }
++
++      usbip_dbg_xmit("enter\n");
+       do {
+               sock->sk->sk_allocation = GFP_NOIO;
+@@ -341,11 +337,8 @@ int usbip_recv(struct socket *sock, void
+               msg.msg_flags      = MSG_NOSIGNAL;
+               result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL);
+-              if (result <= 0) {
+-                      pr_debug("receive sock %p buf %p size %u ret %d total %d\n",
+-                               sock, buf, size, result, total);
++              if (result <= 0)
+                       goto err;
+-              }
+               size -= result;
+               buf += result;
+--- a/drivers/usb/usbip/vhci_hcd.c
++++ b/drivers/usb/usbip/vhci_hcd.c
+@@ -782,7 +782,7 @@ static void vhci_shutdown_connection(str
+       /* need this? see stub_dev.c */
+       if (ud->tcp_socket) {
+-              pr_debug("shutdown tcp_socket %p\n", ud->tcp_socket);
++              pr_debug("shutdown sockfd %d\n", ud->sockfd);
+               kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
+       }
diff --git a/queue-3.18/usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch b/queue-3.18/usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch
new file mode 100644 (file)
index 0000000..3223e12
--- /dev/null
@@ -0,0 +1,124 @@
+From 2f2d0088eb93db5c649d2a5e34a3800a8a935fc5 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <shuahkh@osg.samsung.com>
+Date: Thu, 7 Dec 2017 14:16:49 -0700
+Subject: usbip: prevent vhci_hcd driver from leaking a socket pointer address
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 2f2d0088eb93db5c649d2a5e34a3800a8a935fc5 upstream.
+
+When a client has a USB device attached over IP, the vhci_hcd driver is
+locally leaking a socket pointer address via the
+
+/sys/devices/platform/vhci_hcd/status file (world-readable) and in debug
+output when "usbip --debug port" is run.
+
+Fix it to not leak. The socket pointer address is not used at the moment
+and it was made visible as a convenient way to find IP address from socket
+pointer address by looking up /proc/net/{tcp,tcp6}.
+
+As this opens a security hole, the fix replaces socket pointer address with
+sockfd.
+
+Reported-by: Secunia Research <vuln@secunia.com>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/usb/usbip/usbip_common.h     |    1 +
+ drivers/usb/usbip/vhci_sysfs.c       |   26 +++++++++++++++-----------
+ tools/usb/usbip/libsrc/vhci_driver.c |    8 ++++----
+ 3 files changed, 20 insertions(+), 15 deletions(-)
+
+--- a/drivers/usb/usbip/usbip_common.h
++++ b/drivers/usb/usbip/usbip_common.h
+@@ -261,6 +261,7 @@ struct usbip_device {
+       /* lock for status */
+       spinlock_t lock;
++      int sockfd;
+       struct socket *tcp_socket;
+       struct task_struct *tcp_rx;
+--- a/drivers/usb/usbip/vhci_sysfs.c
++++ b/drivers/usb/usbip/vhci_sysfs.c
+@@ -39,16 +39,20 @@ static ssize_t status_show(struct device
+       /*
+        * output example:
+-       * prt sta spd dev socket           local_busid
+-       * 000 004 000 000         c5a7bb80 1-2.3
+-       * 001 004 000 000         d8cee980 2-3.4
++       * prt  sta spd dev      sockfd local_busid
++       * 0000 004 000 00000000 000003 1-2.3
++       * 0001 004 000 00000000 000004 2-3.4
+        *
+-       * IP address can be retrieved from a socket pointer address by looking
+-       * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
+-       * port number and its peer IP address.
++       * Output includes socket fd instead of socket pointer address to
++       * avoid leaking kernel memory address in:
++       *      /sys/devices/platform/vhci_hcd.0/status and in debug output.
++       * The socket pointer address is not used at the moment and it was
++       * made visible as a convenient way to find IP address from socket
++       * pointer address by looking up /proc/net/{tcp,tcp6}. As this opens
++       * a security hole, the change is made to use sockfd instead.
+        */
+       out += sprintf(out,
+-                     "prt sta spd bus dev socket           local_busid\n");
++                     "prt sta spd dev      sockfd local_busid\n");
+       for (i = 0; i < VHCI_NPORTS; i++) {
+               struct vhci_device *vdev = port_to_vdev(i);
+@@ -59,12 +63,11 @@ static ssize_t status_show(struct device
+               if (vdev->ud.status == VDEV_ST_USED) {
+                       out += sprintf(out, "%03u %08x ",
+                                      vdev->speed, vdev->devid);
+-                      out += sprintf(out, "%16p ", vdev->ud.tcp_socket);
++                      out += sprintf(out, "%06u ", vdev->ud.sockfd);
+                       out += sprintf(out, "%s", dev_name(&vdev->udev->dev));
+-              } else {
+-                      out += sprintf(out, "000 000 000 0000000000000000 0-0");
+-              }
++              } else
++                      out += sprintf(out, "000 00000000 000000 0-0");
+               out += sprintf(out, "\n");
+               spin_unlock(&vdev->ud.lock);
+@@ -223,6 +226,7 @@ static ssize_t store_attach(struct devic
+       vdev->devid         = devid;
+       vdev->speed         = speed;
++      vdev->ud.sockfd     = sockfd;
+       vdev->ud.tcp_socket = socket;
+       vdev->ud.status     = VDEV_ST_NOTASSIGNED;
+--- a/tools/usb/usbip/libsrc/vhci_driver.c
++++ b/tools/usb/usbip/libsrc/vhci_driver.c
+@@ -55,12 +55,12 @@ static int parse_status(const char *valu
+       while (*c != '\0') {
+               int port, status, speed, devid;
+-              unsigned long socket;
++              int sockfd;
+               char lbusid[SYSFS_BUS_ID_SIZE];
+-              ret = sscanf(c, "%d %d %d %x %lx %31s\n",
++              ret = sscanf(c, "%d %d %d %x %u %31s\n",
+                               &port, &status, &speed,
+-                              &devid, &socket, lbusid);
++                              &devid, &sockfd, lbusid);
+               if (ret < 5) {
+                       dbg("sscanf failed: %d", ret);
+@@ -69,7 +69,7 @@ static int parse_status(const char *valu
+               dbg("port %d status %d speed %d devid %x",
+                               port, status, speed, devid);
+-              dbg("socket %lx lbusid %s", socket, lbusid);
++              dbg("sockfd %u lbusid %s", sockfd, lbusid);
+               /* if a device is connected, look at it */
diff --git a/queue-3.18/usbip-stub-stop-printing-kernel-pointer-addresses-in-messages.patch b/queue-3.18/usbip-stub-stop-printing-kernel-pointer-addresses-in-messages.patch
new file mode 100644 (file)
index 0000000..24c1207
--- /dev/null
@@ -0,0 +1,74 @@
+From 248a22044366f588d46754c54dfe29ffe4f8b4df Mon Sep 17 00:00:00 2001
+From: Shuah Khan <shuahkh@osg.samsung.com>
+Date: Mon, 18 Dec 2017 17:23:37 -0700
+Subject: usbip: stub: stop printing kernel pointer addresses in messages
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 248a22044366f588d46754c54dfe29ffe4f8b4df upstream.
+
+Remove and/or change debug, info. and error messages to not print
+kernel pointer addresses.
+
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/usbip/stub_main.c |    5 +++--
+ drivers/usb/usbip/stub_rx.c   |    7 ++-----
+ drivers/usb/usbip/stub_tx.c   |    4 ++--
+ 3 files changed, 7 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/usbip/stub_main.c
++++ b/drivers/usb/usbip/stub_main.c
+@@ -252,11 +252,12 @@ void stub_device_cleanup_urbs(struct stu
+       struct stub_priv *priv;
+       struct urb *urb;
+-      dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev);
++      dev_dbg(&sdev->udev->dev, "Stub device cleaning up urbs\n");
+       while ((priv = stub_priv_pop(sdev))) {
+               urb = priv->urb;
+-              dev_dbg(&sdev->udev->dev, "free urb %p\n", urb);
++              dev_dbg(&sdev->udev->dev, "free urb seqnum %lu\n",
++                      priv->seqnum);
+               usb_kill_urb(urb);
+               kmem_cache_free(stub_priv_cache, priv);
+--- a/drivers/usb/usbip/stub_rx.c
++++ b/drivers/usb/usbip/stub_rx.c
+@@ -230,9 +230,6 @@ static int stub_recv_cmd_unlink(struct s
+               if (priv->seqnum != pdu->u.cmd_unlink.seqnum)
+                       continue;
+-              dev_info(&priv->urb->dev->dev, "unlink urb %p\n",
+-                       priv->urb);
+-
+               /*
+                * This matched urb is not completed yet (i.e., be in
+                * flight in usb hcd hardware/driver). Now we are
+@@ -271,8 +268,8 @@ static int stub_recv_cmd_unlink(struct s
+               ret = usb_unlink_urb(priv->urb);
+               if (ret != -EINPROGRESS)
+                       dev_err(&priv->urb->dev->dev,
+-                              "failed to unlink a urb %p, ret %d\n",
+-                              priv->urb, ret);
++                              "failed to unlink a urb # %lu, ret %d\n",
++                              priv->seqnum, ret);
+               return 0;
+       }
+--- a/drivers/usb/usbip/stub_tx.c
++++ b/drivers/usb/usbip/stub_tx.c
+@@ -201,8 +201,8 @@ static int stub_send_ret_submit(struct s
+               /* 1. setup usbip_header */
+               setup_ret_submit_pdu(&pdu_header, urb);
+-              usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
+-                                pdu_header.base.seqnum, urb);
++              usbip_dbg_stub_tx("setup txdata seqnum: %d\n",
++                                pdu_header.base.seqnum);
+               usbip_header_correct_endian(&pdu_header, 1);
+               iov[iovnum].iov_base = &pdu_header;
diff --git a/queue-3.18/usbip-vhci-hcd-add-usb3-superspeed-support.patch b/queue-3.18/usbip-vhci-hcd-add-usb3-superspeed-support.patch
new file mode 100644 (file)
index 0000000..733dca0
--- /dev/null
@@ -0,0 +1,41 @@
+From 1c9de5bf428612458427943b724bea51abde520a Mon Sep 17 00:00:00 2001
+From: Yuyang Du <yuyang.du@intel.com>
+Date: Thu, 8 Jun 2017 13:04:10 +0800
+Subject: usbip: vhci-hcd: Add USB3 SuperSpeed support
+
+From: Yuyang Du <yuyang.du@intel.com>
+
+commit 1c9de5bf428612458427943b724bea51abde520a upstream.
+
+This patch adds a USB3 HCD to an existing USB2 HCD and provides
+the support of SuperSpeed, in case the device can only be enumerated
+with SuperSpeed.
+
+The bulk of the added code in usb3_bos_desc and hub_control to support
+SuperSpeed is borrowed from the commit 1cd8fd2887e162ad ("usb: gadget:
+dummy_hcd: add SuperSpeed support").
+
+With this patch, each vhci will have VHCI_HC_PORTS HighSpeed ports
+and VHCI_HC_PORTS SuperSpeed ports.
+
+Suggested-by: Krzysztof Opasiak <k.opasiak@samsung.com>
+Signed-off-by: Yuyang Du <yuyang.du@intel.com>
+Acked-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/usbip/vhci_hcd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/usbip/vhci_hcd.c
++++ b/drivers/usb/usbip/vhci_hcd.c
+@@ -279,7 +279,7 @@ static int vhci_hub_control(struct usb_h
+               case USB_PORT_FEAT_POWER:
+                       usbip_dbg_vhci_rh(
+                               " ClearPortFeature: USB_PORT_FEAT_POWER\n");
+-                      dum->port_status[rhport] = 0;
++                      dum->port_status[rhport] &= ~USB_PORT_STAT_POWER;
+                       dum->resuming = 0;
+                       break;
+               case USB_PORT_FEAT_C_RESET:
diff --git a/queue-3.18/usbip-vhci-stop-printing-kernel-pointer-addresses-in-messages.patch b/queue-3.18/usbip-vhci-stop-printing-kernel-pointer-addresses-in-messages.patch
new file mode 100644 (file)
index 0000000..fbccc3c
--- /dev/null
@@ -0,0 +1,144 @@
+From 8272d099d05f7ab2776cf56a2ab9f9443be18907 Mon Sep 17 00:00:00 2001
+From: Shuah Khan <shuahkh@osg.samsung.com>
+Date: Mon, 18 Dec 2017 17:24:22 -0700
+Subject: usbip: vhci: stop printing kernel pointer addresses in messages
+
+From: Shuah Khan <shuahkh@osg.samsung.com>
+
+commit 8272d099d05f7ab2776cf56a2ab9f9443be18907 upstream.
+
+Remove and/or change debug, info. and error messages to not print
+kernel pointer addresses.
+
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/usb/usbip/vhci_hcd.c |   10 ----------
+ drivers/usb/usbip/vhci_rx.c  |   23 +++++++++++------------
+ drivers/usb/usbip/vhci_tx.c  |    3 ++-
+ 3 files changed, 13 insertions(+), 23 deletions(-)
+
+--- a/drivers/usb/usbip/vhci_hcd.c
++++ b/drivers/usb/usbip/vhci_hcd.c
+@@ -469,9 +469,6 @@ static int vhci_urb_enqueue(struct usb_h
+       struct vhci_device *vdev;
+       unsigned long flags;
+-      usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
+-                        hcd, urb, mem_flags);
+-
+       /* patch to usb_sg_init() is in 2.5.60 */
+       BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
+@@ -630,8 +627,6 @@ static int vhci_urb_dequeue(struct usb_h
+       struct vhci_device *vdev;
+       unsigned long flags;
+-      pr_info("dequeue a urb %p\n", urb);
+-
+       spin_lock_irqsave(&the_controller->lock, flags);
+       priv = urb->hcpriv;
+@@ -659,7 +654,6 @@ static int vhci_urb_dequeue(struct usb_h
+               /* tcp connection is closed */
+               spin_lock(&vdev->priv_lock);
+-              pr_info("device %p seems to be disconnected\n", vdev);
+               list_del(&priv->list);
+               kfree(priv);
+               urb->hcpriv = NULL;
+@@ -671,8 +665,6 @@ static int vhci_urb_dequeue(struct usb_h
+                * vhci_rx will receive RET_UNLINK and give back the URB.
+                * Otherwise, we give back it here.
+                */
+-              pr_info("gives back urb %p\n", urb);
+-
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+               spin_unlock_irqrestore(&the_controller->lock, flags);
+@@ -701,8 +693,6 @@ static int vhci_urb_dequeue(struct usb_h
+               unlink->unlink_seqnum = priv->seqnum;
+-              pr_info("device %p seems to be still connected\n", vdev);
+-
+               /* send cmd_unlink and try to cancel the pending URB in the
+                * peer */
+               list_add_tail(&unlink->list, &vdev->unlink_tx);
+--- a/drivers/usb/usbip/vhci_rx.c
++++ b/drivers/usb/usbip/vhci_rx.c
+@@ -37,24 +37,23 @@ struct urb *pickup_urb_and_free_priv(str
+               urb = priv->urb;
+               status = urb->status;
+-              usbip_dbg_vhci_rx("find urb %p vurb %p seqnum %u\n",
+-                              urb, priv, seqnum);
++              usbip_dbg_vhci_rx("find urb seqnum %u\n", seqnum);
+               switch (status) {
+               case -ENOENT:
+                       /* fall through */
+               case -ECONNRESET:
+-                      dev_info(&urb->dev->dev,
+-                               "urb %p was unlinked %ssynchronuously.\n", urb,
+-                               status == -ENOENT ? "" : "a");
++                      dev_dbg(&urb->dev->dev,
++                               "urb seq# %u was unlinked %ssynchronuously\n",
++                               seqnum, status == -ENOENT ? "" : "a");
+                       break;
+               case -EINPROGRESS:
+                       /* no info output */
+                       break;
+               default:
+-                      dev_info(&urb->dev->dev,
+-                               "urb %p may be in a error, status %d\n", urb,
+-                               status);
++                      dev_dbg(&urb->dev->dev,
++                               "urb seq# %u may be in a error, status %d\n",
++                               seqnum, status);
+               }
+               list_del(&priv->list);
+@@ -79,8 +78,8 @@ static void vhci_recv_ret_submit(struct
+       spin_unlock_irqrestore(&vdev->priv_lock, flags);
+       if (!urb) {
+-              pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
+-              pr_info("max seqnum %d\n",
++              pr_err("cannot find a urb of seqnum %u max seqnum %d\n",
++                      pdu->base.seqnum,
+                       atomic_read(&the_controller->seqnum));
+               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+               return;
+@@ -103,7 +102,7 @@ static void vhci_recv_ret_submit(struct
+       if (usbip_dbg_flag_vhci_rx)
+               usbip_dump_urb(urb);
+-      usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
++      usbip_dbg_vhci_rx("now giveback urb %u\n", pdu->base.seqnum);
+       spin_lock_irqsave(&the_controller->lock, flags);
+       usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+@@ -168,7 +167,7 @@ static void vhci_recv_ret_unlink(struct
+               pr_info("the urb (seqnum %d) was already given back\n",
+                       pdu->base.seqnum);
+       } else {
+-              usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
++              usbip_dbg_vhci_rx("now giveback urb %d\n", pdu->base.seqnum);
+               /* If unlink is successful, status is -ECONNRESET */
+               urb->status = pdu->u.ret_unlink.status;
+--- a/drivers/usb/usbip/vhci_tx.c
++++ b/drivers/usb/usbip/vhci_tx.c
+@@ -83,7 +83,8 @@ static int vhci_send_cmd_submit(struct v
+               memset(&msg, 0, sizeof(msg));
+               memset(&iov, 0, sizeof(iov));
+-              usbip_dbg_vhci_tx("setup txdata urb %p\n", urb);
++              usbip_dbg_vhci_tx("setup txdata urb seqnum %lu\n",
++                                priv->seqnum);
+               /* 1. setup usbip_header */
+               setup_cmd_submit_pdu(&pdu_header, urb);