aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorDennis Dalessandro <dennis.dalessandro@intel.com>2014-02-20 11:02:48 -0500
committerRoland Dreier <roland@purestorage.com>2014-03-17 19:16:51 -0400
commit1c20c81909455f64f2df6107cb099ee5569d9f62 (patch)
tree87a26985e77081c38cea01b810d73a5893578ecb /drivers/infiniband
parentcfbf8d4857c26a8a307fb7cd258074c9dcd8c691 (diff)
IB/qib: Fix potential buffer overrun in sending diag packet routine
Guard against a potential buffer overrun. Right now the qib driver is protected by the fact that the data structure in question is only 16 bits. Should that ever change the problem will be exposed. There is a similar defect in the ipath driver and this brings the two code paths into sync. Reported-by: Nico Golde <nico@ngolde.de> Reported-by: Fabian Yamaguchi <fabs@goesec.de> Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/qib/qib_diag.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c
index 1686fd4bda87..07f9030a8f10 100644
--- a/drivers/infiniband/hw/qib/qib_diag.c
+++ b/drivers/infiniband/hw/qib/qib_diag.c
@@ -546,7 +546,7 @@ static ssize_t qib_diagpkt_write(struct file *fp,
546 size_t count, loff_t *off) 546 size_t count, loff_t *off)
547{ 547{
548 u32 __iomem *piobuf; 548 u32 __iomem *piobuf;
549 u32 plen, clen, pbufn; 549 u32 plen, pbufn, maxlen_reserve;
550 struct qib_diag_xpkt dp; 550 struct qib_diag_xpkt dp;
551 u32 *tmpbuf = NULL; 551 u32 *tmpbuf = NULL;
552 struct qib_devdata *dd; 552 struct qib_devdata *dd;
@@ -590,15 +590,20 @@ static ssize_t qib_diagpkt_write(struct file *fp,
590 } 590 }
591 ppd = &dd->pport[dp.port - 1]; 591 ppd = &dd->pport[dp.port - 1];
592 592
593 /* need total length before first word written */ 593 /*
594 /* +1 word is for the qword padding */ 594 * need total length before first word written, plus 2 Dwords. One Dword
595 plen = sizeof(u32) + dp.len; 595 * is for padding so we get the full user data when not aligned on
596 clen = dp.len >> 2; 596 * a word boundary. The other Dword is to make sure we have room for the
597 597 * ICRC which gets tacked on later.
598 if ((plen + 4) > ppd->ibmaxlen) { 598 */
599 maxlen_reserve = 2 * sizeof(u32);
600 if (dp.len > ppd->ibmaxlen - maxlen_reserve) {
599 ret = -EINVAL; 601 ret = -EINVAL;
600 goto bail; /* before writing pbc */ 602 goto bail;
601 } 603 }
604
605 plen = sizeof(u32) + dp.len;
606
602 tmpbuf = vmalloc(plen); 607 tmpbuf = vmalloc(plen);
603 if (!tmpbuf) { 608 if (!tmpbuf) {
604 qib_devinfo(dd->pcidev, 609 qib_devinfo(dd->pcidev,
@@ -638,11 +643,11 @@ static ssize_t qib_diagpkt_write(struct file *fp,
638 */ 643 */
639 if (dd->flags & QIB_PIO_FLUSH_WC) { 644 if (dd->flags & QIB_PIO_FLUSH_WC) {
640 qib_flush_wc(); 645 qib_flush_wc();
641 qib_pio_copy(piobuf + 2, tmpbuf, clen - 1); 646 qib_pio_copy(piobuf + 2, tmpbuf, plen - 1);
642 qib_flush_wc(); 647 qib_flush_wc();
643 __raw_writel(tmpbuf[clen - 1], piobuf + clen + 1); 648 __raw_writel(tmpbuf[plen - 1], piobuf + plen + 1);
644 } else 649 } else
645 qib_pio_copy(piobuf + 2, tmpbuf, clen); 650 qib_pio_copy(piobuf + 2, tmpbuf, plen);
646 651
647 if (dd->flags & QIB_USE_SPCL_TRIG) { 652 if (dd->flags & QIB_USE_SPCL_TRIG) {
648 u32 spcl_off = (pbufn >= dd->piobcnt2k) ? 2047 : 1023; 653 u32 spcl_off = (pbufn >= dd->piobcnt2k) ? 2047 : 1023;