CVE-2024-40979

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
12/07/2024
Last modified:
17/09/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> wifi: ath12k: fix kernel crash during resume<br /> <br /> Currently during resume, QMI target memory is not properly handled, resulting<br /> in kernel crash in case DMA remap is not supported:<br /> <br /> BUG: Bad page state in process kworker/u16:54 pfn:36e80<br /> page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x36e80<br /> page dumped because: nonzero _refcount<br /> Call Trace:<br /> bad_page<br /> free_page_is_bad_report<br /> __free_pages_ok<br /> __free_pages<br /> dma_direct_free<br /> dma_free_attrs<br /> ath12k_qmi_free_target_mem_chunk<br /> ath12k_qmi_msg_mem_request_cb<br /> <br /> The reason is:<br /> Once ath12k module is loaded, firmware sends memory request to host. In case<br /> DMA remap not supported, ath12k refuses the first request due to failure in<br /> allocating with large segment size:<br /> <br /> ath12k_pci 0000:04:00.0: qmi firmware request memory request<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 7077888<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 8454144<br /> ath12k_pci 0000:04:00.0: qmi dma allocation failed (7077888 B type 1), will try later with small size<br /> ath12k_pci 0000:04:00.0: qmi delays mem_request 2<br /> ath12k_pci 0000:04:00.0: qmi firmware request memory request<br /> <br /> Later firmware comes back with more but small segments and allocation<br /> succeeds:<br /> <br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 262144<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 524288<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 4 size 65536<br /> ath12k_pci 0000:04:00.0: qmi mem seg type 1 size 524288<br /> <br /> Now ath12k is working. If suspend is triggered, firmware will be reloaded<br /> during resume. As same as before, firmware requests two large segments at<br /> first. In ath12k_qmi_msg_mem_request_cb() segment count and size are<br /> assigned:<br /> <br /> ab-&gt;qmi.mem_seg_count == 2<br /> ab-&gt;qmi.target_mem[0].size == 7077888<br /> ab-&gt;qmi.target_mem[1].size == 8454144<br /> <br /> Then allocation failed like before and ath12k_qmi_free_target_mem_chunk()<br /> is called to free all allocated segments. Note the first segment is skipped<br /> because its v.addr is cleared due to allocation failure:<br /> <br /> chunk-&gt;v.addr = dma_alloc_coherent()<br /> <br /> Also note that this leaks that segment because it has not been freed.<br /> <br /> While freeing the second segment, a size of 8454144 is passed to<br /> dma_free_coherent(). However remember that this segment is allocated at<br /> the first time firmware is loaded, before suspend. So its real size is<br /> 524288, much smaller than 8454144. As a result kernel found we are freeing<br /> some memory which is in use and thus cras<br /> ---truncated---

Vulnerable products and versions

CPE From Up to
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* 6.3 (including) 6.9.7 (excluding)