From: Hugh Dickins <hugh@veritas.com>

Fix vma_adjust adjust_next wrapping: Rajesh V.  pointed out that if end were
2GB or more beyond next->vm_start (on 32-bit), then next->vm_pgoff would have
been negatively adjusted.

Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/mm/mmap.c |   27 +++++++++++++++++----------
 1 files changed, 17 insertions(+), 10 deletions(-)

diff -puN mm/mmap.c~mm-vma_adjust-adjust_next-wrap mm/mmap.c
--- 25/mm/mmap.c~mm-vma_adjust-adjust_next-wrap	Wed Jun  2 15:12:24 2004
+++ 25-akpm/mm/mmap.c	Wed Jun  2 15:12:25 2004
@@ -373,20 +373,27 @@ void vma_adjust(struct vm_area_struct *v
 
 	if (next && !insert) {
 		if (end >= next->vm_end) {
+			/*
+			 * vma expands, overlapping all the next, and
+			 * perhaps the one after too (mprotect case 6).
+			 */
 again:			remove_next = 1 + (end > next->vm_end);
 			end = next->vm_end;
 			anon_vma = next->anon_vma;
-		} else if (end < vma->vm_end || end > next->vm_start) {
+		} else if (end > next->vm_start) {
 			/*
-			 * vma shrinks, and !insert tells it's not
-			 * split_vma inserting another: so it must
-			 * be mprotect shifting the boundary down.
-			 *   Or:
 			 * vma expands, overlapping part of the next:
-			 * must be mprotect shifting the boundary up.
+			 * mprotect case 5 shifting the boundary up.
+			 */
+			adjust_next = (end - next->vm_start) >> PAGE_SHIFT;
+			anon_vma = next->anon_vma;
+		} else if (end < vma->vm_end) {
+			/*
+			 * vma shrinks, and !insert tells it's not
+			 * split_vma inserting another: so it must be
+			 * mprotect case 4 shifting the boundary down.
 			 */
-			BUG_ON(vma->vm_end != next->vm_start);
-			adjust_next = end - next->vm_start;
+			adjust_next = - ((vma->vm_end - end) >> PAGE_SHIFT);
 			anon_vma = next->anon_vma;
 		}
 	}
@@ -418,8 +425,8 @@ again:			remove_next = 1 + (end > next->
 	vma->vm_end = end;
 	vma->vm_pgoff = pgoff;
 	if (adjust_next) {
-		next->vm_start += adjust_next;
-		next->vm_pgoff += adjust_next >> PAGE_SHIFT;
+		next->vm_start += adjust_next << PAGE_SHIFT;
+		next->vm_pgoff += adjust_next;
 	}
 
 	if (root) {
_