]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Jan 2018 09:12:45 +0000 (10:12 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 24 Jan 2018 09:12:45 +0000 (10:12 +0100)
added patches:
orangefs-initialize-op-on-loop-restart-in-orangefs_devreq_read.patch
orangefs-use-list_for_each_entry_safe-in-purge_waiting_ops.patch
usbip-fix-implicit-fallthrough-warning.patch
usbip-fix-potential-format-overflow-in-userspace-tools.patch
usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch

queue-4.9/orangefs-initialize-op-on-loop-restart-in-orangefs_devreq_read.patch [new file with mode: 0644]
queue-4.9/orangefs-use-list_for_each_entry_safe-in-purge_waiting_ops.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/usbip-fix-implicit-fallthrough-warning.patch [new file with mode: 0644]
queue-4.9/usbip-fix-potential-format-overflow-in-userspace-tools.patch [new file with mode: 0644]
queue-4.9/usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch [new file with mode: 0644]

diff --git a/queue-4.9/orangefs-initialize-op-on-loop-restart-in-orangefs_devreq_read.patch b/queue-4.9/orangefs-initialize-op-on-loop-restart-in-orangefs_devreq_read.patch
new file mode 100644 (file)
index 0000000..e2a2e55
--- /dev/null
@@ -0,0 +1,46 @@
+From a0ec1ded22e6a6bc41981fae22406835b006a66e Mon Sep 17 00:00:00 2001
+From: Martin Brandenburg <martin@omnibond.com>
+Date: Mon, 22 Jan 2018 15:44:52 -0500
+Subject: orangefs: initialize op on loop restart in orangefs_devreq_read
+
+From: Martin Brandenburg <martin@omnibond.com>
+
+commit a0ec1ded22e6a6bc41981fae22406835b006a66e upstream.
+
+In orangefs_devreq_read, there is a loop which picks an op off the list
+of pending ops.  If the loop fails to find an op, there is nothing to
+read, and it returns EAGAIN.  If the op has been given up on, the loop
+is restarted via a goto.  The bug is that the variable which the found
+op is written to is not reinitialized, so if there are no more eligible
+ops on the list, the code runs again on the already handled op.
+
+This is triggered by interrupting a process while the op is being copied
+to the client-core.  It's a fairly small window, but it's there.
+
+Signed-off-by: Martin Brandenburg <martin@omnibond.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/orangefs/devorangefs-req.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/orangefs/devorangefs-req.c
++++ b/fs/orangefs/devorangefs-req.c
+@@ -161,7 +161,7 @@ static ssize_t orangefs_devreq_read(stru
+       struct orangefs_kernel_op_s *op, *temp;
+       __s32 proto_ver = ORANGEFS_KERNEL_PROTO_VERSION;
+       static __s32 magic = ORANGEFS_DEVREQ_MAGIC;
+-      struct orangefs_kernel_op_s *cur_op = NULL;
++      struct orangefs_kernel_op_s *cur_op;
+       unsigned long ret;
+       /* We do not support blocking IO. */
+@@ -181,6 +181,7 @@ static ssize_t orangefs_devreq_read(stru
+       }
+ restart:
++      cur_op = NULL;
+       /* Get next op (if any) from top of list. */
+       spin_lock(&orangefs_request_list_lock);
+       list_for_each_entry_safe(op, temp, &orangefs_request_list, list) {
diff --git a/queue-4.9/orangefs-use-list_for_each_entry_safe-in-purge_waiting_ops.patch b/queue-4.9/orangefs-use-list_for_each_entry_safe-in-purge_waiting_ops.patch
new file mode 100644 (file)
index 0000000..709ef60
--- /dev/null
@@ -0,0 +1,34 @@
+From 0afc0decf247f65b7aba666a76a0a68adf4bc435 Mon Sep 17 00:00:00 2001
+From: Martin Brandenburg <martin@omnibond.com>
+Date: Mon, 22 Jan 2018 15:44:51 -0500
+Subject: orangefs: use list_for_each_entry_safe in purge_waiting_ops
+
+From: Martin Brandenburg <martin@omnibond.com>
+
+commit 0afc0decf247f65b7aba666a76a0a68adf4bc435 upstream.
+
+set_op_state_purged can delete the op.
+
+Signed-off-by: Martin Brandenburg <martin@omnibond.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/orangefs/waitqueue.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/orangefs/waitqueue.c
++++ b/fs/orangefs/waitqueue.c
+@@ -28,10 +28,10 @@ static void orangefs_clean_up_interrupte
+  */
+ void purge_waiting_ops(void)
+ {
+-      struct orangefs_kernel_op_s *op;
++      struct orangefs_kernel_op_s *op, *tmp;
+       spin_lock(&orangefs_request_list_lock);
+-      list_for_each_entry(op, &orangefs_request_list, list) {
++      list_for_each_entry_safe(op, tmp, &orangefs_request_list, list) {
+               gossip_debug(GOSSIP_WAIT_DEBUG,
+                            "pvfs2-client-core: purging op tag %llu %s\n",
+                            llu(op->tag),
index e2d6ad978ed050de03282729f54909148ebf85b1..3c3e7c195156e4d710fc7e57c826e832949d7677 100644 (file)
@@ -1 +1,6 @@
 x86-asm-32-make-sync_core-handle-missing-cpuid-on-all-32-bit-kernels.patch
+orangefs-use-list_for_each_entry_safe-in-purge_waiting_ops.patch
+orangefs-initialize-op-on-loop-restart-in-orangefs_devreq_read.patch
+usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch
+usbip-fix-implicit-fallthrough-warning.patch
+usbip-fix-potential-format-overflow-in-userspace-tools.patch
diff --git a/queue-4.9/usbip-fix-implicit-fallthrough-warning.patch b/queue-4.9/usbip-fix-implicit-fallthrough-warning.patch
new file mode 100644 (file)
index 0000000..da83c9c
--- /dev/null
@@ -0,0 +1,35 @@
+From cfd6ed4537a9e938fa76facecd4b9cd65b6d1563 Mon Sep 17 00:00:00 2001
+From: Jonathan Dieter <jdieter@lesbg.com>
+Date: Mon, 27 Feb 2017 10:31:04 +0200
+Subject: usbip: Fix implicit fallthrough warning
+
+From: Jonathan Dieter <jdieter@lesbg.com>
+
+commit cfd6ed4537a9e938fa76facecd4b9cd65b6d1563 upstream.
+
+GCC 7 now warns when switch statements fall through implicitly, and with
+-Werror enabled in configure.ac, that makes these tools unbuildable.
+
+We fix this by notifying the compiler that this particular case statement
+is meant to fall through.
+
+Reviewed-by: Peter Senna Tschudin <peter.senna@gmail.com>
+Signed-off-by: Jonathan Dieter <jdieter@lesbg.com>
+Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ tools/usb/usbip/src/usbip.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/tools/usb/usbip/src/usbip.c
++++ b/tools/usb/usbip/src/usbip.c
+@@ -176,6 +176,8 @@ int main(int argc, char *argv[])
+                       break;
+               case '?':
+                       printf("usbip: invalid option\n");
++                      /* Terminate after printing error */
++                      /* FALLTHRU */
+               default:
+                       usbip_usage();
+                       goto out;
diff --git a/queue-4.9/usbip-fix-potential-format-overflow-in-userspace-tools.patch b/queue-4.9/usbip-fix-potential-format-overflow-in-userspace-tools.patch
new file mode 100644 (file)
index 0000000..0602642
--- /dev/null
@@ -0,0 +1,108 @@
+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: 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_common.c |   28 +++++++++++++++++++++++-----
+ 2 files changed, 31 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,
++                  (long unsigned)sizeof(busid));
++              return -1;
++      }
+       sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
+       if (!sif) {
+--- a/tools/usb/usbip/libsrc/usbip_host_common.c
++++ b/tools/usb/usbip/libsrc/usbip_host_common.c
+@@ -40,13 +40,20 @@ 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, sizeof(status_attr_path),
++                      "%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,
++                  (long unsigned)sizeof(status_attr_path));
++              return -1;
++      }
++
+       fd = open(status_attr_path, O_RDONLY);
+       if (fd < 0) {
+@@ -218,6 +225,7 @@ int usbip_export_device(struct usbip_exp
+ {
+       char attr_name[] = "usbip_sockfd";
+       char sockfd_attr_path[SYSFS_PATH_MAX];
++      int size;
+       char sockfd_buff[30];
+       int ret;
+@@ -237,10 +245,20 @@ int usbip_export_device(struct usbip_exp
+       }
+       /* 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,
++                  (long unsigned)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,
++                  (long unsigned)sizeof(sockfd_buff));
++              return -1;
++      }
+       ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
+                                   strlen(sockfd_buff));
diff --git a/queue-4.9/usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch b/queue-4.9/usbip-prevent-vhci_hcd-driver-from-leaking-a-socket-pointer-address.patch
new file mode 100644 (file)
index 0000000..24be68f
--- /dev/null
@@ -0,0 +1,128 @@
+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       |   25 +++++++++++++++----------
+ tools/usb/usbip/libsrc/vhci_driver.c |    8 ++++----
+ 3 files changed, 20 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/usbip/usbip_common.h
++++ b/drivers/usb/usbip/usbip_common.h
+@@ -271,6 +271,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
+@@ -49,13 +49,17 @@ static ssize_t status_show_vhci(int pdev
+       /*
+        * output example:
+-       * port sta spd dev      socket           local_busid
+-       * 0000 004 000 00000000         c5a7bb80 1-2.3
+-       * 0001 004 000 00000000         d8cee980 2-3.4
++       * port 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.
+        */
+       for (i = 0; i < VHCI_HC_PORTS; i++) {
+               struct vhci_device *vdev = &vhci->vdev[i];
+@@ -68,13 +72,13 @@ static ssize_t status_show_vhci(int pdev
+               if (vdev->ud.status == VDEV_ST_USED) {
+                       out += sprintf(out, "%03u %08x ",
+                                           vdev->speed, vdev->devid);
+-                      out += sprintf(out, "%16p %s",
+-                                          vdev->ud.tcp_socket,
++                      out += sprintf(out, "%06u %s",
++                                          vdev->ud.sockfd,
+                                           dev_name(&vdev->udev->dev));
+               } else {
+                       out += sprintf(out, "000 00000000 ");
+-                      out += sprintf(out, "0000000000000000 0-0");
++                      out += sprintf(out, "000000 0-0");
+               }
+               out += sprintf(out, "\n");
+@@ -125,7 +129,7 @@ static ssize_t status_show(struct device
+       int pdev_nr;
+       out += sprintf(out,
+-                     "port sta spd dev      socket           local_busid\n");
++                     "port sta spd dev      sockfd local_busid\n");
+       pdev_nr = status_name_to_id(attr->attr.name);
+       if (pdev_nr < 0)
+@@ -324,6 +328,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 */