]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Nov 2021 14:11:31 +0000 (15:11 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Nov 2021 14:11:31 +0000 (15:11 +0100)
added patches:
ib-qib-protect-from-buffer-overflow-in-struct-qib_user_sdma_pkt-fields.patch
ib-qib-use-struct_size-helper.patch

queue-4.14/ib-qib-protect-from-buffer-overflow-in-struct-qib_user_sdma_pkt-fields.patch [new file with mode: 0644]
queue-4.14/ib-qib-use-struct_size-helper.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/ib-qib-protect-from-buffer-overflow-in-struct-qib_user_sdma_pkt-fields.patch b/queue-4.14/ib-qib-protect-from-buffer-overflow-in-struct-qib_user_sdma_pkt-fields.patch
new file mode 100644 (file)
index 0000000..3163908
--- /dev/null
@@ -0,0 +1,115 @@
+From d39bf40e55e666b5905fdbd46a0dced030ce87be Mon Sep 17 00:00:00 2001
+From: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
+Date: Tue, 12 Oct 2021 13:55:19 -0400
+Subject: IB/qib: Protect from buffer overflow in struct qib_user_sdma_pkt fields
+
+From: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
+
+commit d39bf40e55e666b5905fdbd46a0dced030ce87be upstream.
+
+Overflowing either addrlimit or bytes_togo can allow userspace to trigger
+a buffer overflow of kernel memory. Check for overflows in all the places
+doing math on user controlled buffers.
+
+Fixes: f931551bafe1 ("IB/qib: Add new qib driver for QLogic PCIe InfiniBand adapters")
+Link: https://lore.kernel.org/r/20211012175519.7298.77738.stgit@awfm-01.cornelisnetworks.com
+Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
+Reviewed-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
+Signed-off-by: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
+Signed-off-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/hw/qib/qib_user_sdma.c |   33 ++++++++++++++++++++----------
+ 1 file changed, 23 insertions(+), 10 deletions(-)
+
+--- a/drivers/infiniband/hw/qib/qib_user_sdma.c
++++ b/drivers/infiniband/hw/qib/qib_user_sdma.c
+@@ -607,7 +607,7 @@ done:
+ /*
+  * How many pages in this iovec element?
+  */
+-static int qib_user_sdma_num_pages(const struct iovec *iov)
++static size_t qib_user_sdma_num_pages(const struct iovec *iov)
+ {
+       const unsigned long addr  = (unsigned long) iov->iov_base;
+       const unsigned long  len  = iov->iov_len;
+@@ -663,7 +663,7 @@ static void qib_user_sdma_free_pkt_frag(
+ static int qib_user_sdma_pin_pages(const struct qib_devdata *dd,
+                                  struct qib_user_sdma_queue *pq,
+                                  struct qib_user_sdma_pkt *pkt,
+-                                 unsigned long addr, int tlen, int npages)
++                                 unsigned long addr, int tlen, size_t npages)
+ {
+       struct page *pages[8];
+       int i, j;
+@@ -727,7 +727,7 @@ static int qib_user_sdma_pin_pkt(const s
+       unsigned long idx;
+       for (idx = 0; idx < niov; idx++) {
+-              const int npages = qib_user_sdma_num_pages(iov + idx);
++              const size_t npages = qib_user_sdma_num_pages(iov + idx);
+               const unsigned long addr = (unsigned long) iov[idx].iov_base;
+               ret = qib_user_sdma_pin_pages(dd, pq, pkt, addr,
+@@ -829,8 +829,8 @@ static int qib_user_sdma_queue_pkts(cons
+               unsigned pktnw;
+               unsigned pktnwc;
+               int nfrags = 0;
+-              int npages = 0;
+-              int bytes_togo = 0;
++              size_t npages = 0;
++              size_t bytes_togo = 0;
+               int tiddma = 0;
+               int cfur;
+@@ -890,7 +890,11 @@ static int qib_user_sdma_queue_pkts(cons
+                       npages += qib_user_sdma_num_pages(&iov[idx]);
+-                      bytes_togo += slen;
++                      if (check_add_overflow(bytes_togo, slen, &bytes_togo) ||
++                          bytes_togo > type_max(typeof(pkt->bytes_togo))) {
++                              ret = -EINVAL;
++                              goto free_pbc;
++                      }
+                       pktnwc += slen >> 2;
+                       idx++;
+                       nfrags++;
+@@ -909,8 +913,7 @@ static int qib_user_sdma_queue_pkts(cons
+               }
+               if (frag_size) {
+-                      int tidsmsize, n;
+-                      size_t pktsize;
++                      size_t tidsmsize, n, pktsize, sz, addrlimit;
+                       n = npages*((2*PAGE_SIZE/frag_size)+1);
+                       pktsize = struct_size(pkt, addr, n);
+@@ -928,14 +931,24 @@ static int qib_user_sdma_queue_pkts(cons
+                       else
+                               tidsmsize = 0;
+-                      pkt = kmalloc(pktsize+tidsmsize, GFP_KERNEL);
++                      if (check_add_overflow(pktsize, tidsmsize, &sz)) {
++                              ret = -EINVAL;
++                              goto free_pbc;
++                      }
++                      pkt = kmalloc(sz, GFP_KERNEL);
+                       if (!pkt) {
+                               ret = -ENOMEM;
+                               goto free_pbc;
+                       }
+                       pkt->largepkt = 1;
+                       pkt->frag_size = frag_size;
+-                      pkt->addrlimit = n + ARRAY_SIZE(pkt->addr);
++                      if (check_add_overflow(n, ARRAY_SIZE(pkt->addr),
++                                             &addrlimit) ||
++                          addrlimit > type_max(typeof(pkt->addrlimit))) {
++                              ret = -EINVAL;
++                              goto free_pbc;
++                      }
++                      pkt->addrlimit = addrlimit;
+                       if (tiddma) {
+                               char *tidsm = (char *)pkt + pktsize;
diff --git a/queue-4.14/ib-qib-use-struct_size-helper.patch b/queue-4.14/ib-qib-use-struct_size-helper.patch
new file mode 100644 (file)
index 0000000..7a7d891
--- /dev/null
@@ -0,0 +1,58 @@
+From 829ca44ecf60e9b6f83d0161a6ef10c1304c5060 Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
+Date: Wed, 29 May 2019 10:13:26 -0500
+Subject: IB/qib: Use struct_size() helper
+
+From: Gustavo A. R. Silva <gustavo@embeddedor.com>
+
+commit 829ca44ecf60e9b6f83d0161a6ef10c1304c5060 upstream.
+
+Make use of the struct_size() helper instead of an open-coded version
+in order to avoid any potential type mistakes, in particular in the
+context in which this code is being used.
+
+So, replace the following form:
+
+sizeof(*pkt) + sizeof(pkt->addr[0])*n
+
+with:
+
+struct_size(pkt, addr, n)
+
+Also, notice that variable size is unnecessary, hence it is removed.
+
+This code was detected with the help of Coccinelle.
+
+Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
+Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
+Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
+Signed-off-by: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/infiniband/hw/qib/qib_user_sdma.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/infiniband/hw/qib/qib_user_sdma.c
++++ b/drivers/infiniband/hw/qib/qib_user_sdma.c
+@@ -41,6 +41,7 @@
+ #include <linux/rbtree.h>
+ #include <linux/spinlock.h>
+ #include <linux/delay.h>
++#include <linux/overflow.h>
+ #include "qib.h"
+ #include "qib_user_sdma.h"
+@@ -908,10 +909,11 @@ static int qib_user_sdma_queue_pkts(cons
+               }
+               if (frag_size) {
+-                      int pktsize, tidsmsize, n;
++                      int tidsmsize, n;
++                      size_t pktsize;
+                       n = npages*((2*PAGE_SIZE/frag_size)+1);
+-                      pktsize = sizeof(*pkt) + sizeof(pkt->addr[0])*n;
++                      pktsize = struct_size(pkt, addr, n);
+                       /*
+                        * Determine if this is tid-sdma or just sdma.
index 6699f334924d2202912bc04dfbe3dc73c71c896e..06594d7464e6ab691cab2a916bbbf338119d25a2 100644 (file)
@@ -3,3 +3,5 @@ media-firewire-firedtv-avc-fix-a-buffer-overflow-in-avc_ca_pmt.patch
 mm-zsmalloc-prepare-to-variable-max_physmem_bits.patch
 arch-pgtable-define-max_possible_physmem_bits-where-needed.patch
 arm-9120-1-revert-amba-make-use-of-1-irqs-warn.patch
+ib-qib-use-struct_size-helper.patch
+ib-qib-protect-from-buffer-overflow-in-struct-qib_user_sdma_pkt-fields.patch