staging: vt6656: Don't leak memory in drivers/staging/vt6656/ioctl.c::private_ioctl()
[firefly-linux-kernel-4.4.55.git] / drivers / staging / vt6656 / ioctl.c
index 49390026dea358e4d86c828a7077abffe0c31167..d59456c29df15db61b310281841c16164e6cc4dc 100644 (file)
@@ -295,6 +295,10 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
                        result = -EFAULT;
                        break;
                }
+               if (sList.uItem > (ULONG_MAX - sizeof(SBSSIDList)) / sizeof(SBSSIDItem)) {
+                       result = -EINVAL;
+                       break;
+               }
                pList = (PSBSSIDList)kmalloc(sizeof(SBSSIDList) + (sList.uItem * sizeof(SBSSIDItem)), (int)GFP_ATOMIC);
                if (pList == NULL) {
                        result = -ENOMEM;
@@ -557,7 +561,11 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
                        result = -EFAULT;
                        break;
                }
-               pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
+               if (sNodeList.uItem > (ULONG_MAX - sizeof(SNodeList)) / sizeof(SNodeItem)) {
+                       result = -ENOMEM;
+                       break;
+               }
+               pNodeList = kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
                if (pNodeList == NULL) {
                        result = -ENOMEM;
                        break;
@@ -593,6 +601,7 @@ int private_ioctl(PSDevice pDevice, struct ifreq *rq)
                        }
                }
                if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
+                       kfree(pNodeList);
                        result = -EFAULT;
                        break;
                }