]> err.no Git - linux-2.6/blobdiff - fs/proc/task_mmu.c
Merge branch 'upstream-net26' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / fs / proc / task_mmu.c
index 49958cffbd8da91d4505a55ee5cbb9a353555c1b..4206454734e09d464d34a5c5a3bd86a6b51cfa9d 100644 (file)
@@ -531,7 +531,7 @@ struct pagemapread {
 #define PM_RESERVED_BITS    3
 #define PM_RESERVED_OFFSET  (64 - PM_RESERVED_BITS)
 #define PM_RESERVED_MASK    (((1LL<<PM_RESERVED_BITS)-1) << PM_RESERVED_OFFSET)
-#define PM_SPECIAL(nr)      (((nr) << PM_RESERVED_OFFSET) | PM_RESERVED_MASK)
+#define PM_SPECIAL(nr)      (((nr) << PM_RESERVED_OFFSET) & PM_RESERVED_MASK)
 #define PM_NOT_PRESENT      PM_SPECIAL(1LL)
 #define PM_SWAP             PM_SPECIAL(2LL)
 #define PM_END_OF_BUFFER    1
@@ -640,17 +640,17 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
 
        ret = -EACCES;
        if (!ptrace_may_attach(task))
-               goto out;
+               goto out_task;
 
        ret = -EINVAL;
        /* file position must be aligned */
        if (*ppos % PM_ENTRY_BYTES)
-               goto out;
+               goto out_task;
 
        ret = 0;
        mm = get_task_mm(task);
        if (!mm)
-               goto out;
+               goto out_task;
 
        ret = -ENOMEM;
        uaddr = (unsigned long)buf & PAGE_MASK;
@@ -658,7 +658,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE;
        pages = kmalloc(pagecount * sizeof(struct page *), GFP_KERNEL);
        if (!pages)
-               goto out_task;
+               goto out_mm;
 
        down_read(&current->mm->mmap_sem);
        ret = get_user_pages(current, current->mm, uaddr, pagecount,
@@ -668,6 +668,12 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
        if (ret < 0)
                goto out_free;
 
+       if (ret != pagecount) {
+               pagecount = ret;
+               ret = -EFAULT;
+               goto out_pages;
+       }
+
        pm.out = buf;
        pm.end = buf + count;
 
@@ -699,15 +705,17 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
                        ret = pm.out - buf;
        }
 
+out_pages:
        for (; pagecount; pagecount--) {
                page = pages[pagecount-1];
                if (!PageReserved(page))
                        SetPageDirty(page);
                page_cache_release(page);
        }
-       mmput(mm);
 out_free:
        kfree(pages);
+out_mm:
+       mmput(mm);
 out_task:
        put_task_struct(task);
 out: