]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Aug 2016 15:58:05 +0000 (17:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Aug 2016 15:58:05 +0000 (17:58 +0200)
added patches:

queue-3.14/ib-security-restrict-use-of-the-write-interface.patch

index 3656e2d7a7d7ff882a163444f25a067c2da8ca16..3c4510582266a7a9eb70c8d38d3cb6b4effe326c 100644 (file)
-From ben@decadent.org.uk  Sun Aug 14 17:34:33 2016
-From: Ben Hutchings <ben@decadent.org.uk>
-Date: Tue, 31 May 2016 03:40:50 +0100
+From e6bd18f57aad1a2d1ef40e646d03ed0f2515c9e3 Mon Sep 17 00:00:00 2001
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+Date: Sun, 10 Apr 2016 19:13:13 -0600
 Subject: IB/security: Restrict use of the write() interface
-To: stable@vger.kernel.org
-Cc: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>, Doug Ledford <dledford@redhat.com>, linux-rdma@vger.kernel.org
-Message-ID: <20160531024050.GL7555@decadent.org.uk>
-Content-Disposition: inline
 
-From: Ben Hutchings <ben@decadent.org.uk>
+From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
 
-Commit e6bd18f57aad ("IB/security: Restrict use of the write()
-interface") fixed a security problem with various write()
-implementations in the Infiniband subsystem.  In older kernel versions
-the ipath_write() function has the same problem and needs the same
-restriction.  (The ipath driver has been completely removed upstream.)
+commit e6bd18f57aad1a2d1ef40e646d03ed0f2515c9e3 upstream.
 
-Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+The drivers/infiniband stack uses write() as a replacement for
+bi-directional ioctl().  This is not safe. There are ways to
+trigger write calls that result in the return structure that
+is normally written to user space being shunted off to user
+specified kernel memory instead.
+
+For the immediate repair, detect and deny suspicious accesses to
+the write API.
+
+For long term, update the user space libraries and the kernel API
+to something that doesn't present the same security vulnerabilities
+(likely a structured ioctl() interface).
 
+The impacted uAPI interfaces are generally only available if
+hardware from drivers/infiniband is installed in the system.
+
+Reported-by: Jann Horn <jann@thejh.net>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
+[ Expanded check to all known write() entry points ]
+Signed-off-by: Doug Ledford <dledford@redhat.com>
+[ Expanded to include removed ipath driver, and dropped non-existent
+  hfi1 driver ]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 ---
+ drivers/infiniband/core/ucm.c                |    4 ++++
+ drivers/infiniband/core/ucma.c               |    3 +++
+ drivers/infiniband/core/uverbs_main.c        |    5 +++++
  drivers/infiniband/hw/ipath/ipath_file_ops.c |    5 +++++
- 1 file changed, 5 insertions(+)
+ drivers/infiniband/hw/qib/qib_file_ops.c     |    5 +++++
+ include/rdma/ib.h                            |   16 ++++++++++++++++
+ 6 files changed, 38 insertions(+)
 
+--- a/drivers/infiniband/core/ucm.c
++++ b/drivers/infiniband/core/ucm.c
+@@ -48,6 +48,7 @@
+ #include <asm/uaccess.h>
++#include <rdma/ib.h>
+ #include <rdma/ib_cm.h>
+ #include <rdma/ib_user_cm.h>
+ #include <rdma/ib_marshall.h>
+@@ -1104,6 +1105,9 @@ static ssize_t ib_ucm_write(struct file
+       struct ib_ucm_cmd_hdr hdr;
+       ssize_t result;
++      if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
++              return -EACCES;
++
+       if (len < sizeof(hdr))
+               return -EINVAL;
+--- a/drivers/infiniband/core/ucma.c
++++ b/drivers/infiniband/core/ucma.c
+@@ -1487,6 +1487,9 @@ static ssize_t ucma_write(struct file *f
+       struct rdma_ucm_cmd_hdr hdr;
+       ssize_t ret;
++      if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
++              return -EACCES;
++
+       if (len < sizeof(hdr))
+               return -EINVAL;
+--- a/drivers/infiniband/core/uverbs_main.c
++++ b/drivers/infiniband/core/uverbs_main.c
+@@ -48,6 +48,8 @@
+ #include <asm/uaccess.h>
++#include <rdma/ib.h>
++
+ #include "uverbs.h"
+ MODULE_AUTHOR("Roland Dreier");
+@@ -605,6 +607,9 @@ static ssize_t ib_uverbs_write(struct fi
+       struct ib_uverbs_cmd_hdr hdr;
+       __u32 flags;
++      if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
++              return -EACCES;
++
+       if (count < sizeof hdr)
+               return -EINVAL;
 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
 +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
 @@ -45,6 +45,8 @@
  #include <linux/cpu.h>
  #include <asm/pgtable.h>
  
-+#include <rdma/ib.h>
++#include "rdma/ib.h"
 +
  #include "ipath_kernel.h"
  #include "ipath_common.h"
@@ -37,9 +108,60 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        ssize_t ret = 0;
        void *dest;
  
++      if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
++              return -EACCES;
++
+       if (count < sizeof(cmd.type)) {
+               ret = -EINVAL;
+               goto bail;
+--- a/drivers/infiniband/hw/qib/qib_file_ops.c
++++ b/drivers/infiniband/hw/qib/qib_file_ops.c
+@@ -45,6 +45,8 @@
+ #include <linux/delay.h>
+ #include <linux/export.h>
++#include <rdma/ib.h>
++
+ #include "qib.h"
+ #include "qib_common.h"
+ #include "qib_user_sdma.h"
+@@ -2058,6 +2060,9 @@ static ssize_t qib_write(struct file *fp
+       ssize_t ret = 0;
+       void *dest;
 +      if (WARN_ON_ONCE(!ib_safe_file_access(fp)))
 +              return -EACCES;
 +
        if (count < sizeof(cmd.type)) {
                ret = -EINVAL;
                goto bail;
+--- a/include/rdma/ib.h
++++ b/include/rdma/ib.h
+@@ -34,6 +34,7 @@
+ #define _RDMA_IB_H
+ #include <linux/types.h>
++#include <linux/sched.h>
+ struct ib_addr {
+       union {
+@@ -86,4 +87,19 @@ struct sockaddr_ib {
+       __u64                   sib_scope_id;
+ };
++/*
++ * The IB interfaces that use write() as bi-directional ioctl() are
++ * fundamentally unsafe, since there are lots of ways to trigger "write()"
++ * calls from various contexts with elevated privileges. That includes the
++ * traditional suid executable error message writes, but also various kernel
++ * interfaces that can write to file descriptors.
++ *
++ * This function provides protection for the legacy API by restricting the
++ * calling context.
++ */
++static inline bool ib_safe_file_access(struct file *filp)
++{
++      return filp->f_cred == current_cred() && segment_eq(get_fs(), USER_DS);
++}
++
+ #endif /* _RDMA_IB_H */