From: Vladimir Sokolovsky Date: Sun, 15 May 2016 06:15:09 +0000 (+0300) Subject: IB/security: Restrict use of the write() interface X-Git-Tag: vofed-3.18-2-rc2^0 X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=0f85f68471b29fbd1544e1664a4b8e12e52dd318;p=~tnikolova%2Fcompat-rdma%2F.git IB/security: Restrict use of the write() interface 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 Signed-off-by: Linus Torvalds Signed-off-by: Jason Gunthorpe [ Expanded check to all known write() entry points ] Cc: stable@vger.kernel.org Signed-off-by: Doug Ledford Signed-off-by: Vladimir Sokolovsky --- diff --git a/linux-next-cherry-picks/0046-IB-security-Restrict-use-of-the-write-interface.patch b/linux-next-cherry-picks/0046-IB-security-Restrict-use-of-the-write-interface.patch new file mode 100644 index 0000000..189952f --- /dev/null +++ b/linux-next-cherry-picks/0046-IB-security-Restrict-use-of-the-write-interface.patch @@ -0,0 +1,152 @@ +From e6bd18f57aad1a2d1ef40e646d03ed0f2515c9e3 Mon Sep 17 00:00:00 2001 +From: Jason Gunthorpe +Date: Sun, 10 Apr 2016 19:13:13 -0600 +Subject: [PATCH] IB/security: Restrict use of the write() interface + +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 +Signed-off-by: Linus Torvalds +Signed-off-by: Jason Gunthorpe +[ Expanded check to all known write() entry points ] +Cc: stable@vger.kernel.org +Signed-off-by: Doug Ledford +--- + drivers/infiniband/core/ucm.c | 4 ++++ + drivers/infiniband/core/ucma.c | 3 +++ + drivers/infiniband/core/uverbs_main.c | 5 +++++ + drivers/infiniband/hw/qib/qib_file_ops.c | 5 +++++ + include/rdma/ib.h | 16 ++++++++++++++++ + 7 files changed, 40 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c +index 4a9aa04..7713ef0 100644 +--- a/drivers/infiniband/core/ucm.c ++++ b/drivers/infiniband/core/ucm.c +@@ -48,6 +48,7 @@ + + #include + ++#include + #include + #include + #include +@@ -1103,6 +1104,9 @@ static ssize_t ib_ucm_write(struct file *filp, const char __user *buf, + 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; + +diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c +index dd3bcce..c0f3826 100644 +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -1574,6 +1574,9 @@ static ssize_t ucma_write(struct file *filp, const char __user *buf, + 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; + +diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c +index 28ba2cc..31f422a 100644 +--- a/drivers/infiniband/core/uverbs_main.c ++++ b/drivers/infiniband/core/uverbs_main.c +@@ -48,6 +48,8 @@ + + #include + ++#include ++ + #include "uverbs.h" + + MODULE_AUTHOR("Roland Dreier"); +@@ -709,6 +711,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, + int srcu_key; + ssize_t ret; + ++ if (WARN_ON_ONCE(!ib_safe_file_access(filp))) ++ return -EACCES; ++ + if (count < sizeof hdr) + return -EINVAL; + +diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c +index e449e39..24f4a78 100644 +--- a/drivers/infiniband/hw/qib/qib_file_ops.c ++++ b/drivers/infiniband/hw/qib/qib_file_ops.c +@@ -45,6 +45,8 @@ + #include + #include + ++#include ++ + #include "qib.h" + #include "qib_common.h" + #include "qib_user_sdma.h" +@@ -2067,6 +2069,9 @@ static ssize_t qib_write(struct file *fp, const char __user *data, + 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; +diff --git a/include/rdma/ib.h b/include/rdma/ib.h +index cf8f9e7..a6b9370 100644 +--- a/include/rdma/ib.h ++++ b/include/rdma/ib.h +@@ -34,6 +34,7 @@ + #define _RDMA_IB_H + + #include ++#include + + 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 */ +-- +1.8.3.1 +