Skip to content

Commit 9480c53

Browse files
jsgftorvalds
authored andcommitted
mm: rearrange exit_mmap() to unlock before arch_exit_mmap
Christophe Saout reported [in precursor to: http://marc.info/?l=linux-kernel&m=123209902707347&w=4]: > Note that I also some a different issue with CONFIG_UNEVICTABLE_LRU. > Seems like Xen tears down current->mm early on process termination, so > that __get_user_pages in exit_mmap causes nasty messages when the > process had any mlocked pages. (in fact, it somehow manages to get into > the swapping code and produces a null pointer dereference trying to get > a swap token) Jeremy explained: Yes. In the normal case under Xen, an in-use pagetable is "pinned", meaning that it is RO to the kernel, and all updates must go via hypercall (or writes are trapped and emulated, which is much the same thing). An unpinned pagetable is not currently in use by any process, and can be directly accessed as normal RW pages. As an optimisation at process exit time, we unpin the pagetable as early as possible (switching the process to init_mm), so that all the normal pagetable teardown can happen with direct memory accesses. This happens in exit_mmap() -> arch_exit_mmap(). The munlocking happens a few lines below. The obvious thing to do would be to move arch_exit_mmap() to below the munlock code, but I think we'd want to call it even if mm->mmap is NULL, just to be on the safe side. Thus, this patch: exit_mmap() needs to unlock any locked vmas before calling arch_exit_mmap, as the latter may switch the current mm to init_mm, which would cause the former to fail. Signed-off-by: Jeremy Fitzhardinge <[email protected]> Signed-off-by: Lee Schermerhorn <[email protected]> Cc: Christophe Saout <[email protected]> Cc: Keir Fraser <[email protected]> Cc: Christophe Saout <[email protected]> Cc: Alex Williamson <[email protected]> Cc: <[email protected]> [2.6.28.x] Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 3abdbf9 commit 9480c53

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

mm/mmap.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,12 +2084,8 @@ void exit_mmap(struct mm_struct *mm)
20842084
unsigned long end;
20852085

20862086
/* mm's last user has gone, and its about to be pulled down */
2087-
arch_exit_mmap(mm);
20882087
mmu_notifier_release(mm);
20892088

2090-
if (!mm->mmap) /* Can happen if dup_mmap() received an OOM */
2091-
return;
2092-
20932089
if (mm->locked_vm) {
20942090
vma = mm->mmap;
20952091
while (vma) {
@@ -2098,7 +2094,13 @@ void exit_mmap(struct mm_struct *mm)
20982094
vma = vma->vm_next;
20992095
}
21002096
}
2097+
2098+
arch_exit_mmap(mm);
2099+
21012100
vma = mm->mmap;
2101+
if (!vma) /* Can happen if dup_mmap() received an OOM */
2102+
return;
2103+
21022104
lru_add_drain();
21032105
flush_cache_mm(mm);
21042106
tlb = tlb_gather_mmu(mm, 1);

0 commit comments

Comments
 (0)