VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45869

CVE-2026-45869

Description

In the Linux kernel, the following vulnerability has been resolved:

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

In probe(), request_irq() is called before allocating/registering a power_supply handle. If an interrupt is fired between the call to request_irq() and power_supply_register(), the power_supply handle will be used uninitialized in power_supply_changed() in wm97xx_bat_update() (triggered from the interrupt handler). This will lead to a NULL pointer dereference since

Fix this racy NULL pointer dereference by making sure the IRQ is requested _after_ the registration of the power_supply handle. Since the IRQ is the last thing requests in the probe() now, remove the error path for freeing it. Instead add one for unregistering the power_supply handle when IRQ request fails.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A race condition in Linux kernel's wm97xx battery driver causes NULL pointer dereference when an interrupt fires before power_supply registration.

Vulnerability

In the Linux kernel's wm97xx battery driver (power: supply: wm97xx), a race condition exists in the probe sequence. The function request_irq() is called before power_supply_register(), meaning the interrupt handler (wm97xx_bat_update()) can be invoked before the power_supply handle is allocated and registered. If an interrupt fires between these two calls, the handler calls power_supply_changed() with an uninitialized (NULL) power supply pointer, leading to a NULL pointer dereference. The bug affects all kernel versions where this driver is present until the fix is applied [1][2].

Exploitation

An attacker with the ability to cause a hardware interrupt on the system (e.g., through battery insertion/removal or other power events) can trigger the race condition. No authentication is required, and no user interaction is needed beyond the normal operation that generates the interrupt. The exploitation window is between the request_irq() and power_supply_register() calls during driver probe.

Impact

Successful exploitation results in a NULL pointer dereference, which likely causes a kernel panic or oops, leading to a denial of service (system crash). The crash occurs at the privilege level of the kernel, so the entire system is affected. No information disclosure or privilege escalation is described in the references.

Mitigation

The fix is to reorder the probe sequence so that power_supply_register() is called before request_irq(). This ensures the power supply handle is valid before any interrupts can be processed. The commit IDs are: 438f9a303ea8b55162b2d5376490c2ab3ec165a0 [1] and 3d7b5391bb95505b3581c1fb77150c467ab92864 [2] (stable backports). Users should apply the kernel patch or update to a kernel version containing this fix. No workaround is available if the patch is not applied.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

16
9b7d77cb046b

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 6.1.165via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index a0e1eaa25d93ec..e2a41f9c903c5c 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
3d7b5391bb95

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 5.10.252via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index a0e1eaa25d93ec..e2a41f9c903c5c 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
93bdf715d33c

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 6.12.75via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index 1cc38d1437d91f..181bb7ab64d607 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
c0def811ad8d

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 6.18.14via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index b3b0c37a9dd2d5..f00722c88c6fea 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
86183153c299

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 6.6.128via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index f4b190adb33594..d3e5c2f7762a6f 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
dfaf235d5a6b

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 6.19.4via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index b3b0c37a9dd2d5..f00722c88c6fea 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
39fe0eac6d75

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 7.0via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index b3b0c37a9dd2d5..f00722c88c6fea 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
438f9a303ea8

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWaqar HameedDec 20, 2025Fixed in 5.15.202via kernel-cna
1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index a0e1eaa25d93ec..e2a41f9c903c5c 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
86183153c299

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index f4b190adb33594..d3e5c2f7762a6f 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
438f9a303ea8

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index a0e1eaa25d93ec..e2a41f9c903c5c 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
93bdf715d33c

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index 1cc38d1437d91f..181bb7ab64d607 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
9b7d77cb046b

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index a0e1eaa25d93ec..e2a41f9c903c5c 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
c0def811ad8d

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index b3b0c37a9dd2d5..f00722c88c6fea 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
dfaf235d5a6b

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index b3b0c37a9dd2d5..f00722c88c6fea 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
39fe0eac6d75

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index b3b0c37a9dd2d5..f00722c88c6fea 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    
3d7b5391bb95

power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()

1 file changed · +19 16
  • drivers/power/supply/wm97xx_battery.c+19 16 modified
    diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
    index a0e1eaa25d93ec..e2a41f9c903c5c 100644
    --- a/drivers/power/supply/wm97xx_battery.c
    +++ b/drivers/power/supply/wm97xx_battery.c
    @@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     				     "failed to get charge GPIO\n");
     	if (charge_gpiod) {
     		gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
    -		ret = request_irq(gpiod_to_irq(charge_gpiod),
    -				wm97xx_chrg_irq, 0,
    -				"AC Detect", dev);
    -		if (ret)
    -			return dev_err_probe(&dev->dev, ret,
    -					     "failed to request GPIO irq\n");
     		props++;	/* POWER_SUPPLY_PROP_STATUS */
     	}
     
    @@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		props++;	/* POWER_SUPPLY_PROP_VOLTAGE_MIN */
     
     	prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
    -	if (!prop) {
    -		ret = -ENOMEM;
    -		goto err3;
    -	}
    +	if (!prop)
    +		return -ENOMEM;
     
     	prop[i++] = POWER_SUPPLY_PROP_PRESENT;
     	if (charge_gpiod)
    @@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
     		schedule_work(&bat_work);
     	} else {
     		ret = PTR_ERR(bat_psy);
    -		goto err4;
    +		goto free;
    +	}
    +
    +	if (charge_gpiod) {
    +		ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
    +				  0, "AC Detect", dev);
    +		if (ret) {
    +			dev_err_probe(&dev->dev, ret,
    +				      "failed to request GPIO irq\n");
    +			goto unregister;
    +		}
     	}
     
     	return 0;
    -err4:
    +
    +unregister:
    +	power_supply_unregister(bat_psy);
    +
    +free:
     	kfree(prop);
    -err3:
    -	if (charge_gpiod)
    -		free_irq(gpiod_to_irq(charge_gpiod), dev);
    +
     	return ret;
     }
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Incorrect ordering in probe: request_irq() is called before power_supply_register(), creating a race window where an interrupt handler dereferences an uninitialized power_supply pointer."

Attack vector

An attacker who can cause a charge-GPIO interrupt to fire on the wm97xx battery device during the probe sequence can trigger a NULL pointer dereference. The interrupt handler `wm97xx_chrg_irq` calls `wm97xx_bat_update()`, which invokes `power_supply_changed()` on the `power_supply` handle. Because `request_irq()` was called before `power_supply_register()`, the handle is still NULL when the interrupt arrives, causing a NULL pointer dereference in the kernel [patch_id=2661885]. No special privileges are required beyond the ability to trigger the hardware interrupt during the narrow race window in probe.

Affected code

The vulnerability is in the `wm97xx_bat_probe()` function in `drivers/power/supply/wm97xx_battery.c` [patch_id=2661885]. The original code called `request_irq()` for the charge-GPIO interrupt before `power_supply_register()` had been called, leaving the `power_supply` handle uninitialized during the window between those two calls.

What the fix does

The patch moves the `request_irq()` call from early in `wm97xx_bat_probe()` (before `power_supply_register()`) to after the `power_supply` handle has been successfully registered [patch_id=2661885]. This eliminates the race window where an interrupt could fire on an uninitialized handle. The error-handling labels are also reworked: the old `err3`/`err4` labels that freed the IRQ and the `prop` array are replaced with `unregister` (which calls `power_supply_unregister()`) and `free` (which frees `prop`), ensuring proper cleanup when the IRQ request fails after registration.

Preconditions

  • configThe wm97xx battery driver must be probed on a system with a charge-GPIO interrupt configured
  • inputA charge-GPIO interrupt must fire during the window between request_irq() and power_supply_register() in the probe function

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.