Davidlohr Bueso
2018-09-18 14:54:57 UTC
Hi,
A potential local priviledge escalation bug was reported in the vmacache code dealing with 32-bit sequence number overflows, introduced in v3.16 by 6b4ebc3a9078 (mm,vmacache: optimize overflow system-wide flushing). The change introduces a "fastpath" which skips the invalidation on overflows for single threads (mm_users == 1), which can lead to a use-after-free. As reported:
`
[A starts as a singlethreaded process]
A: create mappings X and Y (in separate memory areas far away from other allocations)
A: perform repeated invalidations until current->mm->vmacache_seqnum==0xffffffff and current->vmacache.seqnum==0xfffffffe
A: dereference an address in mapping Y that is not paged in (thereby populating A's VMA cache with Y at seqnum 0xffffffff)
A: unmap mapping X (thereby bumping current->mm->vmacache_seqnum to 0)
A: without any more find_vma() calls (which could happen e.g. via pagefaults), create a thread B
B: perform repeated invalidations until current->mm->vmacache_seqnum==0xfffffffe
B: unmap mapping Y (thereby bumping current->mm->vmacache_seqnum to 0xffffffff)
A: dereference an address in the freed mapping Y (or any address that isn't present in the pagetables and doesn't correspond to a valid VMA cache entry)
This is fixed in 7a9cdebdcc17 (mm: get rid of vmacache_flush_all() entirely), by converting it to a 64-bit counter and not dealing with overflows anymore; which also makes the code simpler and removes rarely-run code in core kernel paths.
So a win-win altogether.
Thanks,
Davidlohr
A potential local priviledge escalation bug was reported in the vmacache code dealing with 32-bit sequence number overflows, introduced in v3.16 by 6b4ebc3a9078 (mm,vmacache: optimize overflow system-wide flushing). The change introduces a "fastpath" which skips the invalidation on overflows for single threads (mm_users == 1), which can lead to a use-after-free. As reported:
`
[A starts as a singlethreaded process]
A: create mappings X and Y (in separate memory areas far away from other allocations)
A: perform repeated invalidations until current->mm->vmacache_seqnum==0xffffffff and current->vmacache.seqnum==0xfffffffe
A: dereference an address in mapping Y that is not paged in (thereby populating A's VMA cache with Y at seqnum 0xffffffff)
A: unmap mapping X (thereby bumping current->mm->vmacache_seqnum to 0)
A: without any more find_vma() calls (which could happen e.g. via pagefaults), create a thread B
B: perform repeated invalidations until current->mm->vmacache_seqnum==0xfffffffe
B: unmap mapping Y (thereby bumping current->mm->vmacache_seqnum to 0xffffffff)
A: dereference an address in the freed mapping Y (or any address that isn't present in the pagetables and doesn't correspond to a valid VMA cache entry)
This is fixed in 7a9cdebdcc17 (mm: get rid of vmacache_flush_all() entirely), by converting it to a 64-bit counter and not dealing with overflows anymore; which also makes the code simpler and removes rarely-run code in core kernel paths.
So a win-win altogether.
Thanks,
Davidlohr