All of lore.kernel.org
 help / color / mirror / Atom feed
From: Niklas Cassel <cassel@kernel.org>
To: Damien Le Moal <dlemoal@kernel.org>,
	Niklas Cassel <cassel@kernel.org>,
	Baokun Li <libaokun1@huawei.com>,
	Sergei Shtylyov <sergei.shtylyov@gmail.com>
Cc: Brian Norris <computersforpeace@gmail.com>,
	stable@vger.kernel.org,
	Damien Le Moal <damien.lemoal@opensource.wdc.com>,
	linux-ide@vger.kernel.org
Subject: [PATCH v4 2/5] ata: sata_fsl: Fix use-after-free of host_priv on probe() failure
Date: Thu, 10 Sep 2026 19:14:08 +0200	[thread overview]
Message-ID: <20260910171406.131211-9-cassel@kernel.org> (raw)
In-Reply-To: <20260910171406.131211-7-cassel@kernel.org>

sata_fsl_host_stop() releases hcr_base and host_priv:

	static void sata_fsl_host_stop(struct ata_host *host)
	{
		struct sata_fsl_host_priv *host_priv = host->private_data;

		iounmap(host_priv->hcr_base);
		kfree(host_priv);
	}

->host_stop() is called by the driver core through the ata_host_stop()
devres action which ata_host_start() registers, so it is called both
when the device is unbound and when probe() fails after
ata_host_activate() has started the host.

The error_exit_with_cleanup label in sata_fsl_probe() releases hcr_base
and host_priv as well, and it is reachable from the two
device_create_file() calls done after ata_host_activate(). In that case
sata_fsl_host_stop() runs on an already freed host_priv, resulting in a
use-after-free and a double iounmap()/kfree().

sata_fsl_probe() also ignores the return value of ata_host_activate(),
so probe() returns success even if activating the host failed.

Check the return value of ata_host_activate() and, once the host has
been activated, leave hcr_base and host_priv to sata_fsl_host_stop().

Note that if ata_host_activate() fails inside ata_host_start(), e.g. if
sata_fsl_port_start() fails, ->host_stop() is not registered and
hcr_base and host_priv are leaked. Leaking them is preferable to freeing
them twice, and this is addressed by a later patch in this series.

Fixes: 6c8ad7e8cf29 ("sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl")
Cc: stable@vger.kernel.org
Signed-off-by: Niklas Cassel <cassel@kernel.org>
---
 drivers/ata/sata_fsl.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 70b210afd291..2123da66dc3c 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -1490,8 +1490,10 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 	 * device discovery process, invoking our port_start() handler &
 	 * error_handler() to execute a dummy Softreset EH session
 	 */
-	ata_host_activate(host, irq, sata_fsl_interrupt, SATA_FSL_IRQ_FLAG,
-			  &sata_fsl_sht);
+	retval = ata_host_activate(host, irq, sata_fsl_interrupt,
+				   SATA_FSL_IRQ_FLAG, &sata_fsl_sht);
+	if (retval)
+		return retval;
 
 	host_priv->intr_coalescing.show = fsl_sata_intr_coalescing_show;
 	host_priv->intr_coalescing.store = fsl_sata_intr_coalescing_store;
@@ -1500,7 +1502,7 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 	host_priv->intr_coalescing.attr.mode = S_IRUGO | S_IWUSR;
 	retval = device_create_file(host->dev, &host_priv->intr_coalescing);
 	if (retval)
-		goto error_exit_with_cleanup;
+		goto error_exit_detach;
 
 	host_priv->rx_watermark.show = fsl_sata_rx_watermark_show;
 	host_priv->rx_watermark.store = fsl_sata_rx_watermark_store;
@@ -1510,16 +1512,24 @@ static int sata_fsl_probe(struct platform_device *ofdev)
 	retval = device_create_file(host->dev, &host_priv->rx_watermark);
 	if (retval) {
 		device_remove_file(&ofdev->dev, &host_priv->intr_coalescing);
-		goto error_exit_with_cleanup;
+		goto error_exit_detach;
 	}
 
 	return 0;
 
-error_exit_with_cleanup:
+	/*
+	 * Once the host has been activated, hcr_base and host_priv are
+	 * released by sata_fsl_host_stop(), which is called by the driver core
+	 * through the ata_host_stop() devres action registered by
+	 * ata_host_start(). Releasing them here as well would result in a
+	 * double iounmap() and a use-after-free.
+	 */
+error_exit_detach:
+	ata_host_detach(host);
 
-	if (host)
-		ata_host_detach(host);
+	return retval;
 
+error_exit_with_cleanup:
 	if (hcr_base)
 		iounmap(hcr_base);
 	kfree(host_priv);
-- 
2.55.0


  parent reply	other threads:[~2026-09-10 17:14 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-10 17:14 [PATCH v4 0/5] ata: Do not release the host resources twice on probe() failure Niklas Cassel
2026-09-10 17:14 ` [PATCH v4 1/5] ata: ahci_st: Assert the power down reset in the probe() error path Niklas Cassel
2026-09-10 17:29   ` sashiko-bot
2026-09-10 17:39     ` Niklas Cassel
2026-09-10 17:14 ` Niklas Cassel [this message]
2026-09-10 17:14 ` [PATCH v4 3/5] ata: libahci: Free the IRQs when activating a multi-IRQ host fails Niklas Cassel
2026-09-10 17:14 ` [PATCH v4 4/5] ata: libata: Do not leave ata_host_stop() registered when activation fails Niklas Cassel
2026-09-10 17:14 ` [PATCH v4 5/5] ata: libata-core: Fix the ata_host_register() kdoc Niklas Cassel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260910171406.131211-9-cassel@kernel.org \
    --to=cassel@kernel.org \
    --cc=computersforpeace@gmail.com \
    --cc=damien.lemoal@opensource.wdc.com \
    --cc=dlemoal@kernel.org \
    --cc=libaokun1@huawei.com \
    --cc=linux-ide@vger.kernel.org \
    --cc=sergei.shtylyov@gmail.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.