Exploitation of a fairly constrained UAF Primitive in the Linux Kernel [CVE-2022-42703]
A post on exploiting a bug that Jann Horn discovered in the linux kernel’s memory management (MM) subsystem. The bug isn’t detailed in this post and is fairly complex (there is a project zero bug report but it’s difficult to understand without deep knowledge of MM internals), though they state it will be written up in a future blogpost. What’s important to takeaway from the bug is that it essentially gets two VMAs merged with different secondary anon_vma
, and subsequently have some mapped pages with a dangling page->mapping
pointer (or folio->mapping
on later kernel versions). This UAF can be triggered by calling madvise()
on the affected page, which eventually calls folio_lock_anon_vma_read()
.
Restricted write
Looking at folio_lock_anon_vma_read()
, they found there was a down_read_trylock()
call that would take a pointer to a reader writer semaphore that came from the UAF’d object. This gave them a restricted write primitive, which would increment a uint64 by 0x100 assuming the most significant bit and the 3 least significant bits weren’t set. This effectively prevents this write from being able to corrupt kernel pointers or anything that isn’t aligned to an 8-byte boundary. KASLR is also a factor, and so this seems like a tricky exploit scenario. Fortunately, it’s possible to take advantage of the fact that there’s non-randomized CPU entry area stacks to store register context (Interrupt Stack Tables / ISTs). By triggering an exception (such as #DB
) in a copy_to/from_user()
, the register context could get dumped to this stack on interrupt and be restored when the thread resumes.
Getting stack OOB read/write + code exec
By intentionally triggering an exception on a copy_to_user()
from a stack address, they could then use the restricted write primitive to increment the register containing the length of the copy to get an out-of-bounds read and leak stack data (including the stack cookie and pointers to defeat kASLR). Conversely, by doing the same on a copy_from_user()
call to a stack address, they could smash the return pointer to get code execution, while maintaining the cookie value they leaked earlier.