freenode
Kernel & Low-Level

PAGEMAP_SCAN fix pins mm to stop unprivileged UAF

A missing mm_users hold let concurrent exit free a hugetlb VMA lock under a live page-table walk.

A use-after-free in the Linux kernel's PAGEMAP_SCAN ioctl left unprivileged callers able to race a page-table walk against process exit, including on systems with no huge pages configured.

The ioctl obtains an mm from /proc//pagemap and takes only the mmap read lock. Unlike the other pagemap and smaps paths in the same code, it never took an mm_users reference. That left exit_mmap free to run unmap work under the same read lock. For ordinary VMAs the later write-locked teardown is safe; shared hugetlb VMAs free their private lock during the read-locked phase. A concurrent walker can therefore load that lock pointer and down_read a semaphore that has already been freed.

Ngoc Quy's fix takes mmget_not_zero for the duration of the scan, matching the pattern used by the neighboring consumers, so the exiting task cannot reach exit_mmap while the walk is still in progress. Andrew Morton said the change checks out, while questioning a new defensive NULL mm test that would turn a cant-happen into a quiet -ESRCH instead of an oops.