CVE-2024-40979
Publication date:
12/07/2024
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->qmi.mem_seg_count == 2<br />
ab->qmi.target_mem[0].size == 7077888<br />
ab->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->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---
Severity CVSS v4.0: Pending analysis
Last modification:
17/09/2025