From: Greg Kroah-Hartman Date: Thu, 4 Nov 2021 14:11:31 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.19.216~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6f90742590798a5cfcce93982b6ce610be2ba0cd;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: ib-qib-protect-from-buffer-overflow-in-struct-qib_user_sdma_pkt-fields.patch ib-qib-use-struct_size-helper.patch --- 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 index 00000000000..31639086c12 --- /dev/null +++ b/queue-4.14/ib-qib-protect-from-buffer-overflow-in-struct-qib_user_sdma_pkt-fields.patch @@ -0,0 +1,115 @@ +From d39bf40e55e666b5905fdbd46a0dced030ce87be Mon Sep 17 00:00:00 2001 +From: Mike Marciniszyn +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 + +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 +Reviewed-by: Dennis Dalessandro +Signed-off-by: Mike Marciniszyn +Signed-off-by: Dennis Dalessandro +Signed-off-by: Jason Gunthorpe +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..7a7d891490c --- /dev/null +++ b/queue-4.14/ib-qib-use-struct_size-helper.patch @@ -0,0 +1,58 @@ +From 829ca44ecf60e9b6f83d0161a6ef10c1304c5060 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Wed, 29 May 2019 10:13:26 -0500 +Subject: IB/qib: Use struct_size() helper + +From: Gustavo A. R. Silva + +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 +Reviewed-by: Dennis Dalessandro +Signed-off-by: Jason Gunthorpe +Signed-off-by: Mike Marciniszyn +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + + #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. diff --git a/queue-4.14/series b/queue-4.14/series index 6699f334924..06594d7464e 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -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