CVE-2024-49878
Publication date:
21/10/2024
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
resource: fix region_intersects() vs add_memory_driver_managed()<br />
<br />
On a system with CXL memory, the resource tree (/proc/iomem) related to<br />
CXL memory may look like something as follows.<br />
<br />
490000000-50fffffff : CXL Window 0<br />
490000000-50fffffff : region0<br />
490000000-50fffffff : dax0.0<br />
490000000-50fffffff : System RAM (kmem)<br />
<br />
Because drivers/dax/kmem.c calls add_memory_driver_managed() during<br />
onlining CXL memory, which makes "System RAM (kmem)" a descendant of "CXL<br />
Window X". This confuses region_intersects(), which expects all "System<br />
RAM" resources to be at the top level of iomem_resource. This can lead to<br />
bugs.<br />
<br />
For example, when the following command line is executed to write some<br />
memory in CXL memory range via /dev/mem,<br />
<br />
$ dd if=data of=/dev/mem bs=$((1 10)) count=1<br />
dd: error writing &#39;/dev/mem&#39;: Bad address<br />
1+0 records in<br />
0+0 records out<br />
0 bytes copied, 0.0283507 s, 0.0 kB/s<br />
<br />
the command fails as expected. However, the error code is wrong. It<br />
should be "Operation not permitted" instead of "Bad address". More<br />
seriously, the /dev/mem permission checking in devmem_is_allowed() passes<br />
incorrectly. Although the accessing is prevented later because ioremap()<br />
isn&#39;t allowed to map system RAM, it is a potential security issue. During<br />
command executing, the following warning is reported in the kernel log for<br />
calling ioremap() on system RAM.<br />
<br />
ioremap on RAM at 0x0000000490000000 - 0x0000000490000fff<br />
WARNING: CPU: 2 PID: 416 at arch/x86/mm/ioremap.c:216 __ioremap_caller.constprop.0+0x131/0x35d<br />
Call Trace:<br />
memremap+0xcb/0x184<br />
xlate_dev_mem_ptr+0x25/0x2f<br />
write_mem+0x94/0xfb<br />
vfs_write+0x128/0x26d<br />
ksys_write+0xac/0xfe<br />
do_syscall_64+0x9a/0xfd<br />
entry_SYSCALL_64_after_hwframe+0x4b/0x53<br />
<br />
The details of command execution process are as follows. In the above<br />
resource tree, "System RAM" is a descendant of "CXL Window 0" instead of a<br />
top level resource. So, region_intersects() will report no System RAM<br />
resources in the CXL memory region incorrectly, because it only checks the<br />
top level resources. Consequently, devmem_is_allowed() will return 1<br />
(allow access via /dev/mem) for CXL memory region incorrectly. <br />
Fortunately, ioremap() doesn&#39;t allow to map System RAM and reject the<br />
access.<br />
<br />
So, region_intersects() needs to be fixed to work correctly with the<br />
resource tree with "System RAM" not at top level as above. To fix it, if<br />
we found a unmatched resource in the top level, we will continue to search<br />
matched resources in its descendant resources. So, we will not miss any<br />
matched resources in resource tree anymore.<br />
<br />
In the new implementation, an example resource tree<br />
<br />
|------------- "CXL Window 0" ------------|<br />
|-- "System RAM" --|<br />
<br />
will behave similar as the following fake resource tree for<br />
region_intersects(, IORESOURCE_SYSTEM_RAM, ),<br />
<br />
|-- "System RAM" --||-- "CXL Window 0a" --|<br />
<br />
Where "CXL Window 0a" is part of the original "CXL Window 0" that<br />
isn&#39;t covered by "System RAM".
Severity CVSS v4.0: Pending analysis
Last modification:
03/11/2025