[PATCH 3/3] UBUNTU: SAUCE: opennsl: bde: check for out-of-bounds index io.dev

Colin King colin.king at canonical.com
Wed Sep 20 10:27:07 UTC 2017


From: Colin Ian King <colin.king at canonical.com>

BugLink: https://launchpad.net/bugs/1718388

io.dev is used as an index into the _devices array and currently
the user may pass any unsigned int value into io.dev which can create
an out-of-bounds error.  Fix this by sanity checking io.dev and
returning -EINVAL for out-of-bounds values of io.dev

Detected by CoverityScan CID#1456895 ("Untrusted array index read")

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 .../systems/bde/linux/user/kernel/linux-user-bde.c | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/ubuntu/opennsl/OpenNSL/sdk-6.4.10-gpl-modules/systems/bde/linux/user/kernel/linux-user-bde.c b/ubuntu/opennsl/OpenNSL/sdk-6.4.10-gpl-modules/systems/bde/linux/user/kernel/linux-user-bde.c
index 2d7a521..44adb45 100644
--- a/ubuntu/opennsl/OpenNSL/sdk-6.4.10-gpl-modules/systems/bde/linux/user/kernel/linux-user-bde.c
+++ b/ubuntu/opennsl/OpenNSL/sdk-6.4.10-gpl-modules/systems/bde/linux/user/kernel/linux-user-bde.c
@@ -912,6 +912,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
         io.d0 = user_bde->num_devices(io.dev);
         break;
     case LUBDE_GET_DEVICE:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         bde_dev = user_bde->get_dev(io.dev);
         if (bde_dev) {
             io.d0 = bde_dev->device;
@@ -926,13 +928,19 @@ _ioctl(unsigned int cmd, unsigned long arg)
         }
         break;
     case LUBDE_GET_DEVICE_TYPE:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         io.d0 = _devices[io.dev].dev_type;
         break;
     case LUBDE_GET_BUS_FEATURES:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         user_bde->pci_bus_features(io.dev, (int *) &io.d0, (int *) &io.d1,
                                    (int *) &io.d2);
         break;
     case LUBDE_PCI_CONFIG_PUT32:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) {
             user_bde->pci_conf_write(io.dev, io.d0, io.d1);
         } else {
@@ -940,6 +948,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
         }
         break;
     case LUBDE_PCI_CONFIG_GET32:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) {
             io.d0 = user_bde->pci_conf_read(io.dev, io.d0);
         } else {
@@ -947,6 +957,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
         }
         break;
     case LUBDE_GET_DMA_INFO:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         inst_id = io.dev;
         if (_bde_multi_inst){
             _dma_resource_get(inst_id, &pbase, &size);
@@ -959,6 +971,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
         io.d2 = USE_LINUX_BDE_MMAP;
         break;
     case LUBDE_ENABLE_INTERRUPTS:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) {
             if (_devices[io.dev].isr && !_devices[io.dev].enabled) {
                 user_bde->interrupt_connect(io.dev,
@@ -978,12 +992,16 @@ _ioctl(unsigned int cmd, unsigned long arg)
         }
         break;
     case LUBDE_DISABLE_INTERRUPTS:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (_devices[io.dev].enabled) {
             user_bde->interrupt_disconnect(io.dev);
             _devices[io.dev].enabled = 0;
         }
         break;
     case LUBDE_WAIT_FOR_INTERRUPT:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) {
             res = &_bde_inst_resource[_devices[io.dev].inst];
 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
@@ -1040,27 +1058,39 @@ _ioctl(unsigned int cmd, unsigned long arg)
         }
         break;
     case LUBDE_WRITE_IRQ_MASK:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         io.rc = lkbde_irq_mask_set(io.dev, io.d0, io.d1, 0);
         break;
     case LUBDE_SPI_READ_REG:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (user_bde->spi_read(io.dev, io.d0, io.dx.buf, io.d1) == -1) {
             io.rc = LUBDE_FAIL;
         } 
         break;
     case LUBDE_SPI_WRITE_REG:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (user_bde->spi_write(io.dev, io.d0, io.dx.buf, io.d1) == -1) {
             io.rc = LUBDE_FAIL;
         }
         break;
     case LUBDE_READ_REG_16BIT_BUS:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         io.d1 = user_bde->read(io.dev, io.d0);
         break;
     case LUBDE_WRITE_REG_16BIT_BUS:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         io.rc = user_bde->write(io.dev, io.d0, io.d1);
         break;
 #if (defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT))
     case LUBDE_CPU_WRITE_REG:
     {
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (lkbde_cpu_write(io.dev, io.d0, (uint32*)io.dx.buf) == -1) {
             io.rc = LUBDE_FAIL;
         }
@@ -1068,6 +1098,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
     }
     case LUBDE_CPU_READ_REG:
     {
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (lkbde_cpu_read(io.dev, io.d0, (uint32*)io.dx.buf) == -1) {
             io.rc = LUBDE_FAIL;
         }
@@ -1075,6 +1107,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
     }
     case LUBDE_CPU_PCI_REGISTER:
     {
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (lkbde_cpu_pci_register(io.dev) == -1) {
             io.rc = LUBDE_FAIL;
         }
@@ -1082,6 +1116,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
     }
 #endif
     case LUBDE_DEV_RESOURCE:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         bde_dev = user_bde->get_dev(io.dev);
         if (bde_dev) {
             if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) {
@@ -1094,12 +1130,16 @@ _ioctl(unsigned int cmd, unsigned long arg)
         }
         break;
     case LUBDE_IPROC_READ_REG:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         io.d1 = user_bde->iproc_read(io.dev, io.d0);
         if (io.d1 == -1) {
             io.rc = LUBDE_FAIL;
         }
         break;
     case LUBDE_IPROC_WRITE_REG:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         if (user_bde->iproc_write(io.dev, io.d0, io.d1) == -1) {
             io.rc = LUBDE_FAIL;
         }
@@ -1108,6 +1148,8 @@ _ioctl(unsigned int cmd, unsigned long arg)
         io.rc = _instance_attach(io.d0, io.d1);
         break;
     case LUBDE_GET_DEVICE_STATE:
+        if (io.dev >= LINUX_BDE_MAX_DEVICES)
+		return -EINVAL;
         io.rc = lkbde_dev_state_get(io.dev, &io.d0);
         break;
     default:
-- 
2.7.4





More information about the kernel-team mailing list