Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp1292858ybi; Fri, 2 Aug 2019 12:48:18 -0700 (PDT) X-Google-Smtp-Source: APXvYqzuzxcXnw33Ic8lrz+Czif7vX+bvlVLBQ4bB7ve50YkmeY3wpILqrW7spiqReGcHCroHeNU X-Received: by 2002:aa7:9786:: with SMTP id o6mr59982962pfp.222.1564775298123; Fri, 02 Aug 2019 12:48:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564775298; cv=none; d=google.com; s=arc-20160816; b=aDv2kYZ6Xwdr2TqL4RLn33MEDYIHkHCWVIkYNryDPRfwn9XI/kRPT9t5RPA3LXGU4B u2WHnKbQcEj2VcUGja9mnS/BC+WWGL8+SNw3VM4J56hVybgTSa/21JI4km0buRxJAXLK y0rpJkQMmTkmVcd+8OtMDxdjau6RvOj9Js2dRUr83i/0KOQjj1oBoajeQSPzOdmorKrB tlozQ38LQWnyGB/lzYHxj3VjqP7nad5Jo6QQgDd53QE1hwdcnhUluiopBAaQ9gePD+FY 9yCUkjw+9wqD+LI2iAYwcv71k98hVKdvdsUgPjv6o3woh4NNIRfPeqyfilQXbqJcnCPz tL/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=7z081z4jFp+/gujeA8WITFQsYhRper6XRuz5OLA86cc=; b=x83mQNPHJow+/MPoiksfSplYp+3p8tvlTqbG0aR6p7MtttZeyetvWyWw1rQuV7D2yY E9BT6rWuRwKuofiBrKOb0LIm0hJsnoGMgknHDyB1BqeaHgTa+lc279HafI+or7Hpfml4 qotQdIQNDxdeWPiCZiQtP3ZrM+4OrMd1Gi1NB7BylRDPuIYrGSmWUBFik2IZ1MZQQKC0 bDiWywN7wvf3aasSZT+HumeWUx7z7+ID02x3GI459LD7KNCq7rNEVJwN51lR5S9TaRs6 bwJr6K1EDv9jI5G4u7Cbc1dQ6V0QoPagEm+Y7fHQPygl2610yq8j/vbF9uobj4dQgTLn Mgpw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=nkzeN31G; 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 ci23si6803267pjb.85.2019.08.02.12.48.03; Fri, 02 Aug 2019 12:48:18 -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=@kernel.org header.s=default header.b=nkzeN31G; 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 S2407219AbfHBKEL (ORCPT + 99 others); Fri, 2 Aug 2019 06:04:11 -0400 Received: from mail.kernel.org ([198.145.29.99]:41716 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391731AbfHBJkh (ORCPT ); Fri, 2 Aug 2019 05:40:37 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 69ED72086A; Fri, 2 Aug 2019 09:40:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1564738835; bh=RS0NyBFS6JKuvq0PDVkbfKTmJJz/+1JMsm+1zqfCZuo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=nkzeN31Gm+PhSDS5pFb4YbmY+LV3QISvI/mwKGP0OBth6ukGt1T9SgIIxJ3YALjma BpZE/Kj6wp/p1fwQZLFpykUkNdU3YU6+7XMlyNm7hFPPTBiWtGEL1EpFxNlKq2Kf04 Qcbk1CXiI+4zdFAKZ+ceuw2uyNdYYZOoQ35Qjmho= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Sven Van Asbroeck , Robin Gong , Vinod Koul , Sasha Levin Subject: [PATCH 4.9 004/223] dmaengine: imx-sdma: fix use-after-free on probe error path Date: Fri, 2 Aug 2019 11:33:49 +0200 Message-Id: <20190802092239.001709269@linuxfoundation.org> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190802092238.692035242@linuxfoundation.org> References: <20190802092238.692035242@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org [ 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 84856ac75a09..9f240b2d85a5 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