-
Wang Hai authored
I got a null-ptr-deref report: KASAN: null-ptr-deref in range [0x0000000000000090-0x0000000000000097] ... RIP: 0010:regulator_enable+0x84/0x260 ... Call Trace: ahci_platform_enable_regulators+0xae/0x320 ahci_platform_enable_resources+0x1a/0x120 ahci_probe+0x4f/0x1b9 platform_probe+0x10b/0x280 ... entry_SYSCALL_64_after_hwframe+0x44/0xae If devm_regulator_get() in ahci_platform_get_resources() fails, hpriv->phy_regulator will point to NULL, when enabling or disabling it, null-ptr-deref will occur. ahci_probe() ahci_platform_get_resources() devm_regulator_get(, "phy") // failed, let phy_regulator = NULL ahci_platform_enable_resources() ahci_platform_enable_regulators() regulator_enable(hpriv->phy_regulator) // null-ptr-deref commit 962399bb ("ata: libahci_platform: Fix regulator_get_optional() misuse") replaces devm_regulator_get_optional() with devm_regulator_get(), but PHY regulator omits to delete "hpriv->phy_regulator = NULL;" like AHCI. Delete it like AHCI regulator to fix this bug. Fixes: commit 962399bb ("ata: libahci_platform: Fix regulator_get_optional() misuse") Reported-by:
Hulk Robot <hulkci@huawei.com> Signed-off-by:
Wang Hai <wanghai38@huawei.com> Reviewed-by:
Hans de Goede <hdegoede@redhat.com> Signed-off-by:
Damien Le Moal <damien.lemoal@wdc.com>
Wang Hai authoredI got a null-ptr-deref report: KASAN: null-ptr-deref in range [0x0000000000000090-0x0000000000000097] ... RIP: 0010:regulator_enable+0x84/0x260 ... Call Trace: ahci_platform_enable_regulators+0xae/0x320 ahci_platform_enable_resources+0x1a/0x120 ahci_probe+0x4f/0x1b9 platform_probe+0x10b/0x280 ... entry_SYSCALL_64_after_hwframe+0x44/0xae If devm_regulator_get() in ahci_platform_get_resources() fails, hpriv->phy_regulator will point to NULL, when enabling or disabling it, null-ptr-deref will occur. ahci_probe() ahci_platform_get_resources() devm_regulator_get(, "phy") // failed, let phy_regulator = NULL ahci_platform_enable_resources() ahci_platform_enable_regulators() regulator_enable(hpriv->phy_regulator) // null-ptr-deref commit 962399bb ("ata: libahci_platform: Fix regulator_get_optional() misuse") replaces devm_regulator_get_optional() with devm_regulator_get(), but PHY regulator omits to delete "hpriv->phy_regulator = NULL;" like AHCI. Delete it like AHCI regulator to fix this bug. Fixes: commit 962399bb ("ata: libahci_platform: Fix regulator_get_optional() misuse") Reported-by:
Hulk Robot <hulkci@huawei.com> Signed-off-by:
Wang Hai <wanghai38@huawei.com> Reviewed-by:
Hans de Goede <hdegoede@redhat.com> Signed-off-by:
Damien Le Moal <damien.lemoal@wdc.com>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
libahci_platform.c 20.62 KiB
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* AHCI SATA platform library
*
* Copyright 2004-2005 Red Hat, Inc.
* Jeff Garzik <jgarzik@pobox.com>
* Copyright 2010 MontaVista Software, LLC.
* Anton Vorontsov <avorontsov@ru.mvista.com>
*/
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/gfp.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/libata.h>
#include <linux/ahci_platform.h>
#include <linux/phy/phy.h>
#include <linux/pm_runtime.h>
#include <linux/of_platform.h>
#include <linux/reset.h>
#include "ahci.h"
static void ahci_host_stop(struct ata_host *host);
struct ata_port_operations ahci_platform_ops = {
.inherits = &ahci_ops,
.host_stop = ahci_host_stop,
};
EXPORT_SYMBOL_GPL(ahci_platform_ops);
/**
* ahci_platform_enable_phys - Enable PHYs
* @hpriv: host private area to store config values
*
* This function enables all the PHYs found in hpriv->phys, if any.
* If a PHY fails to be enabled, it disables all the PHYs already
* enabled in reverse order and returns an error.
*
* RETURNS:
* 0 on success otherwise a negative error code
*/
int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
{
int rc, i;
for (i = 0; i < hpriv->nports; i++) {
rc = phy_init(hpriv->phys[i]);
if (rc)
goto disable_phys;
rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA);
if (rc) {
phy_exit(hpriv->phys[i]);
goto disable_phys;
}
rc = phy_power_on(hpriv->phys[i]);
if (rc && !(rc == -EOPNOTSUPP && (hpriv->flags & AHCI_HFLAG_IGN_NOTSUPP_POWER_ON))) {
phy_exit(hpriv->phys[i]);
goto disable_phys;
}
}
return 0;
disable_phys: