r2284 - in trunk/kernel/source: kernel-source-2.6.10-2.6.10/debian kernel-source-2.6.10-2.6.10/debian/patches kernel-source-2.6.10-2.6.10/debian/patches/series 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@costa.debian.org
Thu, 13 Jan 2005 07:47:09 +0100
Author: dilinger-guest
Date: 2005-01-13 07:47:07 +0100 (Thu, 13 Jan 2005)
New Revision: 2284
Added:
trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/033-rlimit_memlock_check.dpatch
trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/034-stack_resize_exploit.dpatch
trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/035-do_brk_security_fixes-2.dpatch
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/033-rlimit_memlock_check.dpatch
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/034-stack_resize_exploit.dpatch
trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/035-do_brk_security_fixes-2.dpatch
trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/033-rlimit_memlock_check.dpatch
trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/034-stack_resize_exploit.dpatch
trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/035-do_brk_security_fixes-2.dpatch
trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-6
Modified:
trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/changelog
trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/series/2.6.10-4
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-13
trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/changelog
Log:
* [SECURITY] 033-rlimit_memlock_check.dpatch
RLIMIT_MEMLOCK isn't checked properly, allowing for a DoS attack.
See http://seclists.org/lists/fulldisclosure/2005/Jan/0270.html for
more details. This patch fixes it, and all reorganizes the stack resize
stuff a bit (*sigh*) (Andres Salomon).
* [SECURITY] 034-stack_resize_exploit.dpatch
Fix exploitable race condition on SMP and HT systems where two
threads attempt to expand the stack at the same time. This is
CAN-2005-0001 (happy new year!) (Andres Salomon).
* [SECURITY] 035-do_brk_security_fixes-2.dpatch
Further do_brk fixes; just to be safe, lock everywhere do_brk
is used (Andres Salomon).
Modified: trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/changelog
===================================================================
--- trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/changelog 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/changelog 2005-01-13 06:47:07 UTC (rev 2284)
@@ -27,6 +27,21 @@
* Fix weird alpha IO failures due to typo. (Maximilian Attems)
+ * [SECURITY] 033-rlimit_memlock_check.dpatch
+ RLIMIT_MEMLOCK isn't checked properly, allowing for a DoS attack.
+ See http://seclists.org/lists/fulldisclosure/2005/Jan/0270.html for
+ more details. This patch fixes it, and all reorganizes the stack resize
+ stuff a bit (*sigh*) (Andres Salomon).
+
+ * [SECURITY] 034-stack_resize_exploit.dpatch
+ Fix exploitable race condition on SMP and HT systems where two
+ threads attempt to expand the stack at the same time. This is
+ CAN-2005-0001 (happy new year!) (Andres Salomon).
+
+ * [SECURITY] 035-do_brk_security_fixes-2.dpatch
+ Further do_brk fixes; just to be safe, lock everywhere do_brk
+ is used (Andres Salomon).
+
-- Sven Luther <luther@debian.org> Mon, 10 Jan 2005 18:06:29 +0100
kernel-source-2.6.10 (2.6.10-3) unstable; urgency=low
Added: trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/033-rlimit_memlock_check.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/033-rlimit_memlock_check.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/033-rlimit_memlock_check.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,182 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Clean up stack growth checks and move them into a common function.
+## DP: Patch author: torvalds@ppc970.osdl.org
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/10 11:23:42-08:00 torvalds@ppc970.osdl.org
+# Clean up stack growth checks and move them into a common function.
+#
+# The grows-up and grows-down cases had all the same issues, but
+# differered in the details. Additionlly, historical evolution of
+# the tests had caused the result to be pretty unreadable with some
+# rather long and complex conditionals.
+#
+# Fix it all up in a more readable helper function.
+#
+# This also adds the missing RLIMIT_MEMLOCK test.
+#
+# mm/mmap.c
+# 2005/01/10 11:23:35-08:00 torvalds@ppc970.osdl.org +61 -44
+# Clean up stack growth checks and move them into a common function.
+#
+# The grows-up and grows-down cases had all the same issues, but
+# differered in the details. Additionlly, historical evolution of
+# the tests had caused the result to be pretty unreadable with some
+# rather long and complex conditionals.
+#
+# Fix it all up in a more readable helper function.
+#
+# This also adds the missing RLIMIT_MEMLOCK test.
+#
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:21:10 -08:00
++++ b/mm/mmap.c 2005-01-12 20:21:10 -08:00
+@@ -1335,13 +1335,58 @@
+ return prev ? prev->vm_next : vma;
+ }
+
++/*
++ * Verify that the stack growth is acceptable and
++ * update accounting. This is shared with both the
++ * grow-up and grow-down cases.
++ */
++static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, unsigned long grow)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ struct rlimit *rlim = current->signal->rlim;
++
++ /* address space limit tests */
++ rlim = current->signal->rlim;
++ if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
++ return -ENOMEM;
++
++ /* Stack limit test */
++ if (size > rlim[RLIMIT_STACK].rlim_cur)
++ return -ENOMEM;
++
++ /* mlock limit tests */
++ if (vma->vm_flags & VM_LOCKED) {
++ unsigned long locked;
++ unsigned long limit;
++ locked = mm->locked_vm + grow;
++ limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
++ if (locked > limit)
++ return -ENOMEM;
++ }
++
++ /*
++ * Overcommit.. This must be the final test, as it will
++ * update security statistics.
++ */
++ if (security_vm_enough_memory(grow))
++ return -ENOMEM;
++
++ /* Ok, everything looks good - let it rip */
++ mm->total_vm += grow;
++ if (vma->vm_flags & VM_LOCKED)
++ mm->locked_vm += grow;
++ __vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
++ return 0;
++}
++
+ #ifdef CONFIG_STACK_GROWSUP
+ /*
+ * vma is the first one with address > vma->vm_end. Have to extend vma.
+ */
+ int expand_stack(struct vm_area_struct * vma, unsigned long address)
+ {
+- unsigned long grow;
++ int error;
++ unsigned long size, grow;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+@@ -1361,28 +1406,14 @@
+ */
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
++ size = address - vma->vm_start;
+ grow = (address - vma->vm_end) >> PAGE_SHIFT;
+
+- /* Overcommit.. */
+- if (security_vm_enough_memory(grow)) {
+- anon_vma_unlock(vma);
+- return -ENOMEM;
+- }
+-
+- if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
+- ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+- current->signal->rlim[RLIMIT_AS].rlim_cur) {
+- anon_vma_unlock(vma);
+- vm_unacct_memory(grow);
+- return -ENOMEM;
+- }
+- vma->vm_end = address;
+- vma->vm_mm->total_vm += grow;
+- if (vma->vm_flags & VM_LOCKED)
+- vma->vm_mm->locked_vm += grow;
+- __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
++ error = acct_stack_growth(vma, size, grow);
++ if (!error)
++ vma->vm_end = address;
+ anon_vma_unlock(vma);
+- return 0;
++ return error;
+ }
+
+ struct vm_area_struct *
+@@ -1409,7 +1440,8 @@
+ */
+ int expand_stack(struct vm_area_struct *vma, unsigned long address)
+ {
+- unsigned long grow;
++ int error;
++ unsigned long size, grow;
+
+ /*
+ * We must make sure the anon_vma is allocated
+@@ -1425,29 +1457,16 @@
+ * anon_vma lock to serialize against concurrent expand_stacks.
+ */
+ address &= PAGE_MASK;
++ size = vma->vm_end - address;
+ grow = (vma->vm_start - address) >> PAGE_SHIFT;
+
+- /* Overcommit.. */
+- if (security_vm_enough_memory(grow)) {
+- anon_vma_unlock(vma);
+- return -ENOMEM;
+- }
+-
+- if (vma->vm_end - address > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
+- ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+- current->signal->rlim[RLIMIT_AS].rlim_cur) {
+- anon_vma_unlock(vma);
+- vm_unacct_memory(grow);
+- return -ENOMEM;
++ error = acct_stack_growth(vma, size, grow);
++ if (!error) {
++ vma->vm_start = address;
++ vma->vm_pgoff -= grow;
+ }
+- vma->vm_start = address;
+- vma->vm_pgoff -= grow;
+- vma->vm_mm->total_vm += grow;
+- if (vma->vm_flags & VM_LOCKED)
+- vma->vm_mm->locked_vm += grow;
+- __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
+ anon_vma_unlock(vma);
+- return 0;
++ return error;
+ }
+
+ struct vm_area_struct *
Added: trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/034-stack_resize_exploit.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/034-stack_resize_exploit.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/034-stack_resize_exploit.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,101 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Handle two threads both trying to expand their stack simultaneously.
+## DP: Patch author: torvalds@ppc970.osdl.org
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/12 08:09:20-08:00 torvalds@ppc970.osdl.org
+# Handle two threads both trying to expand their stack simultaneously.
+#
+# We had all the locking right, but we didn't check whether one of the
+# threads now no longer needed to expand, so we could incorrectly _shrink_
+# the stack in the other thread instead (not only causing segfaults, but
+# since we didn't do a proper unmap, we'd possibly leak pages too).
+#
+# So re-check the need for expand after getting the lock.
+#
+# Noticed by Paul Starzetz.
+#
+# mm/mmap.c
+# 2005/01/12 08:09:12-08:00 torvalds@ppc970.osdl.org +25 -13
+# Handle two threads both trying to expand their stack simultaneously.
+#
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:22:12 -08:00
++++ b/mm/mmap.c 2005-01-12 20:22:12 -08:00
+@@ -1475,7 +1475,6 @@
+ int expand_stack(struct vm_area_struct * vma, unsigned long address)
+ {
+ int error;
+- unsigned long size, grow;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+@@ -1495,12 +1494,19 @@
+ */
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
+- size = address - vma->vm_start;
+- grow = (address - vma->vm_end) >> PAGE_SHIFT;
++ error = 0;
+
+- error = acct_stack_growth(vma, size, grow);
+- if (!error)
+- vma->vm_end = address;
++ /* Somebody else might have raced and expanded it already */
++ if (address > vma->vm_end) {
++ unsigned long size, grow;
++
++ size = address - vma->vm_start;
++ grow = (address - vma->vm_end) >> PAGE_SHIFT;
++
++ error = acct_stack_growth(vma, size, grow);
++ if (!error)
++ vma->vm_end = address;
++ }
+ anon_vma_unlock(vma);
+ return error;
+ }
+@@ -1528,7 +1534,6 @@
+ int expand_stack(struct vm_area_struct *vma, unsigned long address)
+ {
+ int error;
+- unsigned long size, grow;
+
+ /*
+ * We must make sure the anon_vma is allocated
+@@ -1544,13 +1549,20 @@
+ * anon_vma lock to serialize against concurrent expand_stacks.
+ */
+ address &= PAGE_MASK;
+- size = vma->vm_end - address;
+- grow = (vma->vm_start - address) >> PAGE_SHIFT;
++ error = 0;
+
+- error = acct_stack_growth(vma, size, grow);
+- if (!error) {
+- vma->vm_start = address;
+- vma->vm_pgoff -= grow;
++ /* Somebody else might have raced and expanded it already */
++ if (address < vma->vm_start) {
++ unsigned long size, grow;
++
++ size = vma->vm_end - address;
++ grow = (vma->vm_start - address) >> PAGE_SHIFT;
++
++ error = acct_stack_growth(vma, size, grow);
++ if (!error) {
++ vma->vm_start = address;
++ vma->vm_pgoff -= grow;
++ }
+ }
+ anon_vma_unlock(vma);
+ return error;
Added: trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/035-do_brk_security_fixes-2.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/035-do_brk_security_fixes-2.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/035-do_brk_security_fixes-2.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,334 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: [PATCH] do_brk() needs mmap_sem write-locked
+## DP: Patch author: marcelo.tosatti@cyclades.com
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/12 08:12:09-08:00 marcelo.tosatti@cyclades.com
+# [PATCH] do_brk() needs mmap_sem write-locked
+#
+# It seems to be general consensus that its safer to require all do_brk() callers
+# to grab mmap_sem, and have do_brk to warn otherwise. This is what the following
+# patch does.
+#
+# Similar version has been changed to in v2.4.
+#
+# Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+#
+# arch/mips/kernel/irixelf.c
+# 2005/01/11 17:35:36-08:00 marcelo.tosatti@cyclades.com +10 -1
+# do_brk() needs mmap_sem write-locked
+#
+# arch/sparc64/kernel/binfmt_aout32.c
+# 2005/01/11 17:37:28-08:00 marcelo.tosatti@cyclades.com +12 -0
+# do_brk() needs mmap_sem write-locked
+#
+# arch/x86_64/ia32/ia32_aout.c
+# 2005/01/11 17:34:26-08:00 marcelo.tosatti@cyclades.com +11 -1
+# do_brk() needs mmap_sem write-locked
+#
+# fs/binfmt_aout.c
+# 2005/01/11 17:31:51-08:00 marcelo.tosatti@cyclades.com +14 -3
+# do_brk() needs mmap_sem write-locked
+#
+# fs/binfmt_elf.c
+# 2005/01/11 18:07:01-08:00 marcelo.tosatti@cyclades.com +11 -1
+# do_brk() needs mmap_sem write-locked
+#
+# mm/mmap.c
+# 2005/01/11 17:43:11-08:00 marcelo.tosatti@cyclades.com +6 -0
+# do_brk() needs mmap_sem write-locked
+#
+diff -Nru a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
+--- a/arch/mips/kernel/irixelf.c 2005-01-12 20:26:27 -08:00
++++ b/arch/mips/kernel/irixelf.c 2005-01-12 20:26:27 -08:00
+@@ -127,7 +127,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+
+@@ -375,7 +377,9 @@
+
+ /* Map the last of the bss segment */
+ if (last_bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ do_brk(len, (last_bss - len));
++ up_write(¤t->mm->mmap_sem);
+ }
+ kfree(elf_phdata);
+
+@@ -562,7 +566,9 @@
+ unsigned long v;
+ struct prda *pp;
+
++ down_write(¤t->mm->mmap_sem);
+ v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
++ up_write(¤t->mm->mmap_sem);
+
+ if (v < 0)
+ return;
+@@ -852,8 +858,11 @@
+
+ len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
+ bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
+- if (bss > len)
++ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ do_brk(len, bss-len);
++ up_write(¤t->mm->mmap_sem);
++ }
+ kfree(elf_phdata);
+ return 0;
+ }
+diff -Nru a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
+--- a/arch/sparc64/kernel/binfmt_aout32.c 2005-01-12 20:26:27 -08:00
++++ b/arch/sparc64/kernel/binfmt_aout32.c 2005-01-12 20:26:27 -08:00
+@@ -49,7 +49,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+ /*
+@@ -246,10 +248,14 @@
+ if (N_MAGIC(ex) == NMAGIC) {
+ loff_t pos = fd_offset;
+ /* Fuck me plenty... */
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_TXTADDR(ex), ex.a_text);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+ ex.a_text, &pos);
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_DATADDR(ex), ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
+ ex.a_data, &pos);
+ goto beyond_if;
+@@ -257,8 +263,10 @@
+
+ if (N_MAGIC(ex) == OMAGIC) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex) & PAGE_MASK,
+ ex.a_text+ex.a_data + PAGE_SIZE - 1);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+ } else {
+@@ -272,7 +280,9 @@
+
+ if (!bprm->file->f_op->mmap) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(0, ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+@@ -389,7 +399,9 @@
+ len = PAGE_ALIGN(ex.a_text + ex.a_data);
+ bss = ex.a_text + ex.a_data + ex.a_bss;
+ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(start_addr + len, bss - len);
++ up_write(¤t->mm->mmap_sem);
+ retval = error;
+ if (error != start_addr + len)
+ goto out;
+diff -Nru a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
+--- a/arch/x86_64/ia32/ia32_aout.c 2005-01-12 20:26:27 -08:00
++++ b/arch/x86_64/ia32/ia32_aout.c 2005-01-12 20:26:27 -08:00
+@@ -115,7 +115,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+ #if CORE_DUMP
+@@ -325,7 +327,10 @@
+ pos = 32;
+ map_size = ex.a_text+ex.a_data;
+
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(text_addr & PAGE_MASK, map_size);
++ up_write(¤t->mm->mmap_sem);
++
+ if (error != (text_addr & PAGE_MASK)) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+@@ -361,7 +366,9 @@
+
+ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+ flush_icache_range((unsigned long) N_TXTADDR(ex),
+@@ -469,8 +476,9 @@
+ error_time = jiffies;
+ }
+ #endif
+-
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
++ up_write(¤t->mm->mmap_sem);
+
+ file->f_op->read(file, (char *)start_addr,
+ ex.a_text + ex.a_data, &pos);
+@@ -494,7 +502,9 @@
+ len = PAGE_ALIGN(ex.a_text + ex.a_data);
+ bss = ex.a_text + ex.a_data + ex.a_bss;
+ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(start_addr + len, bss - len);
++ up_write(¤t->mm->mmap_sem);
+ retval = error;
+ if (error != start_addr + len)
+ goto out;
+diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
+--- a/fs/binfmt_aout.c 2005-01-12 20:26:27 -08:00
++++ b/fs/binfmt_aout.c 2005-01-12 20:26:27 -08:00
+@@ -50,7 +50,10 @@
+ start = PAGE_ALIGN(start);
+ end = PAGE_ALIGN(end);
+ if (end > start) {
+- unsigned long addr = do_brk(start, end - start);
++ unsigned long addr;
++ down_write(¤t->mm->mmap_sem);
++ addr = do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+@@ -323,10 +326,14 @@
+ loff_t pos = fd_offset;
+ /* Fuck me plenty... */
+ /* <AOL></AOL> */
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_TXTADDR(ex), ex.a_text);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
+ ex.a_text, &pos);
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_DATADDR(ex), ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
+ ex.a_data, &pos);
+ goto beyond_if;
+@@ -346,8 +353,9 @@
+ pos = 32;
+ map_size = ex.a_text+ex.a_data;
+ #endif
+-
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(text_addr & PAGE_MASK, map_size);
++ up_write(¤t->mm->mmap_sem);
+ if (error != (text_addr & PAGE_MASK)) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+@@ -382,7 +390,9 @@
+
+ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+@@ -487,8 +497,9 @@
+ file->f_dentry->d_name.name);
+ error_time = jiffies;
+ }
+-
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
++ up_write(¤t->mm->mmap_sem);
+
+ file->f_op->read(file, (char __user *)start_addr,
+ ex.a_text + ex.a_data, &pos);
+diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+--- a/fs/binfmt_elf.c 2005-01-12 20:26:27 -08:00
++++ b/fs/binfmt_elf.c 2005-01-12 20:26:27 -08:00
+@@ -88,7 +88,10 @@
+ start = ELF_PAGEALIGN(start);
+ end = ELF_PAGEALIGN(end);
+ if (end > start) {
+- unsigned long addr = do_brk(start, end - start);
++ unsigned long addr;
++ down_write(¤t->mm->mmap_sem);
++ addr = do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+@@ -409,7 +412,9 @@
+
+ /* Map the last of the bss segment */
+ if (last_bss > elf_bss) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(elf_bss, last_bss - elf_bss);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(error))
+ goto out_close;
+ }
+@@ -449,7 +454,9 @@
+ goto out;
+ }
+
++ down_write(¤t->mm->mmap_sem);
+ do_brk(0, text_data);
++ up_write(¤t->mm->mmap_sem);
+ if (!interpreter->f_op || !interpreter->f_op->read)
+ goto out;
+ if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
+@@ -457,8 +464,11 @@
+ flush_icache_range((unsigned long)addr,
+ (unsigned long)addr + text_data);
+
++
++ down_write(¤t->mm->mmap_sem);
+ do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
+ interp_ex->a_bss);
++ up_write(¤t->mm->mmap_sem);
+ elf_entry = interp_ex->a_entry;
+
+ out:
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:26:27 -08:00
++++ b/mm/mmap.c 2005-01-12 20:26:27 -08:00
+@@ -1903,6 +1903,12 @@
+ }
+
+ /*
++ * mm->mmap_sem is required to protect against another thread
++ * changing the mappings in case we sleep.
++ */
++ WARN_ON(down_read_trylock(&mm->mmap_sem));
++
++ /*
+ * Clear old maps. this also does some error checking for us
+ */
+ munmap_back:
Modified: trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/series/2.6.10-4
===================================================================
--- trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/series/2.6.10-4 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.10-2.6.10/debian/patches/series/2.6.10-4 2005-01-13 06:47:07 UTC (rev 2284)
@@ -13,3 +13,6 @@
- modular-vesafb.dpatch
+ modular-vesafb-3.dpatch
+ alpha-io-typo.dpatch
++ 033-rlimit_memlock_check.dpatch
++ 034-stack_resize_exploit.dpatch
++ 035-do_brk_security_fixes-2.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/changelog 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog 2005-01-13 06:47:07 UTC (rev 2284)
@@ -5,6 +5,21 @@
* Fix viewsvn url for patches in README.Debian as reported by
Alexander E. Patrakov. (Christoph Hellwig) (closes: #288062).
+
+ * [SECURITY] 033-rlimit_memlock_check.dpatch
+ RLIMIT_MEMLOCK isn't checked properly, allowing for a DoS attack.
+ See http://seclists.org/lists/fulldisclosure/2005/Jan/0270.html for
+ more details. This patch fixes it, and all reorganizes the stack resize
+ stuff a bit (*sigh*) (Andres Salomon).
+
+ * [SECURITY] 034-stack_resize_exploit.dpatch
+ Fix exploitable race condition on SMP and HT systems where two
+ threads attempt to expand the stack at the same time. This is
+ CAN-2005-0001 (happy new year!) (Andres Salomon).
+
+ * [SECURITY] 035-do_brk_security_fixes-2.dpatch
+ Further do_brk fixes; just to be safe, lock everywhere do_brk
+ is used (Andres Salomon).
-- Christoph Hellwig <hch@lst.de> Sat, 08 Jan 2005 13:38:12 +0100
Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/033-rlimit_memlock_check.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/033-rlimit_memlock_check.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/033-rlimit_memlock_check.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,182 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Clean up stack growth checks and move them into a common function.
+## DP: Patch author: torvalds@ppc970.osdl.org
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/10 11:23:42-08:00 torvalds@ppc970.osdl.org
+# Clean up stack growth checks and move them into a common function.
+#
+# The grows-up and grows-down cases had all the same issues, but
+# differered in the details. Additionlly, historical evolution of
+# the tests had caused the result to be pretty unreadable with some
+# rather long and complex conditionals.
+#
+# Fix it all up in a more readable helper function.
+#
+# This also adds the missing RLIMIT_MEMLOCK test.
+#
+# mm/mmap.c
+# 2005/01/10 11:23:35-08:00 torvalds@ppc970.osdl.org +61 -44
+# Clean up stack growth checks and move them into a common function.
+#
+# The grows-up and grows-down cases had all the same issues, but
+# differered in the details. Additionlly, historical evolution of
+# the tests had caused the result to be pretty unreadable with some
+# rather long and complex conditionals.
+#
+# Fix it all up in a more readable helper function.
+#
+# This also adds the missing RLIMIT_MEMLOCK test.
+#
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:21:10 -08:00
++++ b/mm/mmap.c 2005-01-12 20:21:10 -08:00
+@@ -1335,13 +1335,58 @@
+ return prev ? prev->vm_next : vma;
+ }
+
++/*
++ * Verify that the stack growth is acceptable and
++ * update accounting. This is shared with both the
++ * grow-up and grow-down cases.
++ */
++static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, unsigned long grow)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ struct rlimit *rlim = current->signal->rlim;
++
++ /* address space limit tests */
++ rlim = current->signal->rlim;
++ if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
++ return -ENOMEM;
++
++ /* Stack limit test */
++ if (size > rlim[RLIMIT_STACK].rlim_cur)
++ return -ENOMEM;
++
++ /* mlock limit tests */
++ if (vma->vm_flags & VM_LOCKED) {
++ unsigned long locked;
++ unsigned long limit;
++ locked = mm->locked_vm + grow;
++ limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
++ if (locked > limit)
++ return -ENOMEM;
++ }
++
++ /*
++ * Overcommit.. This must be the final test, as it will
++ * update security statistics.
++ */
++ if (security_vm_enough_memory(grow))
++ return -ENOMEM;
++
++ /* Ok, everything looks good - let it rip */
++ mm->total_vm += grow;
++ if (vma->vm_flags & VM_LOCKED)
++ mm->locked_vm += grow;
++ __vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
++ return 0;
++}
++
+ #ifdef CONFIG_STACK_GROWSUP
+ /*
+ * vma is the first one with address > vma->vm_end. Have to extend vma.
+ */
+ int expand_stack(struct vm_area_struct * vma, unsigned long address)
+ {
+- unsigned long grow;
++ int error;
++ unsigned long size, grow;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+@@ -1361,28 +1406,14 @@
+ */
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
++ size = address - vma->vm_start;
+ grow = (address - vma->vm_end) >> PAGE_SHIFT;
+
+- /* Overcommit.. */
+- if (security_vm_enough_memory(grow)) {
+- anon_vma_unlock(vma);
+- return -ENOMEM;
+- }
+-
+- if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
+- ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+- current->signal->rlim[RLIMIT_AS].rlim_cur) {
+- anon_vma_unlock(vma);
+- vm_unacct_memory(grow);
+- return -ENOMEM;
+- }
+- vma->vm_end = address;
+- vma->vm_mm->total_vm += grow;
+- if (vma->vm_flags & VM_LOCKED)
+- vma->vm_mm->locked_vm += grow;
+- __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
++ error = acct_stack_growth(vma, size, grow);
++ if (!error)
++ vma->vm_end = address;
+ anon_vma_unlock(vma);
+- return 0;
++ return error;
+ }
+
+ struct vm_area_struct *
+@@ -1409,7 +1440,8 @@
+ */
+ int expand_stack(struct vm_area_struct *vma, unsigned long address)
+ {
+- unsigned long grow;
++ int error;
++ unsigned long size, grow;
+
+ /*
+ * We must make sure the anon_vma is allocated
+@@ -1425,29 +1457,16 @@
+ * anon_vma lock to serialize against concurrent expand_stacks.
+ */
+ address &= PAGE_MASK;
++ size = vma->vm_end - address;
+ grow = (vma->vm_start - address) >> PAGE_SHIFT;
+
+- /* Overcommit.. */
+- if (security_vm_enough_memory(grow)) {
+- anon_vma_unlock(vma);
+- return -ENOMEM;
+- }
+-
+- if (vma->vm_end - address > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
+- ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+- current->signal->rlim[RLIMIT_AS].rlim_cur) {
+- anon_vma_unlock(vma);
+- vm_unacct_memory(grow);
+- return -ENOMEM;
++ error = acct_stack_growth(vma, size, grow);
++ if (!error) {
++ vma->vm_start = address;
++ vma->vm_pgoff -= grow;
+ }
+- vma->vm_start = address;
+- vma->vm_pgoff -= grow;
+- vma->vm_mm->total_vm += grow;
+- if (vma->vm_flags & VM_LOCKED)
+- vma->vm_mm->locked_vm += grow;
+- __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
+ anon_vma_unlock(vma);
+- return 0;
++ return error;
+ }
+
+ struct vm_area_struct *
Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/034-stack_resize_exploit.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/034-stack_resize_exploit.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/034-stack_resize_exploit.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,101 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Handle two threads both trying to expand their stack simultaneously.
+## DP: Patch author: torvalds@ppc970.osdl.org
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/12 08:09:20-08:00 torvalds@ppc970.osdl.org
+# Handle two threads both trying to expand their stack simultaneously.
+#
+# We had all the locking right, but we didn't check whether one of the
+# threads now no longer needed to expand, so we could incorrectly _shrink_
+# the stack in the other thread instead (not only causing segfaults, but
+# since we didn't do a proper unmap, we'd possibly leak pages too).
+#
+# So re-check the need for expand after getting the lock.
+#
+# Noticed by Paul Starzetz.
+#
+# mm/mmap.c
+# 2005/01/12 08:09:12-08:00 torvalds@ppc970.osdl.org +25 -13
+# Handle two threads both trying to expand their stack simultaneously.
+#
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:22:12 -08:00
++++ b/mm/mmap.c 2005-01-12 20:22:12 -08:00
+@@ -1475,7 +1475,6 @@
+ int expand_stack(struct vm_area_struct * vma, unsigned long address)
+ {
+ int error;
+- unsigned long size, grow;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+@@ -1495,12 +1494,19 @@
+ */
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
+- size = address - vma->vm_start;
+- grow = (address - vma->vm_end) >> PAGE_SHIFT;
++ error = 0;
+
+- error = acct_stack_growth(vma, size, grow);
+- if (!error)
+- vma->vm_end = address;
++ /* Somebody else might have raced and expanded it already */
++ if (address > vma->vm_end) {
++ unsigned long size, grow;
++
++ size = address - vma->vm_start;
++ grow = (address - vma->vm_end) >> PAGE_SHIFT;
++
++ error = acct_stack_growth(vma, size, grow);
++ if (!error)
++ vma->vm_end = address;
++ }
+ anon_vma_unlock(vma);
+ return error;
+ }
+@@ -1528,7 +1534,6 @@
+ int expand_stack(struct vm_area_struct *vma, unsigned long address)
+ {
+ int error;
+- unsigned long size, grow;
+
+ /*
+ * We must make sure the anon_vma is allocated
+@@ -1544,13 +1549,20 @@
+ * anon_vma lock to serialize against concurrent expand_stacks.
+ */
+ address &= PAGE_MASK;
+- size = vma->vm_end - address;
+- grow = (vma->vm_start - address) >> PAGE_SHIFT;
++ error = 0;
+
+- error = acct_stack_growth(vma, size, grow);
+- if (!error) {
+- vma->vm_start = address;
+- vma->vm_pgoff -= grow;
++ /* Somebody else might have raced and expanded it already */
++ if (address < vma->vm_start) {
++ unsigned long size, grow;
++
++ size = vma->vm_end - address;
++ grow = (vma->vm_start - address) >> PAGE_SHIFT;
++
++ error = acct_stack_growth(vma, size, grow);
++ if (!error) {
++ vma->vm_start = address;
++ vma->vm_pgoff -= grow;
++ }
+ }
+ anon_vma_unlock(vma);
+ return error;
Added: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/035-do_brk_security_fixes-2.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/035-do_brk_security_fixes-2.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/035-do_brk_security_fixes-2.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,334 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: [PATCH] do_brk() needs mmap_sem write-locked
+## DP: Patch author: marcelo.tosatti@cyclades.com
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/12 08:12:09-08:00 marcelo.tosatti@cyclades.com
+# [PATCH] do_brk() needs mmap_sem write-locked
+#
+# It seems to be general consensus that its safer to require all do_brk() callers
+# to grab mmap_sem, and have do_brk to warn otherwise. This is what the following
+# patch does.
+#
+# Similar version has been changed to in v2.4.
+#
+# Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+#
+# arch/mips/kernel/irixelf.c
+# 2005/01/11 17:35:36-08:00 marcelo.tosatti@cyclades.com +10 -1
+# do_brk() needs mmap_sem write-locked
+#
+# arch/sparc64/kernel/binfmt_aout32.c
+# 2005/01/11 17:37:28-08:00 marcelo.tosatti@cyclades.com +12 -0
+# do_brk() needs mmap_sem write-locked
+#
+# arch/x86_64/ia32/ia32_aout.c
+# 2005/01/11 17:34:26-08:00 marcelo.tosatti@cyclades.com +11 -1
+# do_brk() needs mmap_sem write-locked
+#
+# fs/binfmt_aout.c
+# 2005/01/11 17:31:51-08:00 marcelo.tosatti@cyclades.com +14 -3
+# do_brk() needs mmap_sem write-locked
+#
+# fs/binfmt_elf.c
+# 2005/01/11 18:07:01-08:00 marcelo.tosatti@cyclades.com +11 -1
+# do_brk() needs mmap_sem write-locked
+#
+# mm/mmap.c
+# 2005/01/11 17:43:11-08:00 marcelo.tosatti@cyclades.com +6 -0
+# do_brk() needs mmap_sem write-locked
+#
+diff -Nru a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
+--- a/arch/mips/kernel/irixelf.c 2005-01-12 20:26:27 -08:00
++++ b/arch/mips/kernel/irixelf.c 2005-01-12 20:26:27 -08:00
+@@ -127,7 +127,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+
+@@ -375,7 +377,9 @@
+
+ /* Map the last of the bss segment */
+ if (last_bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ do_brk(len, (last_bss - len));
++ up_write(¤t->mm->mmap_sem);
+ }
+ kfree(elf_phdata);
+
+@@ -562,7 +566,9 @@
+ unsigned long v;
+ struct prda *pp;
+
++ down_write(¤t->mm->mmap_sem);
+ v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
++ up_write(¤t->mm->mmap_sem);
+
+ if (v < 0)
+ return;
+@@ -852,8 +858,11 @@
+
+ len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
+ bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
+- if (bss > len)
++ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ do_brk(len, bss-len);
++ up_write(¤t->mm->mmap_sem);
++ }
+ kfree(elf_phdata);
+ return 0;
+ }
+diff -Nru a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
+--- a/arch/sparc64/kernel/binfmt_aout32.c 2005-01-12 20:26:27 -08:00
++++ b/arch/sparc64/kernel/binfmt_aout32.c 2005-01-12 20:26:27 -08:00
+@@ -49,7 +49,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+ /*
+@@ -246,10 +248,14 @@
+ if (N_MAGIC(ex) == NMAGIC) {
+ loff_t pos = fd_offset;
+ /* Fuck me plenty... */
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_TXTADDR(ex), ex.a_text);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+ ex.a_text, &pos);
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_DATADDR(ex), ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
+ ex.a_data, &pos);
+ goto beyond_if;
+@@ -257,8 +263,10 @@
+
+ if (N_MAGIC(ex) == OMAGIC) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex) & PAGE_MASK,
+ ex.a_text+ex.a_data + PAGE_SIZE - 1);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+ } else {
+@@ -272,7 +280,9 @@
+
+ if (!bprm->file->f_op->mmap) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(0, ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+@@ -389,7 +399,9 @@
+ len = PAGE_ALIGN(ex.a_text + ex.a_data);
+ bss = ex.a_text + ex.a_data + ex.a_bss;
+ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(start_addr + len, bss - len);
++ up_write(¤t->mm->mmap_sem);
+ retval = error;
+ if (error != start_addr + len)
+ goto out;
+diff -Nru a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
+--- a/arch/x86_64/ia32/ia32_aout.c 2005-01-12 20:26:27 -08:00
++++ b/arch/x86_64/ia32/ia32_aout.c 2005-01-12 20:26:27 -08:00
+@@ -115,7 +115,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+ #if CORE_DUMP
+@@ -325,7 +327,10 @@
+ pos = 32;
+ map_size = ex.a_text+ex.a_data;
+
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(text_addr & PAGE_MASK, map_size);
++ up_write(¤t->mm->mmap_sem);
++
+ if (error != (text_addr & PAGE_MASK)) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+@@ -361,7 +366,9 @@
+
+ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+ flush_icache_range((unsigned long) N_TXTADDR(ex),
+@@ -469,8 +476,9 @@
+ error_time = jiffies;
+ }
+ #endif
+-
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
++ up_write(¤t->mm->mmap_sem);
+
+ file->f_op->read(file, (char *)start_addr,
+ ex.a_text + ex.a_data, &pos);
+@@ -494,7 +502,9 @@
+ len = PAGE_ALIGN(ex.a_text + ex.a_data);
+ bss = ex.a_text + ex.a_data + ex.a_bss;
+ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(start_addr + len, bss - len);
++ up_write(¤t->mm->mmap_sem);
+ retval = error;
+ if (error != start_addr + len)
+ goto out;
+diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
+--- a/fs/binfmt_aout.c 2005-01-12 20:26:27 -08:00
++++ b/fs/binfmt_aout.c 2005-01-12 20:26:27 -08:00
+@@ -50,7 +50,10 @@
+ start = PAGE_ALIGN(start);
+ end = PAGE_ALIGN(end);
+ if (end > start) {
+- unsigned long addr = do_brk(start, end - start);
++ unsigned long addr;
++ down_write(¤t->mm->mmap_sem);
++ addr = do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+@@ -323,10 +326,14 @@
+ loff_t pos = fd_offset;
+ /* Fuck me plenty... */
+ /* <AOL></AOL> */
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_TXTADDR(ex), ex.a_text);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
+ ex.a_text, &pos);
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_DATADDR(ex), ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
+ ex.a_data, &pos);
+ goto beyond_if;
+@@ -346,8 +353,9 @@
+ pos = 32;
+ map_size = ex.a_text+ex.a_data;
+ #endif
+-
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(text_addr & PAGE_MASK, map_size);
++ up_write(¤t->mm->mmap_sem);
+ if (error != (text_addr & PAGE_MASK)) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+@@ -382,7 +390,9 @@
+
+ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+@@ -487,8 +497,9 @@
+ file->f_dentry->d_name.name);
+ error_time = jiffies;
+ }
+-
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
++ up_write(¤t->mm->mmap_sem);
+
+ file->f_op->read(file, (char __user *)start_addr,
+ ex.a_text + ex.a_data, &pos);
+diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+--- a/fs/binfmt_elf.c 2005-01-12 20:26:27 -08:00
++++ b/fs/binfmt_elf.c 2005-01-12 20:26:27 -08:00
+@@ -88,7 +88,10 @@
+ start = ELF_PAGEALIGN(start);
+ end = ELF_PAGEALIGN(end);
+ if (end > start) {
+- unsigned long addr = do_brk(start, end - start);
++ unsigned long addr;
++ down_write(¤t->mm->mmap_sem);
++ addr = do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+@@ -409,7 +412,9 @@
+
+ /* Map the last of the bss segment */
+ if (last_bss > elf_bss) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(elf_bss, last_bss - elf_bss);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(error))
+ goto out_close;
+ }
+@@ -449,7 +454,9 @@
+ goto out;
+ }
+
++ down_write(¤t->mm->mmap_sem);
+ do_brk(0, text_data);
++ up_write(¤t->mm->mmap_sem);
+ if (!interpreter->f_op || !interpreter->f_op->read)
+ goto out;
+ if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
+@@ -457,8 +464,11 @@
+ flush_icache_range((unsigned long)addr,
+ (unsigned long)addr + text_data);
+
++
++ down_write(¤t->mm->mmap_sem);
+ do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
+ interp_ex->a_bss);
++ up_write(¤t->mm->mmap_sem);
+ elf_entry = interp_ex->a_entry;
+
+ out:
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:26:27 -08:00
++++ b/mm/mmap.c 2005-01-12 20:26:27 -08:00
+@@ -1903,6 +1903,12 @@
+ }
+
+ /*
++ * mm->mmap_sem is required to protect against another thread
++ * changing the mappings in case we sleep.
++ */
++ WARN_ON(down_read_trylock(&mm->mmap_sem));
++
++ /*
+ * Clear old maps. this also does some error checking for us
+ */
+ munmap_back:
Modified: trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-13
===================================================================
--- trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-13 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-13 2005-01-13 06:47:07 UTC (rev 2284)
@@ -1,3 +1,6 @@
+ scsi-blacklist-2.dpatch
- smbfs-overflow-fixes.dpatch
+ smbfs-overflow-fixes-2.dpatch
++ 033-rlimit_memlock_check.dpatch
++ 034-stack_resize_exploit.dpatch
++ 035-do_brk_security_fixes-2.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 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/changelog 2005-01-13 06:47:07 UTC (rev 2284)
@@ -1,3 +1,22 @@
+kernel-source-2.6.9 (2.6.9-5) UNRELEASED; urgency=low
+
+ * [SECURITY] 033-rlimit_memlock_check.dpatch
+ RLIMIT_MEMLOCK isn't checked properly, allowing for a DoS attack.
+ See http://seclists.org/lists/fulldisclosure/2005/Jan/0270.html for
+ more details. This patch fixes it, and all reorganizes the stack resize
+ stuff a bit (*sigh*) (Andres Salomon).
+
+ * [SECURITY] 034-stack_resize_exploit.dpatch
+ Fix exploitable race condition on SMP and HT systems where two
+ threads attempt to expand the stack at the same time. This is
+ CAN-2005-0001 (happy new year!) (Andres Salomon).
+
+ * [SECURITY] 035-do_brk_security_fixes-2.dpatch
+ Further do_brk fixes; just to be safe, lock everywhere do_brk
+ is used (Andres Salomon).
+
+ -- Andres Salomon <dilinger@voxel.net> Thu, 13 Jan 2005 01:50:48 -0500
+
kernel-source-2.6.9 (2.6.9-5) unstable; urgency=low
* [powerpc] Added a couple of powermac patches from Benjamin Herrenschmidt :
Added: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/033-rlimit_memlock_check.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/033-rlimit_memlock_check.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/033-rlimit_memlock_check.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,182 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Clean up stack growth checks and move them into a common function.
+## DP: Patch author: torvalds@ppc970.osdl.org
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/10 11:23:42-08:00 torvalds@ppc970.osdl.org
+# Clean up stack growth checks and move them into a common function.
+#
+# The grows-up and grows-down cases had all the same issues, but
+# differered in the details. Additionlly, historical evolution of
+# the tests had caused the result to be pretty unreadable with some
+# rather long and complex conditionals.
+#
+# Fix it all up in a more readable helper function.
+#
+# This also adds the missing RLIMIT_MEMLOCK test.
+#
+# mm/mmap.c
+# 2005/01/10 11:23:35-08:00 torvalds@ppc970.osdl.org +61 -44
+# Clean up stack growth checks and move them into a common function.
+#
+# The grows-up and grows-down cases had all the same issues, but
+# differered in the details. Additionlly, historical evolution of
+# the tests had caused the result to be pretty unreadable with some
+# rather long and complex conditionals.
+#
+# Fix it all up in a more readable helper function.
+#
+# This also adds the missing RLIMIT_MEMLOCK test.
+#
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:21:10 -08:00
++++ b/mm/mmap.c 2005-01-12 20:21:10 -08:00
+@@ -1335,13 +1335,58 @@
+ return prev ? prev->vm_next : vma;
+ }
+
++/*
++ * Verify that the stack growth is acceptable and
++ * update accounting. This is shared with both the
++ * grow-up and grow-down cases.
++ */
++static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, unsigned long grow)
++{
++ struct mm_struct *mm = vma->vm_mm;
++ struct rlimit *rlim = current->signal->rlim;
++
++ /* address space limit tests */
++ rlim = current->signal->rlim;
++ if (mm->total_vm + grow > rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT)
++ return -ENOMEM;
++
++ /* Stack limit test */
++ if (size > rlim[RLIMIT_STACK].rlim_cur)
++ return -ENOMEM;
++
++ /* mlock limit tests */
++ if (vma->vm_flags & VM_LOCKED) {
++ unsigned long locked;
++ unsigned long limit;
++ locked = mm->locked_vm + grow;
++ limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
++ if (locked > limit)
++ return -ENOMEM;
++ }
++
++ /*
++ * Overcommit.. This must be the final test, as it will
++ * update security statistics.
++ */
++ if (security_vm_enough_memory(grow))
++ return -ENOMEM;
++
++ /* Ok, everything looks good - let it rip */
++ mm->total_vm += grow;
++ if (vma->vm_flags & VM_LOCKED)
++ mm->locked_vm += grow;
++ __vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
++ return 0;
++}
++
+ #ifdef CONFIG_STACK_GROWSUP
+ /*
+ * vma is the first one with address > vma->vm_end. Have to extend vma.
+ */
+ int expand_stack(struct vm_area_struct * vma, unsigned long address)
+ {
+- unsigned long grow;
++ int error;
++ unsigned long size, grow;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+@@ -1361,28 +1406,14 @@
+ */
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
++ size = address - vma->vm_start;
+ grow = (address - vma->vm_end) >> PAGE_SHIFT;
+
+- /* Overcommit.. */
+- if (security_vm_enough_memory(grow)) {
+- anon_vma_unlock(vma);
+- return -ENOMEM;
+- }
+-
+- if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
+- ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+- current->signal->rlim[RLIMIT_AS].rlim_cur) {
+- anon_vma_unlock(vma);
+- vm_unacct_memory(grow);
+- return -ENOMEM;
+- }
+- vma->vm_end = address;
+- vma->vm_mm->total_vm += grow;
+- if (vma->vm_flags & VM_LOCKED)
+- vma->vm_mm->locked_vm += grow;
+- __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
++ error = acct_stack_growth(vma, size, grow);
++ if (!error)
++ vma->vm_end = address;
+ anon_vma_unlock(vma);
+- return 0;
++ return error;
+ }
+
+ struct vm_area_struct *
+@@ -1409,7 +1440,8 @@
+ */
+ int expand_stack(struct vm_area_struct *vma, unsigned long address)
+ {
+- unsigned long grow;
++ int error;
++ unsigned long size, grow;
+
+ /*
+ * We must make sure the anon_vma is allocated
+@@ -1425,29 +1457,16 @@
+ * anon_vma lock to serialize against concurrent expand_stacks.
+ */
+ address &= PAGE_MASK;
++ size = vma->vm_end - address;
+ grow = (vma->vm_start - address) >> PAGE_SHIFT;
+
+- /* Overcommit.. */
+- if (security_vm_enough_memory(grow)) {
+- anon_vma_unlock(vma);
+- return -ENOMEM;
+- }
+-
+- if (vma->vm_end - address > current->signal->rlim[RLIMIT_STACK].rlim_cur ||
+- ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+- current->signal->rlim[RLIMIT_AS].rlim_cur) {
+- anon_vma_unlock(vma);
+- vm_unacct_memory(grow);
+- return -ENOMEM;
++ error = acct_stack_growth(vma, size, grow);
++ if (!error) {
++ vma->vm_start = address;
++ vma->vm_pgoff -= grow;
+ }
+- vma->vm_start = address;
+- vma->vm_pgoff -= grow;
+- vma->vm_mm->total_vm += grow;
+- if (vma->vm_flags & VM_LOCKED)
+- vma->vm_mm->locked_vm += grow;
+- __vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
+ anon_vma_unlock(vma);
+- return 0;
++ return error;
+ }
+
+ struct vm_area_struct *
Added: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/034-stack_resize_exploit.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/034-stack_resize_exploit.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/034-stack_resize_exploit.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,101 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: Handle two threads both trying to expand their stack simultaneously.
+## DP: Patch author: torvalds@ppc970.osdl.org
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/12 08:09:20-08:00 torvalds@ppc970.osdl.org
+# Handle two threads both trying to expand their stack simultaneously.
+#
+# We had all the locking right, but we didn't check whether one of the
+# threads now no longer needed to expand, so we could incorrectly _shrink_
+# the stack in the other thread instead (not only causing segfaults, but
+# since we didn't do a proper unmap, we'd possibly leak pages too).
+#
+# So re-check the need for expand after getting the lock.
+#
+# Noticed by Paul Starzetz.
+#
+# mm/mmap.c
+# 2005/01/12 08:09:12-08:00 torvalds@ppc970.osdl.org +25 -13
+# Handle two threads both trying to expand their stack simultaneously.
+#
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:22:12 -08:00
++++ b/mm/mmap.c 2005-01-12 20:22:12 -08:00
+@@ -1475,7 +1475,6 @@
+ int expand_stack(struct vm_area_struct * vma, unsigned long address)
+ {
+ int error;
+- unsigned long size, grow;
+
+ if (!(vma->vm_flags & VM_GROWSUP))
+ return -EFAULT;
+@@ -1495,12 +1494,19 @@
+ */
+ address += 4 + PAGE_SIZE - 1;
+ address &= PAGE_MASK;
+- size = address - vma->vm_start;
+- grow = (address - vma->vm_end) >> PAGE_SHIFT;
++ error = 0;
+
+- error = acct_stack_growth(vma, size, grow);
+- if (!error)
+- vma->vm_end = address;
++ /* Somebody else might have raced and expanded it already */
++ if (address > vma->vm_end) {
++ unsigned long size, grow;
++
++ size = address - vma->vm_start;
++ grow = (address - vma->vm_end) >> PAGE_SHIFT;
++
++ error = acct_stack_growth(vma, size, grow);
++ if (!error)
++ vma->vm_end = address;
++ }
+ anon_vma_unlock(vma);
+ return error;
+ }
+@@ -1528,7 +1534,6 @@
+ int expand_stack(struct vm_area_struct *vma, unsigned long address)
+ {
+ int error;
+- unsigned long size, grow;
+
+ /*
+ * We must make sure the anon_vma is allocated
+@@ -1544,13 +1549,20 @@
+ * anon_vma lock to serialize against concurrent expand_stacks.
+ */
+ address &= PAGE_MASK;
+- size = vma->vm_end - address;
+- grow = (vma->vm_start - address) >> PAGE_SHIFT;
++ error = 0;
+
+- error = acct_stack_growth(vma, size, grow);
+- if (!error) {
+- vma->vm_start = address;
+- vma->vm_pgoff -= grow;
++ /* Somebody else might have raced and expanded it already */
++ if (address < vma->vm_start) {
++ unsigned long size, grow;
++
++ size = vma->vm_end - address;
++ grow = (vma->vm_start - address) >> PAGE_SHIFT;
++
++ error = acct_stack_growth(vma, size, grow);
++ if (!error) {
++ vma->vm_start = address;
++ vma->vm_pgoff -= grow;
++ }
+ }
+ anon_vma_unlock(vma);
+ return error;
Added: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/035-do_brk_security_fixes-2.dpatch
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/035-do_brk_security_fixes-2.dpatch 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/035-do_brk_security_fixes-2.dpatch 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,334 @@
+#! /bin/sh -e
+## <PATCHNAME>.dpatch by <PATCH_AUTHOR@EMAI>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Description: [PATCH] do_brk() needs mmap_sem write-locked
+## DP: Patch author: marcelo.tosatti@cyclades.com
+## DP: Upstream status: backported
+
+. $(dirname $0)/DPATCH
+
+@DPATCH@
+# This is a BitKeeper generated diff -Nru style patch.
+#
+# ChangeSet
+# 2005/01/12 08:12:09-08:00 marcelo.tosatti@cyclades.com
+# [PATCH] do_brk() needs mmap_sem write-locked
+#
+# It seems to be general consensus that its safer to require all do_brk() callers
+# to grab mmap_sem, and have do_brk to warn otherwise. This is what the following
+# patch does.
+#
+# Similar version has been changed to in v2.4.
+#
+# Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+#
+# arch/mips/kernel/irixelf.c
+# 2005/01/11 17:35:36-08:00 marcelo.tosatti@cyclades.com +10 -1
+# do_brk() needs mmap_sem write-locked
+#
+# arch/sparc64/kernel/binfmt_aout32.c
+# 2005/01/11 17:37:28-08:00 marcelo.tosatti@cyclades.com +12 -0
+# do_brk() needs mmap_sem write-locked
+#
+# arch/x86_64/ia32/ia32_aout.c
+# 2005/01/11 17:34:26-08:00 marcelo.tosatti@cyclades.com +11 -1
+# do_brk() needs mmap_sem write-locked
+#
+# fs/binfmt_aout.c
+# 2005/01/11 17:31:51-08:00 marcelo.tosatti@cyclades.com +14 -3
+# do_brk() needs mmap_sem write-locked
+#
+# fs/binfmt_elf.c
+# 2005/01/11 18:07:01-08:00 marcelo.tosatti@cyclades.com +11 -1
+# do_brk() needs mmap_sem write-locked
+#
+# mm/mmap.c
+# 2005/01/11 17:43:11-08:00 marcelo.tosatti@cyclades.com +6 -0
+# do_brk() needs mmap_sem write-locked
+#
+diff -Nru a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
+--- a/arch/mips/kernel/irixelf.c 2005-01-12 20:26:27 -08:00
++++ b/arch/mips/kernel/irixelf.c 2005-01-12 20:26:27 -08:00
+@@ -127,7 +127,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+
+@@ -375,7 +377,9 @@
+
+ /* Map the last of the bss segment */
+ if (last_bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ do_brk(len, (last_bss - len));
++ up_write(¤t->mm->mmap_sem);
+ }
+ kfree(elf_phdata);
+
+@@ -562,7 +566,9 @@
+ unsigned long v;
+ struct prda *pp;
+
++ down_write(¤t->mm->mmap_sem);
+ v = do_brk (PRDA_ADDRESS, PAGE_SIZE);
++ up_write(¤t->mm->mmap_sem);
+
+ if (v < 0)
+ return;
+@@ -852,8 +858,11 @@
+
+ len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
+ bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
+- if (bss > len)
++ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ do_brk(len, bss-len);
++ up_write(¤t->mm->mmap_sem);
++ }
+ kfree(elf_phdata);
+ return 0;
+ }
+diff -Nru a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
+--- a/arch/sparc64/kernel/binfmt_aout32.c 2005-01-12 20:26:27 -08:00
++++ b/arch/sparc64/kernel/binfmt_aout32.c 2005-01-12 20:26:27 -08:00
+@@ -49,7 +49,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+ /*
+@@ -246,10 +248,14 @@
+ if (N_MAGIC(ex) == NMAGIC) {
+ loff_t pos = fd_offset;
+ /* Fuck me plenty... */
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_TXTADDR(ex), ex.a_text);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+ ex.a_text, &pos);
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_DATADDR(ex), ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex),
+ ex.a_data, &pos);
+ goto beyond_if;
+@@ -257,8 +263,10 @@
+
+ if (N_MAGIC(ex) == OMAGIC) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex) & PAGE_MASK,
+ ex.a_text+ex.a_data + PAGE_SIZE - 1);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+ } else {
+@@ -272,7 +280,9 @@
+
+ if (!bprm->file->f_op->mmap) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(0, ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+@@ -389,7 +399,9 @@
+ len = PAGE_ALIGN(ex.a_text + ex.a_data);
+ bss = ex.a_text + ex.a_data + ex.a_bss;
+ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(start_addr + len, bss - len);
++ up_write(¤t->mm->mmap_sem);
+ retval = error;
+ if (error != start_addr + len)
+ goto out;
+diff -Nru a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
+--- a/arch/x86_64/ia32/ia32_aout.c 2005-01-12 20:26:27 -08:00
++++ b/arch/x86_64/ia32/ia32_aout.c 2005-01-12 20:26:27 -08:00
+@@ -115,7 +115,9 @@
+ end = PAGE_ALIGN(end);
+ if (end <= start)
+ return;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ }
+
+ #if CORE_DUMP
+@@ -325,7 +327,10 @@
+ pos = 32;
+ map_size = ex.a_text+ex.a_data;
+
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(text_addr & PAGE_MASK, map_size);
++ up_write(¤t->mm->mmap_sem);
++
+ if (error != (text_addr & PAGE_MASK)) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+@@ -361,7 +366,9 @@
+
+ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+ flush_icache_range((unsigned long) N_TXTADDR(ex),
+@@ -469,8 +476,9 @@
+ error_time = jiffies;
+ }
+ #endif
+-
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
++ up_write(¤t->mm->mmap_sem);
+
+ file->f_op->read(file, (char *)start_addr,
+ ex.a_text + ex.a_data, &pos);
+@@ -494,7 +502,9 @@
+ len = PAGE_ALIGN(ex.a_text + ex.a_data);
+ bss = ex.a_text + ex.a_data + ex.a_bss;
+ if (bss > len) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(start_addr + len, bss - len);
++ up_write(¤t->mm->mmap_sem);
+ retval = error;
+ if (error != start_addr + len)
+ goto out;
+diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c
+--- a/fs/binfmt_aout.c 2005-01-12 20:26:27 -08:00
++++ b/fs/binfmt_aout.c 2005-01-12 20:26:27 -08:00
+@@ -50,7 +50,10 @@
+ start = PAGE_ALIGN(start);
+ end = PAGE_ALIGN(end);
+ if (end > start) {
+- unsigned long addr = do_brk(start, end - start);
++ unsigned long addr;
++ down_write(¤t->mm->mmap_sem);
++ addr = do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+@@ -323,10 +326,14 @@
+ loff_t pos = fd_offset;
+ /* Fuck me plenty... */
+ /* <AOL></AOL> */
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_TXTADDR(ex), ex.a_text);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
+ ex.a_text, &pos);
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(N_DATADDR(ex), ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
+ ex.a_data, &pos);
+ goto beyond_if;
+@@ -346,8 +353,9 @@
+ pos = 32;
+ map_size = ex.a_text+ex.a_data;
+ #endif
+-
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(text_addr & PAGE_MASK, map_size);
++ up_write(¤t->mm->mmap_sem);
+ if (error != (text_addr & PAGE_MASK)) {
+ send_sig(SIGKILL, current, 0);
+ return error;
+@@ -382,7 +390,9 @@
+
+ if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
+ loff_t pos = fd_offset;
++ down_write(¤t->mm->mmap_sem);
+ do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
++ up_write(¤t->mm->mmap_sem);
+ bprm->file->f_op->read(bprm->file,
+ (char __user *)N_TXTADDR(ex),
+ ex.a_text+ex.a_data, &pos);
+@@ -487,8 +497,9 @@
+ file->f_dentry->d_name.name);
+ error_time = jiffies;
+ }
+-
++ down_write(¤t->mm->mmap_sem);
+ do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
++ up_write(¤t->mm->mmap_sem);
+
+ file->f_op->read(file, (char __user *)start_addr,
+ ex.a_text + ex.a_data, &pos);
+diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
+--- a/fs/binfmt_elf.c 2005-01-12 20:26:27 -08:00
++++ b/fs/binfmt_elf.c 2005-01-12 20:26:27 -08:00
+@@ -88,7 +88,10 @@
+ start = ELF_PAGEALIGN(start);
+ end = ELF_PAGEALIGN(end);
+ if (end > start) {
+- unsigned long addr = do_brk(start, end - start);
++ unsigned long addr;
++ down_write(¤t->mm->mmap_sem);
++ addr = do_brk(start, end - start);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(addr))
+ return addr;
+ }
+@@ -409,7 +412,9 @@
+
+ /* Map the last of the bss segment */
+ if (last_bss > elf_bss) {
++ down_write(¤t->mm->mmap_sem);
+ error = do_brk(elf_bss, last_bss - elf_bss);
++ up_write(¤t->mm->mmap_sem);
+ if (BAD_ADDR(error))
+ goto out_close;
+ }
+@@ -449,7 +454,9 @@
+ goto out;
+ }
+
++ down_write(¤t->mm->mmap_sem);
+ do_brk(0, text_data);
++ up_write(¤t->mm->mmap_sem);
+ if (!interpreter->f_op || !interpreter->f_op->read)
+ goto out;
+ if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
+@@ -457,8 +464,11 @@
+ flush_icache_range((unsigned long)addr,
+ (unsigned long)addr + text_data);
+
++
++ down_write(¤t->mm->mmap_sem);
+ do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
+ interp_ex->a_bss);
++ up_write(¤t->mm->mmap_sem);
+ elf_entry = interp_ex->a_entry;
+
+ out:
+diff -Nru a/mm/mmap.c b/mm/mmap.c
+--- a/mm/mmap.c 2005-01-12 20:26:27 -08:00
++++ b/mm/mmap.c 2005-01-12 20:26:27 -08:00
+@@ -1903,6 +1903,12 @@
+ }
+
+ /*
++ * mm->mmap_sem is required to protect against another thread
++ * changing the mappings in case we sleep.
++ */
++ WARN_ON(down_read_trylock(&mm->mmap_sem));
++
++ /*
+ * Clear old maps. this also does some error checking for us
+ */
+ munmap_back:
Added: trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-6
===================================================================
--- trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-6 2005-01-12 18:54:32 UTC (rev 2283)
+++ trunk/kernel/source/kernel-source-2.6.9-2.6.9/debian/patches/series/2.6.9-6 2005-01-13 06:47:07 UTC (rev 2284)
@@ -0,0 +1,3 @@
++ 033-rlimit_memlock_check.dpatch
++ 034-stack_resize_exploit.dpatch
++ 035-do_brk_security_fixes-2.dpatch