X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=mm%2Fmincore.c;h=c47fff50053dfc923fbae90e8ff777f593f104b3;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=280abef57c5f645db0032ecb16fa8dd9995e80b1;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/mm/mincore.c b/mm/mincore.c index 280abef57..c47fff500 100644 --- a/mm/mincore.c +++ b/mm/mincore.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -108,39 +109,45 @@ asmlinkage long sys_mincore(unsigned long start, size_t len, 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; @@ -168,7 +175,15 @@ asmlinkage long sys_mincore(unsigned long start, size_t len, 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; }