bus: hisi_lpc: Unregister logical PIO range to avoid potential use-after-free [Linux 4.19.70]

This Linux kernel change "bus: hisi_lpc: Unregister logical PIO range to avoid potential use-after-free" is included in the Linux 4.19.70 release. This change is authored by John Garry <john.garry [at] huawei.com> on Tue Jul 30 21:29:55 2019 +0800. The commit for this change in Linux stable tree is 649532e (patch) which is from upstream commit 1b15a56. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 1b15a56.

bus: hisi_lpc: Unregister logical PIO range to avoid potential use-after-free

commit 1b15a5632a809ab57d403fd972ca68785363b654 upstream.

If, after registering a logical PIO range, the driver probe later fails,
the logical PIO range memory will be released automatically.

This causes an issue, in that the logical PIO range is not unregistered
and the released range memory may be later referenced.

Fix by unregistering the logical PIO range.

And since we now unregister the logical PIO range for probe failure, avoid
the special ordering of setting logical PIO range ops, which was the
previous (poor) attempt at a safeguard against this.

Cc: stable@vger.kernel.org
Fixes: adf38bb0b595 ("HISI LPC: Support the LPC host on Hip06/Hip07 with DT bindings")
Signed-off-by: John Garry <john.garry@huawei.com>
Signed-off-by: Wei Xu <xuwei5@hisilicon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 11 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/bus/hisi_lpc.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index d5f8545..6fb7111 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -607,24 +607,25 @@ static int hisi_lpc_probe(struct platform_device *pdev)
    range->fwnode = dev->fwnode;
    range->flags = LOGIC_PIO_INDIRECT;
    range->size = PIO_INDIRECT_SIZE;
+   range->hostdata = lpcdev;
+   range->ops = &hisi_lpc_ops;
+   lpcdev->io_host = range;

    ret = logic_pio_register_range(range);
    if (ret) {
        dev_err(dev, "register IO range failed (%d)!\n", ret);
        return ret;
    }
-   lpcdev->io_host = range;

    /* register the LPC host PIO resources */
    if (acpi_device)
        ret = hisi_lpc_acpi_probe(dev);
    else
        ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
-   if (ret)
+   if (ret) {
+       logic_pio_unregister_range(range);
        return ret;
-
-   lpcdev->io_host->hostdata = lpcdev;
-   lpcdev->io_host->ops = &hisi_lpc_ops;
+   }

    io_end = lpcdev->io_host->io_start + lpcdev->io_host->size;
    dev_info(dev, "registered range [%pa - %pa]\n",

Leave a Reply

Your email address will not be published. Required fields are marked *