The attached patch 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 <[EMAIL PROTECTED]> --- warthog>diffstat mincore-2611rc3bk8.diff mincore.c | 50 ++++++++++++++++++++++++++++++++------------------ 1 files changed, 32 insertions(+), 18 deletions(-) diff -uNrp linux-2.6.11-rc3-bk8/mm/mincore.c linux-2.6.11-rc3-bk8-mincore/mm/mincore.c --- linux-2.6.11-rc3-bk8/mm/mincore.c 2005-01-04 11:13:57.000000000 +0000 +++ linux-2.6.11-rc3-bk8-mincore/mm/mincore.c 2005-02-11 18:44:25.563625998 +0000 @@ -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(¤t->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(¤t->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(¤t->mm->mmap_sem); return error; + +einval: + return -EINVAL; +enomem: + return -ENOMEM; } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/