r2005 - in trunk/kernel/source: kernel-source-2.6.8-2.6.8/debian kernel-source-2.6.8-2.6.8/debian/patches kernel-source-2.6.8-2.6.8/debian/patches/series kernel-source-2.6.9-2.6.9/debian kernel-source-2.6.9-2.6.9/debian/patches kernel-source-2.6.9-2.6.9/debian/patches/series

Andres Salomon dilinger-guest@haydn.debian.org
Thu, 16 Dec 2004 00:56:18 -0700


Author: dilinger-guest
Date: 2004-12-16 00:55:50 -0700 (Thu, 16 Dec 2004)
New Revision: 2005

Added:
   trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos.dpatch
   trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos2.dpatch
   trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos.dpatch
   trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos2.dpatch
Modified:
   trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
   trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-11
   trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/changelog
   trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-4
Log:
  * [SECURITY] memory exhaustion fix where malformed binaries can create
    local DoS (CAN-2004-1074).  Thanks to Moritz Muehlenhoff for pointing
    this out.  64bit-arch fixes are also in here (Andres Salomon).


Modified: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog	2004-12-16 07:55:50 UTC (rev 2005)
@@ -31,6 +31,10 @@
   * [SECURITY] additional scm_send fix (thanks to Andre Tomt for pointing
     this out) (Andres Salomon).
 
+  * [SECURITY] memory exhaustion fix where malformed binaries can create
+    local DoS (CAN-2004-1074).  Thanks to Moritz Muehlenhoff for pointing
+    this out.  64bit-arch fixes are also in here (Andres Salomon).
+
  -- dann frazier <dannf@debian.org>  Fri, 03 Dec 2004 00:13:41 -0700
 
 kernel-source-2.6.8 (2.6.8-10) unstable; urgency=high

Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos.dpatch	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos.dpatch	2004-12-16 07:55:50 UTC (rev 2005)
@@ -0,0 +1,53 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: setup_arg_pages can insert overlapping vma (CAN-2004-1074)
+## DP: Patch author: Chris Wright <chrisw@osdl.org>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/16 17:38:48-08:00 chrisw@osdl.org 
+#   [PATCH] setup_arg_pages can insert overlapping vma
+#   
+#   Florian Heinz built an a.out binary that could map bss from 0x0 to
+#   0xc0000000, and setup_arg_pages() would be unhappt in insert_vma_struct
+#   because the arg pages overlapped.  This just checks before inserting,
+#   and bails out if it would overlap.
+#   
+#   Signed-off-by: Chris Wright <chrisw@osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+# 
+# fs/exec.c
+#   2004/11/11 19:24:54-08:00 chrisw@osdl.org +7 -0
+#   setup_arg_pages can insert overlapping vma
+# 
+diff -Nru a/fs/exec.c b/fs/exec.c
+--- a/fs/exec.c	2004-12-15 23:40:47 -08:00
++++ b/fs/exec.c	2004-12-15 23:40:47 -08:00
+@@ -413,6 +413,7 @@
+ 
+ 	down_write(&mm->mmap_sem);
+ 	{
++		struct vm_area_struct *vma;
+ 		mpnt->vm_mm = mm;
+ #ifdef CONFIG_STACK_GROWSUP
+ 		mpnt->vm_start = stack_base;
+@@ -433,6 +434,12 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+ 		mpnt->vm_flags |= mm->def_flags;
+ 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
++		vma = find_vma(mm, mpnt->vm_start);
++		if (vma) {
++			up_write(&mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return -ENOMEM;
++		}
+ 		insert_vm_struct(mm, mpnt);
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	}

Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos2.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos2.dpatch	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/binfmt-huge-vma-dos2.dpatch	2004-12-16 07:55:50 UTC (rev 2005)
@@ -0,0 +1,279 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: ia64/x86_64/s390 overlapping vma fix (CAN-2004-1074)
+## DP: Patch author: Zou Nan hai <Nanhai.zou@intel.com>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/25 16:00:28-08:00 nanhai.zou@intel.com 
+#   [PATCH] ia64/x86_64/s390 overlapping vma fix
+#   
+#   IA64 is also vulnerable to the huge-vma-in-executable bug in 64 bit elf
+#   support, it just insert a vma of zero page without checking overlap, so user
+#   can construct a elf with section begin from 0x0 to trigger this BUGON().
+#   
+#   However, I think it's safe to check overlap before we actually insert a vma
+#   into vma list.  And I also feel check vma overlap everywhere is unnecessary,
+#   because invert_vm_struct will check it again, so the check is duplicated.
+#   It's better to have invert_vm_struct return a value then let caller check if
+#   it successes.  Here is a patch against 2.6.10.rc2-mm3 I have tested it on
+#   i386, x86_64 and ia64 machines.
+#   
+#   Signed-off-by: Tony Luck <tony.luck@intel.com>
+#   Signed-off-by: Zou Nan hai <Nanhai.zou@intel.com>
+#   Signed-off-by: Andrew Morton <akpm@osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+# 
+# arch/ia64/ia32/binfmt_elf32.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +21 -5
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# arch/ia64/mm/init.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +14 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# arch/s390/kernel/compat_exec.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +6 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# arch/x86_64/ia32/ia32_binfmt.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +6 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# fs/exec.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +3 -6
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# include/linux/mm.h
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +1 -1
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# mm/mmap.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +3 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
+--- a/arch/ia64/ia32/binfmt_elf32.c	2004-12-15 23:41:30 -08:00
++++ b/arch/ia64/ia32/binfmt_elf32.c	2004-12-15 23:41:30 -08:00
+@@ -100,7 +100,11 @@
+ 		vma->vm_ops = &ia32_shared_page_vm_ops;
+ 		down_write(&current->mm->mmap_sem);
+ 		{
+-			insert_vm_struct(current->mm, vma);
++			if (insert_vm_struct(current->mm, vma)) {
++				kmem_cache_free(vm_area_cachep, vma);
++				up_write(&current->mm->mmap_sem);
++				return;
++			}
+ 		}
+ 		up_write(&current->mm->mmap_sem);
+ 	}
+@@ -123,7 +127,11 @@
+ 		vma->vm_ops = &ia32_gate_page_vm_ops;
+ 		down_write(&current->mm->mmap_sem);
+ 		{
+-			insert_vm_struct(current->mm, vma);
++			if (insert_vm_struct(current->mm, vma)) {
++				kmem_cache_free(vm_area_cachep, vma);
++				up_write(&current->mm->mmap_sem);
++				return;
++			}
+ 		}
+ 		up_write(&current->mm->mmap_sem);
+ 	}
+@@ -142,7 +150,11 @@
+ 		vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE;
+ 		down_write(&current->mm->mmap_sem);
+ 		{
+-			insert_vm_struct(current->mm, vma);
++			if (insert_vm_struct(current->mm, vma)) {
++				kmem_cache_free(vm_area_cachep, vma);
++				up_write(&current->mm->mmap_sem);
++				return;
++			}
+ 		}
+ 		up_write(&current->mm->mmap_sem);
+ 	}
+@@ -190,7 +202,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 
+ 	stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
+ 	mm->arg_start = bprm->p + stack_base;
+@@ -225,7 +237,11 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+ 		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)?
+ 					PAGE_COPY_EXEC: PAGE_COPY;
+-		insert_vm_struct(current->mm, mpnt);
++		if ((ret = insert_vm_struct(current->mm, mpnt))) {
++			up_write(&current->mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return ret;
++		}
+ 		current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt);
+ 	}
+ 
+diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
+--- a/arch/ia64/mm/init.c	2004-12-15 23:41:30 -08:00
++++ b/arch/ia64/mm/init.c	2004-12-15 23:41:30 -08:00
+@@ -131,7 +131,13 @@
+ 		vma->vm_end = vma->vm_start + PAGE_SIZE;
+ 		vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7];
+ 		vma->vm_flags = VM_DATA_DEFAULT_FLAGS | VM_GROWSUP;
+-		insert_vm_struct(current->mm, vma);
++		down_write(&current->mm->mmap_sem);
++		if (insert_vm_struct(current->mm, vma)) {
++			up_write(&current->mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, vma);
++			return;
++		}
++		up_write(&current->mm->mmap_sem);
+ 	}
+ 
+ 	/* map NaT-page at address zero to speed up speculative dereferencing of NULL: */
+@@ -143,7 +149,13 @@
+ 			vma->vm_end = PAGE_SIZE;
+ 			vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
+ 			vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO | VM_RESERVED;
+-			insert_vm_struct(current->mm, vma);
++			down_write(&current->mm->mmap_sem);
++			if (insert_vm_struct(current->mm, vma)) {
++				up_write(&current->mm->mmap_sem);
++				kmem_cache_free(vm_area_cachep, vma);
++				return;
++			}
++			up_write(&current->mm->mmap_sem);
+ 		}
+ 	}
+ }
+diff -Nru a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c
+--- a/arch/s390/kernel/compat_exec.c	2004-12-15 23:41:30 -08:00
++++ b/arch/s390/kernel/compat_exec.c	2004-12-15 23:41:30 -08:00
+@@ -39,7 +39,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 
+ 	stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
+ 	mm->arg_start = bprm->p + stack_base;
+@@ -68,7 +68,11 @@
+ 		/* executable stack setting would be applied here */
+ 		mpnt->vm_page_prot = PAGE_COPY;
+ 		mpnt->vm_flags = VM_STACK_FLAGS;
+-		insert_vm_struct(mm, mpnt);
++		if ((ret = insert_vm_struct(mm, mpnt))) {
++			up_write(&mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return ret;
++		}
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	} 
+ 
+diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
+--- a/arch/x86_64/ia32/ia32_binfmt.c	2004-12-15 23:41:30 -08:00
++++ b/arch/x86_64/ia32/ia32_binfmt.c	2004-12-15 23:41:30 -08:00
+@@ -334,7 +334,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 
+ 	stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+ 	mm->arg_start = bprm->p + stack_base;
+@@ -368,7 +368,11 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+  		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? 
+  			PAGE_COPY_EXEC : PAGE_COPY;
+-		insert_vm_struct(mm, mpnt);
++		if ((ret = insert_vm_struct(mm, mpnt))) {
++			up_write(&mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return ret;
++		}
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	} 
+ 
+diff -Nru a/fs/exec.c b/fs/exec.c
+--- a/fs/exec.c	2004-12-15 23:41:30 -08:00
++++ b/fs/exec.c	2004-12-15 23:41:30 -08:00
+@@ -342,7 +342,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 	long arg_size;
+ 
+ #ifdef CONFIG_STACK_GROWSUP
+@@ -413,7 +413,6 @@
+ 
+ 	down_write(&mm->mmap_sem);
+ 	{
+-		struct vm_area_struct *vma;
+ 		mpnt->vm_mm = mm;
+ #ifdef CONFIG_STACK_GROWSUP
+ 		mpnt->vm_start = stack_base;
+@@ -434,13 +433,11 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+ 		mpnt->vm_flags |= mm->def_flags;
+ 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
+-		vma = find_vma(mm, mpnt->vm_start);
+-		if (vma) {
++		if ((ret = insert_vm_struct(mm, mpnt))) {
+ 			up_write(&mm->mmap_sem);
+ 			kmem_cache_free(vm_area_cachep, mpnt);
+-			return -ENOMEM;
++			return ret;
+ 		}
+-		insert_vm_struct(mm, mpnt);
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	}
+ 
+diff -Nru a/include/linux/mm.h b/include/linux/mm.h
+--- a/include/linux/mm.h	2004-12-15 23:41:30 -08:00
++++ b/include/linux/mm.h	2004-12-15 23:41:30 -08:00
+@@ -675,7 +675,7 @@
+ extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *);
+ extern int split_vma(struct mm_struct *,
+ 	struct vm_area_struct *, unsigned long addr, int new_below);
+-extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
++extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
+ extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *,
+ 	struct rb_node **, struct rb_node *);
+ extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c	2004-12-15 23:41:30 -08:00
++++ b/mm/mmap.c	2004-12-15 23:41:30 -08:00
+@@ -1871,7 +1871,7 @@
+  * and into the inode's i_mmap tree.  If vm_file is non-NULL
+  * then i_mmap_lock is taken here.
+  */
+-void insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
++int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
+ {
+ 	struct vm_area_struct * __vma, * prev;
+ 	struct rb_node ** rb_link, * rb_parent;
+@@ -1894,8 +1894,9 @@
+ 	}
+ 	__vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent);
+ 	if (__vma && __vma->vm_start < vma->vm_end)
+-		BUG();
++		return -ENOMEM;
+ 	vma_link(mm, vma, prev, rb_link, rb_parent);
++	return 0;
+ }
+ 
+ /*

Modified: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-11
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-11	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-11	2004-12-16 07:55:50 UTC (rev 2005)
@@ -7,3 +7,5 @@
 + scm_send-dos-fix.dpatch
 + igmp-src-list-fix.dpatch
 + scm_send-dos-fix2.dpatch
++ binfmt-huge-vma-dos.dpatch
++ binfmt-huge-vma-dos2.dpatch

Modified: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/changelog
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/changelog	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/changelog	2004-12-16 07:55:50 UTC (rev 2005)
@@ -36,6 +36,10 @@
   * [SECURITY] additional scm_send fix (thanks to Andre Tomt for pointing
     this out) (Andres Salomon).
 
+  * [SECURITY] memory exhaustion fix where malformed binaries can create
+    local DoS (CAN-2004-1074).  Thanks to Moritz Muehlenhoff for pointing
+    this out.  64bit-arch fixes are also in here (Andres Salomon).
+
  -- dann frazier <dannf@debian.org>  Fri, 03 Dec 2004 09:26:52 -0700
 
 kernel-source-2.6.9 (2.6.9-3) unstable; urgency=low

Added: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos.dpatch	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos.dpatch	2004-12-16 07:55:50 UTC (rev 2005)
@@ -0,0 +1,53 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: setup_arg_pages can insert overlapping vma (CAN-2004-1074)
+## DP: Patch author: Chris Wright <chrisw@osdl.org>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/16 17:38:48-08:00 chrisw@osdl.org 
+#   [PATCH] setup_arg_pages can insert overlapping vma
+#   
+#   Florian Heinz built an a.out binary that could map bss from 0x0 to
+#   0xc0000000, and setup_arg_pages() would be unhappt in insert_vma_struct
+#   because the arg pages overlapped.  This just checks before inserting,
+#   and bails out if it would overlap.
+#   
+#   Signed-off-by: Chris Wright <chrisw@osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+# 
+# fs/exec.c
+#   2004/11/11 19:24:54-08:00 chrisw@osdl.org +7 -0
+#   setup_arg_pages can insert overlapping vma
+# 
+diff -Nru a/fs/exec.c b/fs/exec.c
+--- a/fs/exec.c	2004-12-15 23:40:47 -08:00
++++ b/fs/exec.c	2004-12-15 23:40:47 -08:00
+@@ -413,6 +413,7 @@
+ 
+ 	down_write(&mm->mmap_sem);
+ 	{
++		struct vm_area_struct *vma;
+ 		mpnt->vm_mm = mm;
+ #ifdef CONFIG_STACK_GROWSUP
+ 		mpnt->vm_start = stack_base;
+@@ -433,6 +434,12 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+ 		mpnt->vm_flags |= mm->def_flags;
+ 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
++		vma = find_vma(mm, mpnt->vm_start);
++		if (vma) {
++			up_write(&mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return -ENOMEM;
++		}
+ 		insert_vm_struct(mm, mpnt);
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	}

Added: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos2.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos2.dpatch	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/binfmt-huge-vma-dos2.dpatch	2004-12-16 07:55:50 UTC (rev 2005)
@@ -0,0 +1,279 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: ia64/x86_64/s390 overlapping vma fix (CAN-2004-1074)
+## DP: Patch author: Zou Nan hai <Nanhai.zou@intel.com>
+## DP: Upstream status: backport
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+#   2004/11/25 16:00:28-08:00 nanhai.zou@intel.com 
+#   [PATCH] ia64/x86_64/s390 overlapping vma fix
+#   
+#   IA64 is also vulnerable to the huge-vma-in-executable bug in 64 bit elf
+#   support, it just insert a vma of zero page without checking overlap, so user
+#   can construct a elf with section begin from 0x0 to trigger this BUGON().
+#   
+#   However, I think it's safe to check overlap before we actually insert a vma
+#   into vma list.  And I also feel check vma overlap everywhere is unnecessary,
+#   because invert_vm_struct will check it again, so the check is duplicated.
+#   It's better to have invert_vm_struct return a value then let caller check if
+#   it successes.  Here is a patch against 2.6.10.rc2-mm3 I have tested it on
+#   i386, x86_64 and ia64 machines.
+#   
+#   Signed-off-by: Tony Luck <tony.luck@intel.com>
+#   Signed-off-by: Zou Nan hai <Nanhai.zou@intel.com>
+#   Signed-off-by: Andrew Morton <akpm@osdl.org>
+#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+# 
+# arch/ia64/ia32/binfmt_elf32.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +21 -5
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# arch/ia64/mm/init.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +14 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# arch/s390/kernel/compat_exec.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +6 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# arch/x86_64/ia32/ia32_binfmt.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +6 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# fs/exec.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +3 -6
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# include/linux/mm.h
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +1 -1
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+# mm/mmap.c
+#   2004/11/24 22:42:43-08:00 nanhai.zou@intel.com +3 -2
+#   ia64/x86_64/s390 overlapping vma fix
+# 
+diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
+--- a/arch/ia64/ia32/binfmt_elf32.c	2004-12-15 23:41:30 -08:00
++++ b/arch/ia64/ia32/binfmt_elf32.c	2004-12-15 23:41:30 -08:00
+@@ -100,7 +100,11 @@
+ 		vma->vm_ops = &ia32_shared_page_vm_ops;
+ 		down_write(&current->mm->mmap_sem);
+ 		{
+-			insert_vm_struct(current->mm, vma);
++			if (insert_vm_struct(current->mm, vma)) {
++				kmem_cache_free(vm_area_cachep, vma);
++				up_write(&current->mm->mmap_sem);
++				return;
++			}
+ 		}
+ 		up_write(&current->mm->mmap_sem);
+ 	}
+@@ -123,7 +127,11 @@
+ 		vma->vm_ops = &ia32_gate_page_vm_ops;
+ 		down_write(&current->mm->mmap_sem);
+ 		{
+-			insert_vm_struct(current->mm, vma);
++			if (insert_vm_struct(current->mm, vma)) {
++				kmem_cache_free(vm_area_cachep, vma);
++				up_write(&current->mm->mmap_sem);
++				return;
++			}
+ 		}
+ 		up_write(&current->mm->mmap_sem);
+ 	}
+@@ -142,7 +150,11 @@
+ 		vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE;
+ 		down_write(&current->mm->mmap_sem);
+ 		{
+-			insert_vm_struct(current->mm, vma);
++			if (insert_vm_struct(current->mm, vma)) {
++				kmem_cache_free(vm_area_cachep, vma);
++				up_write(&current->mm->mmap_sem);
++				return;
++			}
+ 		}
+ 		up_write(&current->mm->mmap_sem);
+ 	}
+@@ -190,7 +202,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 
+ 	stack_base = IA32_STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
+ 	mm->arg_start = bprm->p + stack_base;
+@@ -225,7 +237,11 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+ 		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC)?
+ 					PAGE_COPY_EXEC: PAGE_COPY;
+-		insert_vm_struct(current->mm, mpnt);
++		if ((ret = insert_vm_struct(current->mm, mpnt))) {
++			up_write(&current->mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return ret;
++		}
+ 		current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt);
+ 	}
+ 
+diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
+--- a/arch/ia64/mm/init.c	2004-12-15 23:41:30 -08:00
++++ b/arch/ia64/mm/init.c	2004-12-15 23:41:30 -08:00
+@@ -131,7 +131,13 @@
+ 		vma->vm_end = vma->vm_start + PAGE_SIZE;
+ 		vma->vm_page_prot = protection_map[VM_DATA_DEFAULT_FLAGS & 0x7];
+ 		vma->vm_flags = VM_DATA_DEFAULT_FLAGS | VM_GROWSUP;
+-		insert_vm_struct(current->mm, vma);
++		down_write(&current->mm->mmap_sem);
++		if (insert_vm_struct(current->mm, vma)) {
++			up_write(&current->mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, vma);
++			return;
++		}
++		up_write(&current->mm->mmap_sem);
+ 	}
+ 
+ 	/* map NaT-page at address zero to speed up speculative dereferencing of NULL: */
+@@ -143,7 +149,13 @@
+ 			vma->vm_end = PAGE_SIZE;
+ 			vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
+ 			vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO | VM_RESERVED;
+-			insert_vm_struct(current->mm, vma);
++			down_write(&current->mm->mmap_sem);
++			if (insert_vm_struct(current->mm, vma)) {
++				up_write(&current->mm->mmap_sem);
++				kmem_cache_free(vm_area_cachep, vma);
++				return;
++			}
++			up_write(&current->mm->mmap_sem);
+ 		}
+ 	}
+ }
+diff -Nru a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c
+--- a/arch/s390/kernel/compat_exec.c	2004-12-15 23:41:30 -08:00
++++ b/arch/s390/kernel/compat_exec.c	2004-12-15 23:41:30 -08:00
+@@ -39,7 +39,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 
+ 	stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
+ 	mm->arg_start = bprm->p + stack_base;
+@@ -68,7 +68,11 @@
+ 		/* executable stack setting would be applied here */
+ 		mpnt->vm_page_prot = PAGE_COPY;
+ 		mpnt->vm_flags = VM_STACK_FLAGS;
+-		insert_vm_struct(mm, mpnt);
++		if ((ret = insert_vm_struct(mm, mpnt))) {
++			up_write(&mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return ret;
++		}
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	} 
+ 
+diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
+--- a/arch/x86_64/ia32/ia32_binfmt.c	2004-12-15 23:41:30 -08:00
++++ b/arch/x86_64/ia32/ia32_binfmt.c	2004-12-15 23:41:30 -08:00
+@@ -334,7 +334,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 
+ 	stack_base = IA32_STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
+ 	mm->arg_start = bprm->p + stack_base;
+@@ -368,7 +368,11 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+  		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? 
+  			PAGE_COPY_EXEC : PAGE_COPY;
+-		insert_vm_struct(mm, mpnt);
++		if ((ret = insert_vm_struct(mm, mpnt))) {
++			up_write(&mm->mmap_sem);
++			kmem_cache_free(vm_area_cachep, mpnt);
++			return ret;
++		}
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	} 
+ 
+diff -Nru a/fs/exec.c b/fs/exec.c
+--- a/fs/exec.c	2004-12-15 23:41:30 -08:00
++++ b/fs/exec.c	2004-12-15 23:41:30 -08:00
+@@ -342,7 +342,7 @@
+ 	unsigned long stack_base;
+ 	struct vm_area_struct *mpnt;
+ 	struct mm_struct *mm = current->mm;
+-	int i;
++	int i, ret;
+ 	long arg_size;
+ 
+ #ifdef CONFIG_STACK_GROWSUP
+@@ -413,7 +413,6 @@
+ 
+ 	down_write(&mm->mmap_sem);
+ 	{
+-		struct vm_area_struct *vma;
+ 		mpnt->vm_mm = mm;
+ #ifdef CONFIG_STACK_GROWSUP
+ 		mpnt->vm_start = stack_base;
+@@ -434,13 +433,11 @@
+ 			mpnt->vm_flags = VM_STACK_FLAGS;
+ 		mpnt->vm_flags |= mm->def_flags;
+ 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
+-		vma = find_vma(mm, mpnt->vm_start);
+-		if (vma) {
++		if ((ret = insert_vm_struct(mm, mpnt))) {
+ 			up_write(&mm->mmap_sem);
+ 			kmem_cache_free(vm_area_cachep, mpnt);
+-			return -ENOMEM;
++			return ret;
+ 		}
+-		insert_vm_struct(mm, mpnt);
+ 		mm->stack_vm = mm->total_vm = vma_pages(mpnt);
+ 	}
+ 
+diff -Nru a/include/linux/mm.h b/include/linux/mm.h
+--- a/include/linux/mm.h	2004-12-15 23:41:30 -08:00
++++ b/include/linux/mm.h	2004-12-15 23:41:30 -08:00
+@@ -675,7 +675,7 @@
+ extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *);
+ extern int split_vma(struct mm_struct *,
+ 	struct vm_area_struct *, unsigned long addr, int new_below);
+-extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
++extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
+ extern void __vma_link_rb(struct mm_struct *, struct vm_area_struct *,
+ 	struct rb_node **, struct rb_node *);
+ extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c	2004-12-15 23:41:30 -08:00
++++ b/mm/mmap.c	2004-12-15 23:41:30 -08:00
+@@ -1871,7 +1871,7 @@
+  * and into the inode's i_mmap tree.  If vm_file is non-NULL
+  * then i_mmap_lock is taken here.
+  */
+-void insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
++int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
+ {
+ 	struct vm_area_struct * __vma, * prev;
+ 	struct rb_node ** rb_link, * rb_parent;
+@@ -1894,8 +1894,9 @@
+ 	}
+ 	__vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent);
+ 	if (__vma && __vma->vm_start < vma->vm_end)
+-		BUG();
++		return -ENOMEM;
+ 	vma_link(mm, vma, prev, rb_link, rb_parent);
++	return 0;
+ }
+ 
+ /*

Modified: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-4
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-4	2004-12-16 07:42:28 UTC (rev 2004)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-4	2004-12-16 07:55:50 UTC (rev 2005)
@@ -9,3 +9,5 @@
 + scm_send-dos-fix.dpatch
 + igmp-src-list-fix.dpatch
 + scm_send-dos-fix2.dpatch
++ binfmt-huge-vma-dos.dpatch
++ binfmt-huge-vma-dos2.dpatch