[kernel] r8019 - in dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian: . patches patches/series

Dann Frazier dannf at alioth.debian.org
Sat Dec 16 08:14:21 UTC 2006


Author: dannf
Date: Sat Dec 16 09:14:20 2006
New Revision: 8019

Added:
   dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/mincore-fixes.dpatch
   dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/mincore_hang.dpatch
   dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-16sarge7
Modified:
   dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
Log:
* mincore_hang.dpatch
  [SECURITY] Fix a potential deadlock in mincore, thanks to Marcel
  Holtmann for the patch.
  See CVE-2006-4814
* mincore-fixes.dpatch
  This patch includes a few fixes, necessary for mincore_hang.dpatch to
  apply cleanly.

Modified: dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog
==============================================================================
--- dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog	(original)
+++ dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/changelog	Sat Dec 16 09:14:20 2006
@@ -1,3 +1,15 @@
+kernel-source-2.6.8 (2.6.8-16sarge7) UNRELEASED; urgency=high
+
+  * mincore_hang.dpatch
+    [SECURITY] Fix a potential deadlock in mincore, thanks to Marcel
+    Holtmann for the patch.
+    See CVE-2006-4814
+  * mincore-fixes.dpatch
+    This patch includes a few fixes, necessary for mincore_hang.dpatch to
+    apply cleanly.
+
+ -- dann frazier <dannf at debian.org>  Sat, 16 Dec 2006 01:06:51 -0700
+
 kernel-source-2.6.8 (2.6.8-16sarge6) stable-security; urgency=high
 
   * perfmon-fd-refcnt.dpatch

Added: dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/mincore-fixes.dpatch
==============================================================================
--- (empty file)
+++ dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/mincore-fixes.dpatch	Sat Dec 16 09:14:20 2006
@@ -0,0 +1,107 @@
+From: dhowells <dhowells>
+Date: Fri, 11 Feb 2005 19:01:29 +0000 (+0000)
+Subject: [PATCH] Fix the mincore() syscall
+X-Git-Tag: v2.6.11-rc4
+X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;a=commitdiff;h=64b287cfdd0e37c48579f6ba95ab4fcc576914ee
+
+[PATCH] Fix the mincore() syscall
+
+This fixes the mincore syscall in three ways:
+
+ (1) It moves as much argument checking outside of the semaphore-holding
+     region as possible.
+
+ (2) It checks the region parameters against TASK_SIZE so that a 32-bit binary
+     on a 64-bit platform will get the right error when calling this syscall
+     on a region that overlaps the end of the 32-bit address space.
+
+ (3) It tidies up the VMA checking loop a little.
+
+Signed-Off-By: David Howells <dhowells at redhat.com>
+Signed-Off-By: Linus Torvalds <torvalds at osdl.org>
+
+BKrev: 420d0109S65n5it9qSqkG144z7vKhg
+---
+
+--- a/mm/mincore.c
++++ b/mm/mincore.c
+@@ -109,39 +109,45 @@ asmlinkage long sys_mincore(unsigned lon
+ 	unsigned char __user * vec)
+ {
+ 	int index = 0;
+-	unsigned long end;
++	unsigned long end, limit;
+ 	struct vm_area_struct * vma;
++	size_t max;
+ 	int unmapped_error = 0;
+-	long error = -EINVAL;
++	long error;
+ 
+-	down_read(&current->mm->mmap_sem);
++	/* check the arguments */
++ 	if (start & ~PAGE_CACHE_MASK)
++		goto einval;
++
++	if (start < FIRST_USER_PGD_NR * PGDIR_SIZE)
++		goto enomem;
++
++	limit = TASK_SIZE;
++	if (start >= limit)
++		goto enomem;
++
++	max = limit - start;
++	len = PAGE_CACHE_ALIGN(len);
++	if (len > max)
++		goto einval;
+ 
+-	if (start & ~PAGE_CACHE_MASK)
+-		goto out;
+-	len = (len + ~PAGE_CACHE_MASK) & PAGE_CACHE_MASK;
+ 	end = start + len;
+-	if (end < start)
+-		goto out;
+ 
++	/* check the output buffer whilst holding the lock */
+ 	error = -EFAULT;
+-	if (!access_ok(VERIFY_WRITE, vec, len >> PAGE_SHIFT))
+-		goto out;
++	down_read(&current->mm->mmap_sem);
+ 
+-	error = 0;
+-	if (end == start)
++	if (!access_ok(VERIFY_WRITE, vec, len >> PAGE_SHIFT))
+ 		goto out;
+ 
+ 	/*
+ 	 * If the interval [start,end) covers some unmapped address
+ 	 * ranges, just ignore them, but return -ENOMEM at the end.
+ 	 */
+-	vma = find_vma(current->mm, start);
+-	for (;;) {
+-		/* Still start < end. */
+-		error = -ENOMEM;
+-		if (!vma)
+-			goto out;
++	error = 0;
+ 
++	vma = find_vma(current->mm, start);
++	while (vma) {
+ 		/* Here start < vma->vm_end. */
+ 		if (start < vma->vm_start) {
+ 			unmapped_error = -ENOMEM;
+@@ -169,7 +175,15 @@ asmlinkage long sys_mincore(unsigned lon
+ 		vma = vma->vm_next;
+ 	}
+ 
++	/* we found a hole in the area queried if we arrive here */
++	error = -ENOMEM;
++
+ out:
+ 	up_read(&current->mm->mmap_sem);
+ 	return error;
++
++einval:
++	return -EINVAL;
++enomem:
++	return -ENOMEM;
+ }

Added: dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/mincore_hang.dpatch
==============================================================================
--- (empty file)
+++ dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/mincore_hang.dpatch	Sat Dec 16 09:14:20 2006
@@ -0,0 +1,187 @@
+Updated patch.  Dave's earlier comment made me realize there was a
+rather sinister overflow problem in my earlier patch.  This one was
+tested in much more depth with a simple mincore test that called mincore
+for a very large address space (i.e. more than PAGE_SIZE pages long).
+
+--- linux-2.6.9/mm/mincore.c.orig	2006-09-19 15:04:01.000000000 -0400
++++ linux-2.6.9/mm/mincore.c	2006-09-20 11:44:35.000000000 -0400
+@@ -38,10 +38,9 @@
+ }
+ 
+ static long mincore_vma(struct vm_area_struct * vma,
+-	unsigned long start, unsigned long end, unsigned char __user * vec)
++	unsigned long start, unsigned long end, char * vec)
+ {
+-	long error, i, remaining;
+-	unsigned char * tmp;
++	long error, j, pages;
+ 
+ 	error = -ENOMEM;
+ 	if (!vma->vm_file)
+@@ -52,30 +51,13 @@
+ 		end = vma->vm_end;
+ 	end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
+ 
+-	error = -EAGAIN;
+-	tmp = (unsigned char *) __get_free_page(GFP_KERNEL);
+-	if (!tmp)
+-		return error;
+-
+-	/* (end - start) is # of pages, and also # of bytes in "vec */
+-	remaining = (end - start),
+-
+ 	error = 0;
+-	for (i = 0; remaining > 0; remaining -= PAGE_SIZE, i++) {
+-		int j = 0;
+-		long thispiece = (remaining < PAGE_SIZE) ?
+-						remaining : PAGE_SIZE;
+-
+-		while (j < thispiece)
+-			tmp[j++] = mincore_page(vma, start++);
+-
+-		if (copy_to_user(vec + PAGE_SIZE * i, tmp, thispiece)) {
+-			error = -EFAULT;
+-			break;
+-		}
+-	}
++	pages = end-start;
++	BUG_ON(pages > PAGE_SIZE);
++
++	for (j=0; j < pages; j++)
++		vec[j] = mincore_page(vma, start++);
+ 
+-	free_page((unsigned long) tmp);
+ 	return error;
+ }
+ 
+@@ -108,11 +90,11 @@
+ 	unsigned char __user * vec)
+ {
+ 	int index = 0;
+-	unsigned long end, limit;
++	unsigned long end, real_end, limit;
+ 	struct vm_area_struct * vma;
+ 	size_t max;
+-	int unmapped_error = 0;
+ 	long error;
++	unsigned char * tmp = NULL;
+ 
+ 	/* check the arguments */
+  	if (start & ~PAGE_CACHE_MASK)
+@@ -130,54 +112,85 @@
+ 	if (len > max)
+ 		goto einval;
+ 
+-	end = start + len;
+-
+-	/* check the output buffer whilst holding the lock */
++	/*
++	 * if any pages pointed to by *vec are not in core we
++	 * will deadlock later at the copy_to_user due to mmap_sem
++	 * being locked.  So, we must only look at as many pages 
++	 * as fit into 1 page of vec at a time and and copy to a
++	 * tmp page that we know is in core
++	 */
++	real_end = start + len;
+ 	error = -EFAULT;
+-	down_read(&current->mm->mmap_sem);
+ 
+-	if (!access_ok(VERIFY_WRITE, vec, len >> PAGE_SHIFT))
+-		goto out;
++	end = start;
++	while (end < real_end)
++	{
++	    end += PAGE_SIZE*PAGE_SIZE;
++	    if (end > real_end)
++		end = real_end;
++
++	    index = 0;
++	    tmp = (unsigned char *) __get_free_page(GFP_KERNEL);
++	    if (!tmp)
++		goto enomem;
+ 
+-	/*
+-	 * If the interval [start,end) covers some unmapped address
+-	 * ranges, just ignore them, but return -ENOMEM at the end.
+-	 */
+-	error = 0;
++    	    /* check the output buffer whilst holding the lock */
++    	    down_read(&current->mm->mmap_sem);
++
++    	    if (!access_ok(VERIFY_WRITE, vec, len >> PAGE_SHIFT)){
++		error = -EFAULT;
++		goto error_unlock;
++	    }
+ 
+-	vma = find_vma(current->mm, start);
+-	while (vma) {
++    	    error = 0;
++
++    	    vma = find_vma(current->mm, start);
++    	    while (vma) {
+ 		/* Here start < vma->vm_end. */
+-		if (start < vma->vm_start) {
+-			unmapped_error = -ENOMEM;
+-			start = vma->vm_start;
++		if (start < vma->vm_start){
++		    error = -ENOMEM;
++		    goto error_unlock;
+ 		}
+ 
+ 		/* Here vma->vm_start <= start < vma->vm_end. */
+ 		if (end <= vma->vm_end) {
+-			if (start < end) {
+-				error = mincore_vma(vma, start, end,
+-							&vec[index]);
+-				if (error)
+-					goto out;
+-			}
+-			error = unmapped_error;
+-			goto out;
++	    	    if (start < end) {
++			error = mincore_vma(vma, start, end, &tmp[index]);
++			if (error)
++			    goto error_unlock;
++			index += (end - start) >> PAGE_CACHE_SHIFT;
++			start = end;
++		    }
++		    goto out;
+ 		}
+ 
+ 		/* Here vma->vm_start <= start < vma->vm_end < end. */
+-		error = mincore_vma(vma, start, vma->vm_end, &vec[index]);
++		error = mincore_vma(vma, start, vma->vm_end, &tmp[index]);
+ 		if (error)
+-			goto out;
++		    goto error_unlock;
+ 		index += (vma->vm_end - start) >> PAGE_CACHE_SHIFT;
+ 		start = vma->vm_end;
+ 		vma = vma->vm_next;
+-	}
++    	    }
+ 
+-	/* we found a hole in the area queried if we arrive here */
+-	error = -ENOMEM;
++
++    	    /* we found a hole in the area queried if we arrive here */
++    	    error = -ENOMEM;
++	    goto error_unlock;
+ 
+ out:
++    	    up_read(&current->mm->mmap_sem);
++	    if (copy_to_user(vec, tmp, index))
++		    error = -EFAULT;
++            vec += index;
++	    free_page((unsigned long)tmp);
++	    tmp = NULL;
++	}
++	return error;
++
++error_unlock:
++	if (tmp)
++	    free_page((unsigned long)tmp);
+ 	up_read(&current->mm->mmap_sem);
+ 	return error;
+ 
+
+

Added: dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-16sarge7
==============================================================================
--- (empty file)
+++ dists/sarge-security/kernel/source/kernel-source-2.6.8-2.6.8/debian/patches/series/2.6.8-16sarge7	Sat Dec 16 09:14:20 2006
@@ -0,0 +1,2 @@
++ debian/patches/mincore-fixes.dpatch
++ debian/patches/mincore_hang.dpatch



More information about the Kernel-svn-changes mailing list