A crucial vulnerability has been discovered and resolved in the Linux kernel, specifically in the Qcom endpoint controller's code. The issue stemmed from the incorrect placement of the endpoint cleanup function dw_pcie_ep_cleanup() and the EPF deinit notify function pci_epc_deinit_notify() in the code, which led to crashes in the endpoint SoC (System on Chip) when the host asserted PERST#. This blog post examines the details of the vulnerability, the underlying problem, and the solution that has been implemented to fix it.
The Vulnerability
The Qcom endpoint SoCs under consideration depend on the refclk (reference clock) from the host to keep the controller operational. However, the current implementation of the code calls the dw_pcie_ep_cleanup() and pci_epc_deinit_notify() functions during the execution of qcom_pcie_perst_assert() – when the host has asserted PERST#. Soon after this step, the refclk is disabled by the host, and any access to the hardware registers in the absence of the refclk results in a crash in the endpoint SoC.
Most of the controller cleanups require accessing hardware registers (such as eDMA cleanup performed in dw_pcie_ep_cleanup(), powering down MHI EPF, etc.) So, these cleanup functions end up causing the crash as they are executed when the host asserts PERST# and the refclk is not available.
The following code snippet showcases the problematic functions
int qcom_pcie_perst_assert(...) {
...
dw_pcie_ep_cleanup(...);
pci_epc_deinit_notify(...);
...
}
The Solution
Generating the refclk in the endpoint itself and not depending on the host is one possible solution. However, that is not always feasible since some endpoint designs require the endpoint to consume the refclk from the host.
To address this issue, the controller cleanups have been moved to the beginning of the qcom_pcie_perst_deassert() function. This function is called whenever the host has deasserted PERST#, ensuring that the refclk is active at this point. With the controller cleanup performed after enabling resources, the rest of the PERST# deassert code execution can proceed as usual.
Here's the new code snippet that resolves this vulnerability
int qcom_pcie_perst_deassert(...) {
...
dw_pcie_ep_cleanup(...);
pci_epc_deinit_notify(...);
...
}
Original References
This vulnerability and the subsequent fix have been discussed and documented on the Linux kernel patch mailing list, specifically in the following patches:
- [PATCH v2 /6] arm64: dts: qcom: correct PCIe related DT configuration
(source: https://lore.kernel.org/patchwork/cover/1578748/)
- [PATCH v2 2/6] PCI: qcom-ep: Move controller cleanups to qcom_pcie_perst_deassert()
(source: https://lore.kernel.org/patchwork/patch/1578958/)
Exploit Details
As the vulnerability involves crashing the Qcom endpoint SoC, exploitation could potentially lead to denial of service (DoS) attacks, affecting the stability and availability of the impacted system. However, there have been no reported instances of exploits targeting this issue to date.
Conclusion
The swift resolution of this vulnerability demonstrates the Linux kernel community's commitment to maintaining the security and stability of the Linux ecosystem. The update should be applied as soon as possible on affected systems to mitigate the risk of potential exploits aimed at causing system crashes or denial of service attacks.
Timeline
Published on: 12/24/2024 12:15:23 UTC
Last modified on: 01/20/2025 06:19:56 UTC