--- /dev/null
+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;
--- /dev/null
+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.