A subtle locking change in the Linux kernel’s MHI PCI host driver — tracked as CVE-2025-21951 — patched a deadlock that could cause a full loss of availability during device recovery or system power-management transitions, and operators should treat it as a real operational risk for systems that include MHI-based PCI devices until they install the upstream fix or an equivalent vendor update. (github.com)
The defect appears in the MHI (Modem Host Interface) host PCI “pci_generic” driver path used on platforms that host modems and similar PCI functions. In certain recovery paths the driver could schedule recovery work asynchronously while callers (for example, suspend or shutdown handlers) synchronously waited for that work to finish. When the recovery work attempted a full function reset it used the blocking routine
The upstream remedy is intentionally minimal: replace the call to the blocking reset function with a try variant —
This fix is a textbook example of defensive kernel engineering: a small, well-explained change prevents a subtle locking inversion that would otherwise yield an operationally disruptive deadlock. For administrators, the remediation story is straightforward — inventory for MHI devices and deploy vendor/kernel updates that include the upstream commit — but the operational lesson is broader: availability bugs in low-level drivers can present as surprising lifecycle failures (shutdowns that never complete, suspend/resume regressions), and they demand the same priority as traditional security vulnerabilities.
Source: MSRC Security Update Guide - Microsoft Security Response Center
Background / Overview
The defect appears in the MHI (Modem Host Interface) host PCI “pci_generic” driver path used on platforms that host modems and similar PCI functions. In certain recovery paths the driver could schedule recovery work asynchronously while callers (for example, suspend or shutdown handlers) synchronously waited for that work to finish. When the recovery work attempted a full function reset it used the blocking routine pci_reset_function() — which takes the PCI device lock — and that created a classic lock inversion: the caller held the device lock while waiting for recovery, and the recovery work waited for that same lock while executing pci_reset_function(). The net result could be a deadlock during PM suspend/shutdown (and similar code paths), producing a sustained or persistent loss of availability. (github.com)The upstream remedy is intentionally minimal: replace the call to the blocking reset function with a try variant —
pci_try_reset_function() — that first checks whether the PCI device lock is available. If the lock is free it proceeds; if not it returns -EAGAIN, allowing the recovery path to detect the lock contention and fail gracefully rather than stall forever. This change was accepted upstream and merged into the kernel trees referenced by the standard stable/linus commits. (github.com)What the CVE means in plain terms
- Impact: A local, low-privileged actor (or an interaction that causes the device to die) can trigger code paths that lead to the kernel hanging while attempting device recovery, producing a service or host-level availability outage. The NVD classifies the impact as an availability issue with a CVSS v3.1 base score of 5.5 (Medium).
- Attack surface: This is a local attack vector (CVSS vector AV:L). Exploitation generally requires the ability to invoke or emulate the driver’s recovery/fail paths — for example by provoking a device error or powering down a modem — or to run local code that triggers the sequence. It is not a remotely exploitable, unauthenticated code‑execution bug.
- Availability characteristics: The vulnerability causes deadlock rather than memory corruption or data leakage. A deadlock means the kernel can become non-responsive with respect to the impacted device and potentially block broader system shutdown or power transitions until intervention (reboot or safe recovery) occurs. The vulnerability therefore maps to the worst‑case availability outcome described in the MSRC advisory: total or sustained loss of availability while the attacker continues the triggering action, or persistent condition requiring remediation.
Technical deep dive: where the deadlock happens and why the fix works
The code path and lock inversion
At a high level, the problem follows a repeated pattern seen in kernel device drivers when synchronous lifecycle callbacks (shutdown, suspend) and asynchronous recovery tasks both manipulate hardware and locks:- The PM core or driver calls a lifecycle callback such as
shutdown()orsuspend()while holdingdevice_lock()for the driver/device. Kernel driver core behavior documents that the device lock is taken around these callbacks. When this call is synchronous it expects the driver to finish its work promptly. - Meanwhile, the driver may have previously scheduled an asynchronous
recovery_work(a workqueue job) to run recovery logic if a device error occurred earlier. - The
recovery_workroutine contains a step to reset the PCI function if the device appears dead. Historically, that routine calledpci_reset_function(), a blocking function that will itself attempt to takedevice_lock()before executing the reset sequence. - If the synchronous caller holds
device_lock()and waits forrecovery_workto complete, whilerecovery_workattemptspci_reset_function()(and blocks waiting to acquire that same lock), then the caller and the worker wait on each other — a deadlock. The upstream commit documenting the fix explicitly describes this scenario and cites reproduction on the X1E80100 CRD device. (github.com)
Why pci_try_reset_function() breaks the cycle
pci_try_reset_function() is a non-blocking variant that checks whether the device lock is available before taking it. If the lock is not available, the function returns immediately with an -EAGAIN error instead of waiting. That means the recovery worker will detect the contention and fail with an error rather than block indefinitely. The worker can then log a failure and let the synchronous caller proceed, eliminating the lock inversion deadlock. The upstream change replaces the single call site in mhi_pci_recovery_work() accordingly and updates the error message to include the failure code. (github.com)Evidence, patches and timeline
- The fix was authored and merged by the MHI driver maintainer and is visible in the upstream commit history (commit a321d163… shows the exact change and the updated error handling). The commit message documents the deadlock scenario, includes the reproducer device (X1E80100 CRD), and explains why the
pci_try_reset_function()approach is safer. (github.com) - The issue is tracked by CVE-2025-21951 and appears in standard vulnerability databases and vendor advisories (NVD/OSV) with a medium severity rating and the AV:L/PR:L/AC:L vector profile used in the CVSS calculation.
- Multiple Linux vendors and distributions incorporated the upstream fix and published security advisories or bug updates referencing the change; SUSE’s security update list and several distro trackers show the MHI pci_generic change listed under their kernel fixes. Debian and the security-tracker team added the CVE to stable kernel updates referencing the upstream commit and stable kernels that include it. These vendor entries are the authoritative route for operators to obtain patched kernel packages for their distributions.
Affected code and likely exposed systems
- The vulnerable code sits in drivers/bus/mhi/host/pci_generic.c. Systems that load that driver and have MHI-based modems or PCI functions are the ones to worry about.
- The upstream change notes the problem was observed on an X1E80100 CRD device, but the commit explicitly warns the deadlock pattern can occur in multiple PM contexts (shutdown, suspend, runtime PM, etc.), so any platform using the mhi/pci_generic driver that triggers asynchronous recovery while holding device locks could be affected. This includes embedded platforms, laptops with cellular modems, and some SoC platforms that use MHI for modem control. (github.com)
- Because MHI is not universally present on every Linux host, the practical footprint is narrower than general PCI bugs, but for affected hosts the operational impact can be severe — blocking shutdowns, preventing suspend/resume, or triggering host hangs until a reboot.
Exploitability, public proofs and practical risk
- Public reporting and vulnerability trackers show no widely available proof-of-concept or public exploit code at the time of advisories; the practical exploitation path tends to require local access or triggering device death in a controlled way. Multiple vulnerability catalogs note a low EPSS/exploitability signal but still assign a medium overall severity due to the availability outcome. Administrators should therefore prioritize patching based on exposure and operational risk rather than panic.
- The CVSS vector (AV:L/PR:L/UI:N/S:U/C:N/I:N/A:H) reflects that the vulnerability does not expose confidentiality or integrity risks directly — it is an availability issue — and its exploit requires a local actor or a component that can cause device failures. That said, a non-malicious device fault in the field that triggers asynchronous recovery during shutdown can reproduce the same deadlock, making this both a security and a reliability fix.
- Because
pci_try_reset_function()returns-EAGAINwhen the lock is unavailable, the recovery worker will fail rather than block; operators should expect to see additional log noise related to “Recovery failed: <err>” messages post‑fix if a device was failing in a way that previously produced a hang. Those messages are a useful diagnostic signal that the kernel chose a safe fail path instead of deadlocking. (github.com)
Concrete mitigation and remediation steps (practical checklist)
If you run Linux hosts that may include MHI PCI devices, follow this prioritized checklist.- Identify potentially affected systems
- Check whether your kernel contains
drivers/bus/mhi/host/pci_generic.cand whether the module is loaded. On many distributions you can run: lsmod | grep mhi or check dmesg for mhi-related messages. - Inventory hardware: look for modem/WWAN devices or SoC vendor modules that rely on MHI.
- Apply vendor updates (preferred)
- Update the kernel to a vendor-supplied package that includes the upstream commit (the stable commit listed in the upstream tree is a321d163… or later). Use your distribution’s security advisories or package update channels (SUSE, Debian, Red Hat / EL vendors, Canonical) to get the correct package. SUSE and Debian trackers have entries showing the fix is backported into their kernel builds. (github.com)
- If you cannot patch immediately, consider temporary mitigations
- If MHI functionality is not required, temporarily blacklisting the MHI PCI host driver will prevent the code path from being present. This is a blunt instrument: it removes MHI modems/modules and may break cellular connectivity. Use a blacklist only after confirming the functional impact.
- For hosts in controlled environments, prefer kernel live-patching solutions from vendors (Ksplice, Canonical Livepatch, SUSE Live Patching, or vendor kernel livepatches) that may carry this fix without a full reboot. Confirm with your vendor whether livepatches cover the mhi tree.
- Monitor for signs of the problem or the fix
- After applying the patch, watch dmesg and system logs for “Recovery failed” messages (the upstream commit updated the error text to include the error code). These are an indication the new non-blocking reset path is engaged instead of deadlocking. (github.com)
- Test suspend/shutdown workflows
- In virtualization or fleet environments, validate shutdown and suspend behavior after applying the kernel update on representative hardware. Because the bug affects power-management transitions, a simple lifecycle test on affected hardware can confirm remediation.
- Coordinate with hardware vendors
- If your hardware vendor supplies custom kernels (OEM or embedded Linux vendors), rely on their kernel patch channels. OEM kernel trees that carry additional backports may require separate vendor updates and shipping schedules.
What operators should not assume
- Do not assume this is a remotely exploitable RCE or data‑exfiltration bug. It is an availability (deadlock) issue and requires local code or local conditions that provoke the MHI driver recovery code paths. Treat it as a reliability/availability fix first and a security patch second.
- Do not assume every Linux host is affected. Only systems that load the MHI host driver (or include MHI-based PCI devices) are implicated. Inventory first, patch second.
- Do not assume the lack of a published PoC means the bug is low-priority. The bug’s characteristics — being reachable during shutdown/suspend — mean production impact can be high even without an attacker, so prioritize remediation according to the criticality of the affected endpoints.
Operational risk analysis — strengths of the upstream fix and remaining concerns
Strengths
- The patch is narrowly focused and small (a three-line functional change in the recovery path) and was accepted upstream after peer review and testing. The minimal surface reduction is a strong point: the patch addresses the root cause (lock inversion) rather than attempting a large refactor. (github.com)
- Vendors and major distributions incorporated the fix quickly into their kernel update streams and security advisories, making standard package updates the straightforward remediation path for most operators.
- The fix improves robustness in multiple PM contexts (runtime resume, suspend, shutdown) by breaking a recurring class of deadlock and making recovery behavior deterministic when the device lock is unavailable. (github.com)
Remaining concerns and caveats
- The patch returns an error (
-EAGAIN) and causes the recovery path to fail rather than to succeed. That is safer from a deadlock perspective, but it means that some devices that previously might have been successfully recovered (if the race timing favored the worker) will now fail and require manual attention or a reboot. Expect and plan for this change in operational behavior. - Blacklisting the driver as a mitigation can be disruptive for endpoints that depend on cellular/WWAN modems. Any temporary mitigation must be weighed against the service loss it causes.
- Embedded vendors or downstream kernel forks that do not follow the mainline tree may lag in applying the fix; operators with vendor-provided kernels must verify the presence of the upstream commit in their shipped kernel or ask the vendor for a backport. Distribution trackers and security advisories remain the authoritative source for when a given host receives the fix.
Practical incident response steps if you see a hang
- If a host fails to complete shutdown or suspend, and you observe MHI or PCI function reset logs, avoid forcing further driver interaction that could make recovery worse. Capture logs (journalctl/dmesg) and identify whether
mhiandpci_genericappear in the log stream. - If possible, perform a clean reboot via the out-of-band management interface (IPMI, iDRAC, iLO) instead of physically power-cycling the machine; clean reboots preserve logs and help with forensic analysis.
- After reboot, check kernel version and confirm the presence of the upstream commit (search for the commit SHA in
uname -a+ distribution changelog or vendor advisory). If the host remains on an unpatched kernel, schedule immediate remediation for fleet members. (github.com) - If the device involved is critical (cellular, embedded modem), engage hardware vendor support to check whether a hardware-specific workaround exists.
Final recommendations
- Treat CVE-2025-21951 as an availability-first vulnerability that warrants rapid remediation on systems that use the MHI PCI host driver or host MHI-based devices.
- The fastest, safest path is to install a vendor-supplied kernel update that contains the upstream commit (a321d163… or later) or one of the vendor backports listed in their advisories. Use distribution security repositories rather than manually patching kernels, unless you have a controlled, tested kernel build and rollback plan. (github.com)
- Where updating is temporarily impossible, apply conservative mitigations (driver blacklisting, livepatch if available) only after confirming the functional impact, and prioritize hosts that perform frequent suspend/resume or are exposed to local users who might trigger the recovery paths.
- Finally, monitor system logs for the new, explicit “Recovery failed: <err>” messages introduced by the patch. Those messages are a diagnostic indicator that the non-blocking reset path is in use and that a previous silent deadlock condition has been replaced by a safe failure mode — the preferable outcome for predictable operations. (github.com)
This fix is a textbook example of defensive kernel engineering: a small, well-explained change prevents a subtle locking inversion that would otherwise yield an operationally disruptive deadlock. For administrators, the remediation story is straightforward — inventory for MHI devices and deploy vendor/kernel updates that include the upstream commit — but the operational lesson is broader: availability bugs in low-level drivers can present as surprising lifecycle failures (shutdowns that never complete, suspend/resume regressions), and they demand the same priority as traditional security vulnerabilities.
Source: MSRC Security Update Guide - Microsoft Security Response Center