VYPR
Unrated severityNVD Advisory· Published May 28, 2026

CVE-2026-46109

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

1

Patches

10
be2c1d825f54

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
b0c0d44adb55

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
2a71e01b2cf9

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
0b9fcab1b860

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
f30ccfc29855

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
b0c0d44adb55

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
be2c1d825f54

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
f30ccfc29855

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
2a71e01b2cf9

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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
    
    
    
0b9fcab1b860

usb: ulpi: fix memory leak on ulpi_register() error paths

1 file changed · +4 2
  • drivers/usb/common/ulpi.c+4 2 modified
    diff --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

News mentions

0

No linked articles in our index yet.