Received: by 10.213.65.68 with SMTP id h4csp1611912imn; Thu, 5 Apr 2018 00:13:01 -0700 (PDT) X-Google-Smtp-Source: AIpwx4+F7LtaL5cbA+x2mi32h6HbxrXlljX1mtfRq2WvC0uPBbObXrCgZSQd2O63afM9Ry3d3M7f X-Received: by 2002:a17:902:788e:: with SMTP id q14-v6mr22322164pll.396.1522912381281; Thu, 05 Apr 2018 00:13:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522912381; cv=none; d=google.com; s=arc-20160816; b=Sfnr+WLACmDA3m/q3jsAi+gwiqzOr1eJHCQ98anzYWvlx4//trcV3wl0ngOxQY8Ndp Ug6ubrljhsnOJrjd4URph2cC8V/uJhOj31kxzZ2ij3cotn7qiqFVFPzUUVZOhYZraZFi LHzFR8af5Lt3blG2AHJ1hPEyWImcs9XquHfZxN65akm/JA0CXjGVksrCe/4T/BkV9ImD TTiJPAk6/V0BH1GNshGUlWsPw2QCHhYJyRyM7ptXTOcuf/OWGGoZrEyBPY32sk4k18pL BlSWEkfkmkbuyv/Ga9g2LP04kbtKeBUh0lHG3GDcSyYXM4iTqgT1SjtVBcrpMu4fEJLL 4bJg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:dlp-filter:cms-type:message-id :date:subject:cc:to:from:dkim-signature:dkim-filter :arc-authentication-results; bh=y7YzgXW+/ggi+PMa7m+kSX1Wr3pKYdpK+U1EOacZWDE=; b=TT4nHo5nfU04tyzjVv5nxvEAoL6skibpgGyIq8NVX8rDRU5WPv3gTaQRltIPaTF+3s LpL8cr1pOjYzikWfnaLjspp5uBeFsA/HFUFUgckekpiziXpWbyKfWB76ipGsbmKmxlmy /SNnErmsU+4+Gvq+2aKP0YStlnkzxaUg3nfXOCb+WiwtLPLyD0AT3gJX4juUG6Odnbl6 bAAKzkoh4PfiA9W9vFP/OM63hhhjhQdHUfZnIJl86nZpcinRbB59Qx7cFn+wuU/pS/RS O21P0l1kpzWcI/DH+mxMHA+YBGSTHx0xuWiLB3ldFpuuPWJrXHICbMzE6N93BNWEm+GO 9a6A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@samsung.com header.s=mail20170921 header.b=gwCF1MX0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=samsung.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n20si5183735pgc.508.2018.04.05.00.12.47; Thu, 05 Apr 2018 00:13:01 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@samsung.com header.s=mail20170921 header.b=gwCF1MX0; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=samsung.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751384AbeDEHKX (ORCPT + 99 others); Thu, 5 Apr 2018 03:10:23 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:35887 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750853AbeDEHKV (ORCPT ); Thu, 5 Apr 2018 03:10:21 -0400 Received: from epcas1p4.samsung.com (unknown [182.195.41.48]) by mailout1.samsung.com (KnoxPortal) with ESMTP id 20180405071019epoutp015a868fff46f37996f420133dbbb81e71~ieJg_sdOC2004920049epoutp019; Thu, 5 Apr 2018 07:10:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.samsung.com 20180405071019epoutp015a868fff46f37996f420133dbbb81e71~ieJg_sdOC2004920049epoutp019 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1522912219; bh=y7YzgXW+/ggi+PMa7m+kSX1Wr3pKYdpK+U1EOacZWDE=; h=From:To:Cc:Subject:Date:References:From; b=gwCF1MX0T+FQtg9JUMS2UGvcePJ/CzPxyeXFYaOtnmyLZ9WRckBb3pf11n7vI4aLf IyeCTkLaIIlbDu38h+4Gb7LrpB0ASbgojCc3CZSm4ygIe+4e0u02hc8AS5nsF1B/KL CciKRPIrhd2HOKblVkz//LG+RGC4+2yutUIuWZ6w= Received: from epsmges2p2.samsung.com (unknown [182.195.40.59]) by epcas1p1.samsung.com (KnoxPortal) with ESMTP id 20180405071018epcas1p10a339874ce324faf5fe1a4d3b31dd65d~ieJgrh_nW1223812238epcas1p1c; Thu, 5 Apr 2018 07:10:18 +0000 (GMT) Received: from epcas2p3.samsung.com ( [182.195.41.55]) by epsmges2p2.samsung.com (Symantec Messaging Gateway) with SMTP id 6D.FC.04072.ADBC5CA5; Thu, 5 Apr 2018 16:10:18 +0900 (KST) Received: from epsmgms2p2new.samsung.com (unknown [182.195.42.143]) by epcas2p1.samsung.com (KnoxPortal) with ESMTP id 20180405071018epcas2p193288469c86f6afb2c8f7b0151dd400c~ieJgPx7sa1398313983epcas2p1l; Thu, 5 Apr 2018 07:10:18 +0000 (GMT) X-AuditID: b6c32a46-b6dff70000000fe8-63-5ac5cbda9ab6 Received: from epmmp2 ( [203.254.227.17]) by epsmgms2p2new.samsung.com (Symantec Messaging Gateway) with SMTP id 7A.78.03827.ADBC5CA5; Thu, 5 Apr 2018 16:10:18 +0900 (KST) Received: from localhost.localdomain ([10.253.107.61]) by mmp2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0P6P00DPDAL0WM60@mmp2.samsung.com>; Thu, 05 Apr 2018 16:10:18 +0900 (KST) From: Ji-Hun Kim To: dan.carpenter@oracle.com, gregkh@linuxfoundation.org, baijiaju1990@gmail.com, forest@alittletooquiet.net Cc: dartnorris@gmail.com, santhameena13@gmail.com, julia.lawall@lip6.fr, ji_hun.kim@samsung.com, y.k.oh@samsung.com, devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org, kernel-janitors@vger.kernel.org Subject: [PATCH v5 1/2] staging: vt6655: check for memory allocation failures Date: Thu, 05 Apr 2018 16:09:19 +0900 Message-id: <1522912160-21009-1-git-send-email-ji_hun.kim@samsung.com> X-Mailer: git-send-email 1.9.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrAKsWRmVeSWpSXmKPExsWy7bCmue6t00ejDHZNNLVYN3Ehk8Xrf9NZ LM68P8tksefML3aL+xMesVo0L17PZtF/ejujxbIHpxkttt6Stri8aw6bxclt8hZbun6wOvB4 NDe+Z/W4t+8wi8fOWXfZPfbPXcPusXdLlsfHp7dYPPq2rGL0+LxJLoAjKtUmIzUxJbVIITUv OT8lMy/dVsk7ON453tTMwFDX0NLCXEkhLzE31VbJxSdA1y0zB+hWJYWyxJxSoFBAYnGxkr6d TVF+aUmqQkZ+cYmtUrShoZGeoYG5npGRkZ6JeayVkSlQSUJqxp0f/5gKVgdW7P6/i7GB8bhT FyMnh4SAicS8568Zuxi5OIQEdjBKXP37jQUkISTwnVFizl0zmKKTZ5ewQRRtYJT4Oek7lPOD UeLNprNsIFVsApoSG7uvMYLYIgJ5EvtWHWYCKWIWuMQosXjtSuYuRg4OYQF/iROHeEBqWARU JT7d3AzWyyvgJrFrxllmiG1yEiePTWYF6ZUQ2MAmcf7tC3aIhAvQsvtMELawxKvjW6Di0hLP Vm1khLCrJRZc2cECYddI3Py/FKreWKK35wLYAmYBPomOw3/ZQe6REOCV6GgTgijxkJh9bxHU SEeJPXMbWCEhESvxfsl3lgmMkgsYGVYxiqUWFOempxYbFRjpFSfmFpfmpesl5+duYgSnHi23 HYxLzvkcYhTgYFTi4W34diRKiDWxrLgy9xCjBAezkggva/PRKCHelMTKqtSi/Pii0pzU4kOM psDgmMgsJZqcD0yLeSXxhiaWBiZmZobmRqYG5krivK0BLlFCAumJJanZqakFqUUwfUwcnFIN jDl3sxrnx6ZKRc7QtFrbyzPjqUlKPvc2mw3ZQsJ6hUWXZ75nX6tlJta7d/LxNxHak4NPWTxQ aczm5Wnt+VJ1oqXSqtIj+7RZSl5/zt4DfxOd3A6XfXatLJ/B94Hp9bSgaeIac3IMwxl4Ey4v WuTyqvQ5Yx/bBW3PBInishWb6z/P3/pVOZlNiaU4I9FQi7moOBEAzwnInFMDAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprJLMWRmVeSWpSXmKPExsVy+t9jQd1bp49GGVyZLG6xbuJCJovX/6az WJx5f5bJYs+ZX+wW9yc8YrVoXryezaL/9HZGi2UPTjNabL0lbXF51xw2i5Pb5C22dP1gdeDx aG58z+pxb99hFo+ds+6ye+yfu4bdY++WLI+PT2+xePRtWcXo8XmTXABHFJdNSmpOZllqkb5d AlfGnR//mApWB1bs/r+LsYHxuFMXIyeHhICJxMmzS9i6GLk4hATWMUosezmPGcL5wSgxt2UG E0gVm4CmxMbua4wgtohAnsT2ndNYQIqYBS4xSmx/PBcowcEhLOAr8fGUBUgNi4CqxKebm9lA bF4BN4ldM84yQ2yTkzh5bDLrBEauBYwMqxglUwuKc9Nzi40KjPJSy/WKE3OLS/PS9ZLzczcx AgNs22Gt/h2Mj5fEH2IU4GBU4uHt+HskSog1say4MvcQowQHs5IIL2vz0Sgh3pTEyqrUovz4 otKc1OJDjNIcLErivPz5xyKFBNITS1KzU1MLUotgskwcnFINjLphRWs+W+9q1J7AnKLsseHx VLMP7Q0fk18FtH6O/P7rvlf7tjBlwzlFvXeaz6Qe+NnHyC3guehp2hzBF9ddb+jwzjJK3LTj lP1/Pm4nmyVfd71boz+R41XL8bq8qTyf9cL2m/02L2sL4NksrlFVeqfi24SJfmu2lO9Zv3Ff 1v0Ds8WcnG9bP1RiKc5INNRiLipOBACUF3UPLAIAAA== X-CMS-MailID: 20180405071018epcas2p193288469c86f6afb2c8f7b0151dd400c X-Msg-Generator: CA CMS-TYPE: 102P DLP-Filter: Pass X-CFilter-Loop: Reflected X-CMS-RootMailID: 20180405071018epcas2p193288469c86f6afb2c8f7b0151dd400c X-RootMTR: 20180405071018epcas2p193288469c86f6afb2c8f7b0151dd400c References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org There are no null pointer checking on rd_info and td_info values which are allocated by kzalloc. It has potential null pointer dereferencing issues. Implement error handling code on device_init_rd*, device_init_td* and vnt_start for the allocation failures. Signed-off-by: Ji-Hun Kim --- Changes v5: - Add error handling case for device_alloc_rx_buf() failures. - Add device_free_rx_buf() which is corresponding free function of device_allocated_rx_buf(). And change duplicated codes by this function. - Modify error handling code about freeing allocated value in the loops to more proper ways. - Change goto label names following coding-style conventions. Changes v4: - Fix potential memory leaks from error handling code from device init functions in vnt_start(). Changes v3: - Modify return type of device_init_rd*, device_init_td*. Then add returns error code at those functions and vnt_start as well. Changes v2: - Delete WARN_ON which can makes crashes on some machines. - Instead of return directly, goto freeing function for freeing previously allocated memory in the for loop after kzalloc() failed. - In the freeing function, add if statement for freeing to only allocated values. drivers/staging/vt6655/device_main.c | 144 ++++++++++++++++++++++++++++------- 1 file changed, 118 insertions(+), 26 deletions(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index fbc4bc6..700c03c 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -19,6 +19,7 @@ * device_print_info - print out resource * device_rx_srv - rx service function * device_alloc_rx_buf - rx buffer pre-allocated function + * device_free_rx_buf - free rx buffer function * device_free_tx_buf - free tx buffer function * device_init_rd0_ring- initial rd dma0 ring * device_init_rd1_ring- initial rd dma1 ring @@ -124,14 +125,15 @@ static void device_free_info(struct vnt_private *priv); static void device_print_info(struct vnt_private *priv); -static void device_init_rd0_ring(struct vnt_private *priv); -static void device_init_rd1_ring(struct vnt_private *priv); -static void device_init_td0_ring(struct vnt_private *priv); -static void device_init_td1_ring(struct vnt_private *priv); +static int device_init_rd0_ring(struct vnt_private *priv); +static int device_init_rd1_ring(struct vnt_private *priv); +static int device_init_td0_ring(struct vnt_private *priv); +static int device_init_td1_ring(struct vnt_private *priv); static int device_rx_srv(struct vnt_private *priv, unsigned int idx); static int device_tx_srv(struct vnt_private *priv, unsigned int idx); static bool device_alloc_rx_buf(struct vnt_private *, struct vnt_rx_desc *); +static void device_free_rx_buf(struct vnt_private *priv, struct vnt_rx_desc *rd); static void device_init_registers(struct vnt_private *priv); static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *); static void device_free_td0_ring(struct vnt_private *priv); @@ -528,20 +530,28 @@ static void device_free_rings(struct vnt_private *priv) priv->tx0_bufs, priv->tx_bufs_dma0); } -static void device_init_rd0_ring(struct vnt_private *priv) +static int device_init_rd0_ring(struct vnt_private *priv) { int i; dma_addr_t curr = priv->rd0_pool_dma; struct vnt_rx_desc *desc; + int ret; /* Init the RD0 ring entries */ for (i = 0; i < priv->opts.rx_descs0; i ++, curr += sizeof(struct vnt_rx_desc)) { desc = &priv->aRD0Ring[i]; desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); + if (!desc->rd_info) { + ret = -ENOMEM; + goto err_free_desc; + } - if (!device_alloc_rx_buf(priv, desc)) + if (!device_alloc_rx_buf(priv, desc)) { dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); + ret = -ENOMEM; + goto err_free_rd; + } desc->next = &priv->aRD0Ring[(i + 1) % priv->opts.rx_descs0]; desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); @@ -550,22 +560,44 @@ static void device_init_rd0_ring(struct vnt_private *priv) if (i > 0) priv->aRD0Ring[i-1].next_desc = cpu_to_le32(priv->rd0_pool_dma); priv->pCurrRD[0] = &priv->aRD0Ring[0]; + + return 0; + +err_free_rd: + kfree(desc->rd_info); + +err_free_desc: + while (--i) { + desc = &priv->aRD0Ring[i]; + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); + } + + return ret; } -static void device_init_rd1_ring(struct vnt_private *priv) +static int device_init_rd1_ring(struct vnt_private *priv) { int i; dma_addr_t curr = priv->rd1_pool_dma; struct vnt_rx_desc *desc; + int ret; /* Init the RD1 ring entries */ for (i = 0; i < priv->opts.rx_descs1; i ++, curr += sizeof(struct vnt_rx_desc)) { desc = &priv->aRD1Ring[i]; desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL); + if (!desc->rd_info) { + ret = -ENOMEM; + goto err_free_desc; + } - if (!device_alloc_rx_buf(priv, desc)) + if (!device_alloc_rx_buf(priv, desc)) { dev_err(&priv->pcid->dev, "can not alloc rx bufs\n"); + ret = -ENOMEM; + goto err_free_rd; + } desc->next = &priv->aRD1Ring[(i+1) % priv->opts.rx_descs1]; desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc)); @@ -574,6 +606,20 @@ static void device_init_rd1_ring(struct vnt_private *priv) if (i > 0) priv->aRD1Ring[i-1].next_desc = cpu_to_le32(priv->rd1_pool_dma); priv->pCurrRD[1] = &priv->aRD1Ring[0]; + + return 0; + +err_free_rd: + kfree(desc->rd_info); + +err_free_desc: + while (--i) { + desc = &priv->aRD1Ring[i]; + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); + } + + return ret; } static void device_free_rd0_ring(struct vnt_private *priv) @@ -582,13 +628,8 @@ static void device_free_rd0_ring(struct vnt_private *priv) for (i = 0; i < priv->opts.rx_descs0; i++) { struct vnt_rx_desc *desc = &priv->aRD0Ring[i]; - struct vnt_rd_info *rd_info = desc->rd_info; - - dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, - priv->rx_buf_sz, DMA_FROM_DEVICE); - - dev_kfree_skb(rd_info->skb); + device_free_rx_buf(priv, desc); kfree(desc->rd_info); } } @@ -599,28 +640,28 @@ static void device_free_rd1_ring(struct vnt_private *priv) for (i = 0; i < priv->opts.rx_descs1; i++) { struct vnt_rx_desc *desc = &priv->aRD1Ring[i]; - struct vnt_rd_info *rd_info = desc->rd_info; - - dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, - priv->rx_buf_sz, DMA_FROM_DEVICE); - - dev_kfree_skb(rd_info->skb); + device_free_rx_buf(priv, desc); kfree(desc->rd_info); } } -static void device_init_td0_ring(struct vnt_private *priv) +static int device_init_td0_ring(struct vnt_private *priv) { int i; dma_addr_t curr; struct vnt_tx_desc *desc; + int ret; curr = priv->td0_pool_dma; for (i = 0; i < priv->opts.tx_descs[0]; i++, curr += sizeof(struct vnt_tx_desc)) { desc = &priv->apTD0Rings[i]; desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); + if (!desc->td_info) { + ret = -ENOMEM; + goto err_free_desc; + } desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ; desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ; @@ -632,13 +673,24 @@ static void device_init_td0_ring(struct vnt_private *priv) if (i > 0) priv->apTD0Rings[i-1].next_desc = cpu_to_le32(priv->td0_pool_dma); priv->apTailTD[0] = priv->apCurrTD[0] = &priv->apTD0Rings[0]; + + return 0; + +err_free_desc: + while (--i) { + desc = &priv->apTD0Rings[i]; + kfree(desc->td_info); + } + + return ret; } -static void device_init_td1_ring(struct vnt_private *priv) +static int device_init_td1_ring(struct vnt_private *priv) { int i; dma_addr_t curr; struct vnt_tx_desc *desc; + int ret; /* Init the TD ring entries */ curr = priv->td1_pool_dma; @@ -646,6 +698,10 @@ static void device_init_td1_ring(struct vnt_private *priv) i++, curr += sizeof(struct vnt_tx_desc)) { desc = &priv->apTD1Rings[i]; desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL); + if (!desc->td_info) { + ret = -ENOMEM; + goto err_free_desc; + } desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ; desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ; @@ -657,6 +713,16 @@ static void device_init_td1_ring(struct vnt_private *priv) if (i > 0) priv->apTD1Rings[i-1].next_desc = cpu_to_le32(priv->td1_pool_dma); priv->apTailTD[1] = priv->apCurrTD[1] = &priv->apTD1Rings[0]; + + return 0; + +err_free_desc: + while (--i) { + desc = &priv->apTD1Rings[i]; + kfree(desc->td_info); + } + + return ret; } static void device_free_td0_ring(struct vnt_private *priv) @@ -745,6 +811,16 @@ static bool device_alloc_rx_buf(struct vnt_private *priv, return true; } +static void device_free_rx_buf(struct vnt_private *priv, + struct vnt_rx_desc *rd) +{ + struct vnt_rd_info *rd_info = rd->rd_info; + + dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma, + priv->rx_buf_sz, DMA_FROM_DEVICE); + dev_kfree_skb(rd_info->skb); +} + static const u8 fallback_rate0[5][5] = { {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, @@ -1165,10 +1241,18 @@ static int vnt_start(struct ieee80211_hw *hw) } dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n"); - device_init_rd0_ring(priv); - device_init_rd1_ring(priv); - device_init_td0_ring(priv); - device_init_td1_ring(priv); + ret = device_init_rd0_ring(priv); + if (ret) + return ret; + ret = device_init_rd1_ring(priv); + if (ret) + goto err_free_rd0_ring; + ret = device_init_td0_ring(priv); + if (ret) + goto err_free_rd1_ring; + ret = device_init_td1_ring(priv); + if (ret) + goto err_free_td0_ring; device_init_registers(priv); @@ -1178,6 +1262,14 @@ static int vnt_start(struct ieee80211_hw *hw) ieee80211_wake_queues(hw); return 0; + +err_free_td0_ring: + device_free_td0_ring(priv); +err_free_rd1_ring: + device_free_rd1_ring(priv); +err_free_rd0_ring: + device_free_rd0_ring(priv); + return ret; } static void vnt_stop(struct ieee80211_hw *hw) -- 1.9.1