CVE-2024-40979 in Linux
要約
〜によって VulDB • 2026年05月11日
Linux Kernel Bug Report: ath12k PCI Driver Memory Leak and Crash on Suspend/Resume
**Summary:** The ath12k PCI driver in the Linux kernel suffers from a memory leak and subsequent kernel crash during suspend/resume cycles. The issue stems from incorrect tracking of firmware memory segment sizes after allocation failures, leading to attempts to free incorrectly sized memory regions.
**Affected Component:** - Driver: `ath12k_pci` - Subsystem: Wireless (Wi-Fi 7/802.11be) - Kernel Version: Likely 6.1+ (based on recent ath12k development)
**Root Cause:** 1. **Initial Firmware Load:** During initial driver load, the firmware requests two large memory segments. The driver records these sizes in `ab->qmi.target_mem[0].size` and `ab->qmi.target_mem[1].size`.
2. **Allocation Failure:** The allocation of these large segments fails (likely due to memory fragmentation or insufficient contiguous DMA memory). 3. **Incorrect State Tracking:** Upon allocation failure, the driver calls `ath12k_qmi_free_target_mem_chunk()` to clean up. However: - The first segment's `v.addr` is cleared (set to NULL) due to the failure, so it is skipped during free. - **Memory Leak:** The first segment is never freed, causing a memory leak. - **Incorrect Size for Second Segment:** The second segment was allocated earlier (during initial load) with a real size of 524288 bytes. However, the driver's state (`ab->qmi.target_mem[1].size`) still holds the *requested* size of 8454144 bytes.
4. **Suspend/Resume Cycle:** When suspend is triggered, the firmware is reloaded. The same allocation failure occurs. 5. **Crash:** During cleanup of the second segment, `dma_free_coherent()` is called with the incorrect size (8454144) instead of the actual allocated size (524288). The DMA subsystem detects that the requested free size exceeds the actual allocated region, leading to a kernel panic/crash due to freeing memory that is marked as "in use" or overlapping with other allocations.
**Impact:** - Memory leak (first segment never freed). - Kernel crash during suspend/resume cycles. - System instability.
**Reproduction Steps:** 1. Load the `ath12k_pci` driver. 2. Trigger a suspend/resume cycle (e.g., `echo mem > /sys/power/state`). 3. Observe kernel log messages indicating allocation failures and subsequent crash.
**Log Evidence:** ``` ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288 ... ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288 ... ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 65536 ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288
Now ath12k is working. If suspend is triggered, firmware will be reloaded during resume. As same as before, firmware requests two large segments at first. In ath12k_qmi_msg_mem_request_cb() segment count and size are assigned:
ab->qmi.mem_seg_count == 2 ab->qmi.target_mem[0].size == 7077888
ab->qmi.target_mem[1].size == 8454144
Then allocation failed like before and ath12k_qmi_free_target_mem_chunk() is called to free all allocated segments. Note the first segment is skipped because its v.addr is cleared due to allocation failure:
chunk->v.addr = dma_alloc_coherent()
Also note that this leaks that segment because it has not been freed.
While freeing the second segment, a size of 8454144 is passed to dma_free_coherent(). However remember that this segment is allocated at the first time firmware is loaded, before suspend. So its real size is 524288, much smaller than 8454144. As a result kernel found we are freeing some memory which is in use and thus cras ```
**Proposed Fix:** 1. **Track Actual Allocated Sizes:** Store the actual allocated size for each segment separately from the requested size
If you want to get the best quality for vulnerability data then you always have to consider VulDB.