Patch from Hugh Dickins <hugh@veritas.com>

Hugh's patch fixes vm_area_struct slab corruption due to mremap's move_vma
mistaking how do_munmap splits vmas in one case.

Neither of us are very happy with it - it is fragile, and obscure.  Hugh will
revisit this later, but for now it should fix up the potential memory
corruption.


 mm/mmap.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff -puN mm/mmap.c~vm_area-use-after-free-fix mm/mmap.c
--- 25/mm/mmap.c~vm_area-use-after-free-fix	2003-03-07 12:01:03.000000000 -0800
+++ 25-akpm/mm/mmap.c	2003-03-07 12:01:03.000000000 -0800
@@ -1259,20 +1259,24 @@ int do_munmap(struct mm_struct *mm, unsi
  
 	/*
 	 * If we need to split any vma, do it now to save pain later.
+	 *
+	 * Note: mremap's move_vma VM_ACCOUNT handling assumes a partially
+	 * unmapped vm_area_struct will remain in use: so lower split_vma
+	 * places tmp vma above, and higher split_vma places tmp vma below.
 	 */
 	if (start > mpnt->vm_start) {
 		if (split_vma(mm, mpnt, start, 0))
 			return -ENOMEM;
 		prev = mpnt;
-		mpnt = mpnt->vm_next;
 	}
 
 	/* Does it split the last one? */
 	last = find_vma(mm, end);
 	if (last && end > last->vm_start) {
-		if (split_vma(mm, last, end, 0))
+		if (split_vma(mm, last, end, 1))
 			return -ENOMEM;
 	}
+	mpnt = prev? prev->vm_next: mm->mmap;
 
 	/*
 	 * Remove the vma's, and unmap the actual pages

_