From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A1F60C74A21 for ; Wed, 10 Jul 2019 15:04:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7879C21537 for ; Wed, 10 Jul 2019 15:04:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1562771074; bh=NOZS4sPdMUeEFcRgneiXHh6A/CC/WAk1BAuKohPYOjE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=X3VZ+qb48+v2coywMa1IzIMLYQ8VGyCqg/5xd5ZhRCQFQY5m1WFE3ZD9wyASlEEiy xR4YEPkXkt5ak25TEf5Sw/BBqw5Yn/72KYqqLAppZMWRebics4Q+vC7lojS2IixCmR hET5qLSxs8sxC7yEvS0N8RnlpATHdcYytsIbF7pU= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728009AbfGJPE3 (ORCPT ); Wed, 10 Jul 2019 11:04:29 -0400 Received: from mail.kernel.org ([198.145.29.99]:35588 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728228AbfGJPDg (ORCPT ); Wed, 10 Jul 2019 11:03:36 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 995ED21537; Wed, 10 Jul 2019 15:03:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1562771015; bh=NOZS4sPdMUeEFcRgneiXHh6A/CC/WAk1BAuKohPYOjE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=0/WCktcQ+i6pf44WBrb/7S6VFnKkdsukTmGanZ0YufbXeveCf6MNUyyyrB0fBuDdE y9WquWaYMN3io8GDVqdDmUyzr8xCypN2WJinE2Wz1oSgHgnwfu2RGhBzw9KiA/oiHD OITdbELokc3Wx4DmvaW6uRWWX3oDUP7rN5I02V9U= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Sven Van Asbroeck , Sven Van Asbroeck , Robin Gong , Vinod Koul , Sasha Levin , dmaengine@vger.kernel.org Subject: [PATCH AUTOSEL 4.14 8/8] dmaengine: imx-sdma: fix use-after-free on probe error path Date: Wed, 10 Jul 2019 11:03:18 -0400 Message-Id: <20190710150319.7258-8-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190710150319.7258-1-sashal@kernel.org> References: <20190710150319.7258-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Sven Van Asbroeck [ Upstream commit 2b8066c3deb9140fdf258417a51479b2aeaa7622 ] If probe() fails anywhere beyond the point where sdma_get_firmware() is called, then a kernel oops may occur. Problematic sequence of events: 1. probe() calls sdma_get_firmware(), which schedules the firmware callback to run when firmware becomes available, using the sdma instance structure as the context 2. probe() encounters an error, which deallocates the sdma instance structure 3. firmware becomes available, firmware callback is called with deallocated sdma instance structure 4. use after free - kernel oops ! Solution: only attempt to load firmware when we're certain that probe() will succeed. This guarantees that the firmware callback's context will remain valid. Note that the remove() path is unaffected by this issue: the firmware loader will increment the driver module's use count, ensuring that the module cannot be unloaded while the firmware callback is pending or running. Signed-off-by: Sven Van Asbroeck Reviewed-by: Robin Gong [vkoul: fixed braces for if condition] Signed-off-by: Vinod Koul Signed-off-by: Sasha Levin --- drivers/dma/imx-sdma.c | 48 ++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index a67ec1bdc4e0..80798958706c 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -1821,27 +1821,6 @@ static int sdma_probe(struct platform_device *pdev) if (pdata && pdata->script_addrs) sdma_add_scripts(sdma, pdata->script_addrs); - if (pdata) { - ret = sdma_get_firmware(sdma, pdata->fw_name); - if (ret) - dev_warn(&pdev->dev, "failed to get firmware from platform data\n"); - } else { - /* - * Because that device tree does not encode ROM script address, - * the RAM script in firmware is mandatory for device tree - * probe, otherwise it fails. - */ - ret = of_property_read_string(np, "fsl,sdma-ram-script-name", - &fw_name); - if (ret) - dev_warn(&pdev->dev, "failed to get firmware name\n"); - else { - ret = sdma_get_firmware(sdma, fw_name); - if (ret) - dev_warn(&pdev->dev, "failed to get firmware from device tree\n"); - } - } - sdma->dma_device.dev = &pdev->dev; sdma->dma_device.device_alloc_chan_resources = sdma_alloc_chan_resources; @@ -1883,6 +1862,33 @@ static int sdma_probe(struct platform_device *pdev) of_node_put(spba_bus); } + /* + * Kick off firmware loading as the very last step: + * attempt to load firmware only if we're not on the error path, because + * the firmware callback requires a fully functional and allocated sdma + * instance. + */ + if (pdata) { + ret = sdma_get_firmware(sdma, pdata->fw_name); + if (ret) + dev_warn(&pdev->dev, "failed to get firmware from platform data\n"); + } else { + /* + * Because that device tree does not encode ROM script address, + * the RAM script in firmware is mandatory for device tree + * probe, otherwise it fails. + */ + ret = of_property_read_string(np, "fsl,sdma-ram-script-name", + &fw_name); + if (ret) { + dev_warn(&pdev->dev, "failed to get firmware name\n"); + } else { + ret = sdma_get_firmware(sdma, fw_name); + if (ret) + dev_warn(&pdev->dev, "failed to get firmware from device tree\n"); + } + } + return 0; err_register: -- 2.20.1