CVE-2026-46109
Description
In the Linux kernel, the following vulnerability has been resolved:
usb: ulpi: fix memory leak on ulpi_register() error paths
Commit 01af542392b5 ("usb: ulpi: fix double free in ulpi_register_interface() error path") removed kfree(ulpi) from ulpi_register_interface() to fix a double-free when device_register() fails.
But when ulpi_of_register() or ulpi_read_id() fail before device_register() is called, the ulpi allocation is leaked.
Add kfree(ulpi) on both error paths to properly clean up the allocation.
Affected products
1Patches
10be2c1d825f54usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index d895cf6532a21f..95caad156de58a 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
b0c0d44adb55usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index c9f52cd1cfb2bf..b1957dc687a8c8 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
2a71e01b2cf9usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index d895cf6532a21f..95caad156de58a 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
0b9fcab1b860usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index b34fb65813c45e..9b69148128e5bf 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
f30ccfc29855usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index b34fb65813c45e..9b69148128e5bf 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
b0c0d44adb55usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index c9f52cd1cfb2bf..b1957dc687a8c8 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
be2c1d825f54usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index d895cf6532a21f..95caad156de58a 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
f30ccfc29855usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index b34fb65813c45e..9b69148128e5bf 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
2a71e01b2cf9usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index d895cf6532a21f..95caad156de58a 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
0b9fcab1b860usb: ulpi: fix memory leak on ulpi_register() error paths
1 file changed · +4 −2
drivers/usb/common/ulpi.c+4 −2 modifieddiff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index b34fb65813c45e..9b69148128e5bf 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -286,12 +286,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi) ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); - if (ret) + if (ret) { + kfree(ulpi); return ret; + } ret = ulpi_read_id(ulpi); if (ret) { of_node_put(ulpi->dev.of_node); + kfree(ulpi); return ret; } -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing kfree(ulpi) on two early error paths in ulpi_register() causes a memory leak when ulpi_of_register() or ulpi_read_id() fail before device_register()."
Attack vector
An attacker does not directly trigger this bug; it is a local memory leak that occurs during USB ULPI device registration when the kernel encounters a failure in `ulpi_of_register()` or `ulpi_read_id()`. No special network path or payload is required — the leak happens automatically during normal device probe if the ULPI OF registration or ID read fails. Repeated probe failures (e.g., by hot-plugging a faulty ULPI device) can exhaust kernel memory over time.
Affected code
The vulnerability is in the `ulpi_register()` function in `drivers/usb/common/ulpi.c` [patch_id=2898642]. The function allocates a `struct ulpi` but fails to free it on two early error paths: when `ulpi_of_register()` fails and when `ulpi_read_id()` fails, both before `device_register()` is called.
What the fix does
The patch adds `kfree(ulpi)` inside the error-handling blocks for both `ulpi_of_register()` and `ulpi_read_id()` failures [patch_id=2898642]. Previously, a prior fix (commit 01af542392b5) had removed `kfree(ulpi)` from `ulpi_register_interface()` to prevent a double-free when `device_register()` fails, but that removal inadvertently caused the allocation to be leaked if an error occurred before `device_register()` was reached. Adding the `kfree()` calls on these two early-return paths ensures the `ulpi` allocation is freed regardless of which step fails.
Preconditions
- inputThe kernel must attempt to register a ULPI device where ulpi_of_register() or ulpi_read_id() fails before device_register() is called.
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/0b9fcab1b8608d429e5f239afb197de928d4de7dnvd
- git.kernel.org/stable/c/2a71e01b2cf9b4329ff67102c1bea7448c2a2d2dnvd
- git.kernel.org/stable/c/b0c0d44adb55c66663886cb6e30ee92cbb0f5385nvd
- git.kernel.org/stable/c/be2c1d825f54277472c87019e82013ac534ddc4cnvd
- git.kernel.org/stable/c/f30ccfc2985590b33a23a3d8bed7ca16c0af551bnvd
News mentions
0No linked articles in our index yet.