From: Marcelo Tosatti <marcelo.tosatti@cyclades.com>

Two threads sharing the same VMA can race in expand_stack, resulting in
incorrect VMA size accounting and possibly a "uncovered-by-VMA" pte leak.

Fix is to check if the stack has already been expanded after acquiring a
lock which guarantees exclusivity (page_table_lock in v2.4 and vma_anon
lock in v2.6).

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/mm/mmap.c |   13 +++++++++++++
 1 files changed, 13 insertions(+)

diff -puN mm/mmap.c~fix-expand_stack-smp-race mm/mmap.c
--- 25/mm/mmap.c~fix-expand_stack-smp-race	2005-01-10 21:14:17.112973400 -0800
+++ 25-akpm/mm/mmap.c	2005-01-10 21:14:17.116972792 -0800
@@ -1496,6 +1496,13 @@ int expand_stack(struct vm_area_struct *
 	 */
 	address += 4 + PAGE_SIZE - 1;
 	address &= PAGE_MASK;
+
+	/* already expanded while waiting for anon_vma lock? */
+	if (vma->vm_end >= address) {
+		anon_vma_unlock(vma);
+		return 0;
+	}
+
 	size = address - vma->vm_start;
 	grow = (address - vma->vm_end) >> PAGE_SHIFT;
 
@@ -1539,6 +1546,12 @@ int expand_stack(struct vm_area_struct *
 		return -ENOMEM;
 	anon_vma_lock(vma);
 
+	/* already expanded while waiting for anon_vma lock? */
+	if (vma->vm_start <= address) {
+		anon_vma_unlock(vma);
+		return 0;
+	}
+
 	/*
 	 * vma->vm_start/vm_end cannot change under us because the caller
 	 * is required to hold the mmap_sem in read mode.  We need the
_