CVE-2025-22090
Publication date:
16/04/2025
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
x86/mm/pat: Fix VM_PAT handling when fork() fails in copy_page_range()<br />
<br />
If track_pfn_copy() fails, we already added the dst VMA to the maple<br />
tree. As fork() fails, we&#39;ll cleanup the maple tree, and stumble over<br />
the dst VMA for which we neither performed any reservation nor copied<br />
any page tables.<br />
<br />
Consequently untrack_pfn() will see VM_PAT and try obtaining the<br />
PAT information from the page table -- which fails because the page<br />
table was not copied.<br />
<br />
The easiest fix would be to simply clear the VM_PAT flag of the dst VMA<br />
if track_pfn_copy() fails. However, the whole thing is about "simply"<br />
clearing the VM_PAT flag is shaky as well: if we passed track_pfn_copy()<br />
and performed a reservation, but copying the page tables fails, we&#39;ll<br />
simply clear the VM_PAT flag, not properly undoing the reservation ...<br />
which is also wrong.<br />
<br />
So let&#39;s fix it properly: set the VM_PAT flag only if the reservation<br />
succeeded (leaving it clear initially), and undo the reservation if<br />
anything goes wrong while copying the page tables: clearing the VM_PAT<br />
flag after undoing the reservation.<br />
<br />
Note that any copied page table entries will get zapped when the VMA will<br />
get removed later, after copy_page_range() succeeded; as VM_PAT is not set<br />
then, we won&#39;t try cleaning VM_PAT up once more and untrack_pfn() will be<br />
happy. Note that leaving these page tables in place without a reservation<br />
is not a problem, as we are aborting fork(); this process will never run.<br />
<br />
A reproducer can trigger this usually at the first try:<br />
<br />
https://gitlab.com/davidhildenbrand/scratchspace/-/raw/main/reproducers/pat_fork.c<br />
<br />
WARNING: CPU: 26 PID: 11650 at arch/x86/mm/pat/memtype.c:983 get_pat_info+0xf6/0x110<br />
Modules linked in: ...<br />
CPU: 26 UID: 0 PID: 11650 Comm: repro3 Not tainted 6.12.0-rc5+ #92<br />
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014<br />
RIP: 0010:get_pat_info+0xf6/0x110<br />
...<br />
Call Trace:<br />
<br />
...<br />
untrack_pfn+0x52/0x110<br />
unmap_single_vma+0xa6/0xe0<br />
unmap_vmas+0x105/0x1f0<br />
exit_mmap+0xf6/0x460<br />
__mmput+0x4b/0x120<br />
copy_process+0x1bf6/0x2aa0<br />
kernel_clone+0xab/0x440<br />
__do_sys_clone+0x66/0x90<br />
do_syscall_64+0x95/0x180<br />
<br />
Likely this case was missed in:<br />
<br />
d155df53f310 ("x86/mm/pat: clear VM_PAT if copy_p4d_range failed")<br />
<br />
... and instead of undoing the reservation we simply cleared the VM_PAT flag.<br />
<br />
Keep the documentation of these functions in include/linux/pgtable.h,<br />
one place is more than sufficient -- we should clean that up for the other<br />
functions like track_pfn_remap/untrack_pfn separately.
Severity CVSS v4.0: Pending analysis
Last modification:
17/04/2025