Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp606406ybl; Fri, 10 Jan 2020 03:56:35 -0800 (PST) X-Google-Smtp-Source: APXvYqztLTXgLXWI/qfmDrftPuDD+1hVe6NYUphg72DdqRVjjjmw6aJlVmnQq4auUfr/xgGyLX6m X-Received: by 2002:aca:2207:: with SMTP id b7mr1935700oic.109.1578657394898; Fri, 10 Jan 2020 03:56:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1578657394; cv=none; d=google.com; s=arc-20160816; b=uZ4dQXTeei8+a4eu/EADXI6e1f85gErut1nuNWwMJfuyEdtQHS46i/givjzSD+u7uW NzwUzseHjUL5xNzOt4MuQhhtI0fz0z3gmlidOFtKzmzcbQ5WbLwCDaJdjT3csbpp1ocq JlS1r8caR/Hvot0s8QmrQaCT9TXxwZLthwmHqBF8riUdlEixRl81y1HEmGx10W3dhY80 k4zNGVB26u8zH8aLIlQ5jaP7kDbikVqyH5/TNB0h5Imbe8AZb41xbHcqZ6bz9RCnb54o 8tKpKwVOrd2laLi7T4ApEcB5SylgiWrDbRg49K121m+yTeZ+wgG5XORsdDvPaDYOl89Q PuSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=KRTjgVnH2UcXgL+8XsLYIbJObf6tBxlO9kcMPl48SSE=; b=bJsS0ug0JKeJR9IjuNjLcbpns0hxj0AtLaZVOqoy1v8f8SBstgJoFX4Oc27GtQUJ7J LaZD5XURzRWvKMlCx/BXsq0RSAkIkGjCirLENL4ETIcnQuf/riL4x/q1gX9WRR6DuxXe XvVeLSUmxazW8PEpDd0ZChNJTXVkiEi1BKZrVYIqaM2QnYMDi8vZVMh+tRDK6zAxW+XK HVqkVsqtxIUioNQSpXCqx94cvGa5BiZhPhG7B97JALhZ+3anD9ZMDFLOAipzA+HyTcmK xerd2kC2Xb1nnd4vt78UKWIC6Bhqhjr0ass+q7MdRDLbef8pRl9Nry4tovBWmmcVGQhA kK+A== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e5si1099468oti.104.2020.01.10.03.56.23; Fri, 10 Jan 2020 03:56:34 -0800 (PST) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728056AbgAJLy3 (ORCPT + 99 others); Fri, 10 Jan 2020 06:54:29 -0500 Received: from foss.arm.com ([217.140.110.172]:43110 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728029AbgAJLy2 (ORCPT ); Fri, 10 Jan 2020 06:54:28 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 62F3F13A1; Fri, 10 Jan 2020 03:54:27 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4A3493F534; Fri, 10 Jan 2020 03:54:26 -0800 (PST) From: Andre Przywara To: "David S . Miller" , Radhey Shyam Pandey Cc: Michal Simek , Robert Hancock , netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 03/14] net: axienet: Fix DMA descriptor cleanup path Date: Fri, 10 Jan 2020 11:54:04 +0000 Message-Id: <20200110115415.75683-4-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200110115415.75683-1-andre.przywara@arm.com> References: <20200110115415.75683-1-andre.przywara@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When axienet_dma_bd_init() bails out during the initialisation process, it might do so with parts of the structure already allocated and initialised, while other parts have not been touched yet. Before returning in this case, we call axienet_dma_bd_release(), which does not take care of this corner case. This is most obvious by the first loop happily dereferencing lp->rx_bd_v, which we actually check to be non NULL *afterwards*. Make sure we only unmap or free already allocated structures, by: - directly returning with -ENOMEM if nothing has been allocated at all - checking for lp->rx_bd_v to be non-NULL *before* using it - only unmapping allocated DMA RX regions This avoids NULL pointer dereferences when initialisation fails. Signed-off-by: Andre Przywara --- .../net/ethernet/xilinx/xilinx_axienet_main.c | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 97482cf093ce..7e90044cf2d9 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -160,24 +160,37 @@ static void axienet_dma_bd_release(struct net_device *ndev) int i; struct axienet_local *lp = netdev_priv(ndev); + /* If we end up here, tx_bd_v must have been DMA allocated. */ + dma_free_coherent(ndev->dev.parent, + sizeof(*lp->tx_bd_v) * lp->tx_bd_num, + lp->tx_bd_v, + lp->tx_bd_p); + + if (!lp->rx_bd_v) + return; + for (i = 0; i < lp->rx_bd_num; i++) { - dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys, - lp->max_frm_size, DMA_FROM_DEVICE); + /* A NULL skb means this descriptor has not been initialised + * at all. + */ + if (!lp->rx_bd_v[i].skb) + break; + dev_kfree_skb(lp->rx_bd_v[i].skb); - } - if (lp->rx_bd_v) { - dma_free_coherent(ndev->dev.parent, - sizeof(*lp->rx_bd_v) * lp->rx_bd_num, - lp->rx_bd_v, - lp->rx_bd_p); - } - if (lp->tx_bd_v) { - dma_free_coherent(ndev->dev.parent, - sizeof(*lp->tx_bd_v) * lp->tx_bd_num, - lp->tx_bd_v, - lp->tx_bd_p); + /* For each descriptor, we programmed cntrl with the (non-zero) + * descriptor size, after it had been successfully allocated. + * So a non-zero value in there means we need to unmap it. + */ + if (lp->rx_bd_v[i].cntrl) + dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys, + lp->max_frm_size, DMA_FROM_DEVICE); } + + dma_free_coherent(ndev->dev.parent, + sizeof(*lp->rx_bd_v) * lp->rx_bd_num, + lp->rx_bd_v, + lp->rx_bd_p); } /** @@ -207,7 +220,7 @@ static int axienet_dma_bd_init(struct net_device *ndev) sizeof(*lp->tx_bd_v) * lp->tx_bd_num, &lp->tx_bd_p, GFP_KERNEL); if (!lp->tx_bd_v) - goto out; + return -ENOMEM; lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent, sizeof(*lp->rx_bd_v) * lp->rx_bd_num, -- 2.17.1