CVE-2026-45926
Description
In the Linux kernel, the following vulnerability has been resolved:
rust: pwm: Fix potential memory leak on init error
When initializing a PWM chip using pwmchip_alloc(), the allocated device owns an initial reference that must be released on all error paths.
If __pinned_init() were to fail, the allocated pwm_chip would currently leak because the error path returns without calling pwmchip_put().
Affected products
1Patches
4a2633dc243c3rust: pwm: Fix potential memory leak on init error
1 file changed · +5 −2
rust/kernel/pwm.rs+5 −2 modifieddiff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs index 2dd72a39acb5d0..4f683158fc0816 100644 --- a/rust/kernel/pwm.rs +++ b/rust/kernel/pwm.rs @@ -607,7 +607,11 @@ impl<T: PwmOps> Chip<T> { let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) }; // SAFETY: We construct the `T` object in-place in the allocated private memory. - unsafe { data.__pinned_init(drvdata_ptr.cast())? }; + unsafe { data.__pinned_init(drvdata_ptr.cast()) }.inspect_err(|_| { + // SAFETY: It is safe to call `pwmchip_put()` with a valid pointer obtained + // from `pwmchip_alloc()`. We will not use pointer after this. + unsafe { bindings::pwmchip_put(c_chip_ptr) } + })?; // SAFETY: `c_chip_ptr` points to a valid chip. unsafe { -- cgit 1.3-korg
baa8b7097d9crust: pwm: Fix potential memory leak on init error
1 file changed · +5 −2
rust/kernel/pwm.rs+5 −2 modifieddiff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs index cb00f8a8765c8e..2ba9cfd02bfdbe 100644 --- a/rust/kernel/pwm.rs +++ b/rust/kernel/pwm.rs @@ -601,7 +601,11 @@ impl<T: PwmOps> Chip<T> { let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) }; // SAFETY: We construct the `T` object in-place in the allocated private memory. - unsafe { data.__pinned_init(drvdata_ptr.cast())? }; + unsafe { data.__pinned_init(drvdata_ptr.cast()) }.inspect_err(|_| { + // SAFETY: It is safe to call `pwmchip_put()` with a valid pointer obtained + // from `pwmchip_alloc()`. We will not use pointer after this. + unsafe { bindings::pwmchip_put(c_chip_ptr) } + })?; // SAFETY: `c_chip_ptr` points to a valid chip. unsafe { -- cgit 1.3-korg
baa8b7097d9crust: pwm: Fix potential memory leak on init error
1 file changed · +5 −2
rust/kernel/pwm.rs+5 −2 modifieddiff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs index cb00f8a8765c8e..2ba9cfd02bfdbe 100644 --- a/rust/kernel/pwm.rs +++ b/rust/kernel/pwm.rs @@ -601,7 +601,11 @@ impl<T: PwmOps> Chip<T> { let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) }; // SAFETY: We construct the `T` object in-place in the allocated private memory. - unsafe { data.__pinned_init(drvdata_ptr.cast())? }; + unsafe { data.__pinned_init(drvdata_ptr.cast()) }.inspect_err(|_| { + // SAFETY: It is safe to call `pwmchip_put()` with a valid pointer obtained + // from `pwmchip_alloc()`. We will not use pointer after this. + unsafe { bindings::pwmchip_put(c_chip_ptr) } + })?; // SAFETY: `c_chip_ptr` points to a valid chip. unsafe { -- cgit 1.3-korg
a2633dc243c3rust: pwm: Fix potential memory leak on init error
1 file changed · +5 −2
rust/kernel/pwm.rs+5 −2 modifieddiff --git a/rust/kernel/pwm.rs b/rust/kernel/pwm.rs index 2dd72a39acb5d0..4f683158fc0816 100644 --- a/rust/kernel/pwm.rs +++ b/rust/kernel/pwm.rs @@ -607,7 +607,11 @@ impl<T: PwmOps> Chip<T> { let drvdata_ptr = unsafe { bindings::pwmchip_get_drvdata(c_chip_ptr) }; // SAFETY: We construct the `T` object in-place in the allocated private memory. - unsafe { data.__pinned_init(drvdata_ptr.cast())? }; + unsafe { data.__pinned_init(drvdata_ptr.cast()) }.inspect_err(|_| { + // SAFETY: It is safe to call `pwmchip_put()` with a valid pointer obtained + // from `pwmchip_alloc()`. We will not use pointer after this. + unsafe { bindings::pwmchip_put(c_chip_ptr) } + })?; // SAFETY: `c_chip_ptr` points to a valid chip. unsafe { -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing reference release on error path: when `__pinned_init()` fails, the initial reference obtained by `pwmchip_alloc()` is not released via `pwmchip_put()`, causing a memory leak."
Attack vector
An attacker would need to trigger a failure of the `__pinned_init()` call during PWM chip initialization in the Rust PWM subsystem. This could occur if the in-place construction of the `T` object (the driver's private data) fails, for example due to memory pressure or an invalid configuration. The bug is in the `Chip::<T>::new()` path in `rust/kernel/pwm.rs` [patch_id=2661267]. No special privileges or network access are required beyond the ability to load or probe a Rust-based PWM driver that uses this initialization path.
Affected code
The vulnerable code is in `rust/kernel/pwm.rs` in the `Chip::<T>` implementation, specifically the `new()` function that calls `pwmchip_alloc()` and then `data.__pinned_init()` [patch_id=2661267]. The error path after `__pinned_init()` failure was missing a `pwmchip_put()` call.
What the fix does
The patch wraps the `__pinned_init()` call with `.inspect_err(|_| { unsafe { bindings::pwmchip_put(c_chip_ptr) } })` [patch_id=2661267]. This ensures that if `__pinned_init()` returns an error, the initial reference obtained from `pwmchip_alloc()` is released before the error is propagated. The fix is minimal and follows the kernel's existing reference-counting discipline for `pwm_chip` objects.
Preconditions
- configA Rust-based PWM driver must be loaded that uses the `Chip::::new()` initialization path in `rust/kernel/pwm.rs`.
- inputThe `__pinned_init()` call must fail (e.g., due to memory allocation failure or invalid driver data).
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.