Index: linux-2.6.17-rc4-mm1/mm/migrate.c =================================================================== --- linux-2.6.17-rc4-mm1.orig/mm/migrate.c 2006-05-18 10:36:56.930910584 -0700 +++ linux-2.6.17-rc4-mm1/mm/migrate.c 2006-05-19 18:50:30.150296056 -0700 @@ -723,6 +723,7 @@ out: * Move a list of individual pages */ struct page_to_node { + unsigned long addr; struct page *page; int node; int status; @@ -795,31 +796,56 @@ asmlinkage long sys_move_pages(int pid, } task_nodes = cpuset_mems_allowed(task); + if (nr_pages < 1 || nr_pages + 2 > MAX_SLAB / sizeof(struct page_to_node)) { + err = -ENOMEM; + goto out2; + } pm = kmalloc(GFP_KERNEL, (nr_pages + 1) * sizeof(struct page_to_node)); if (!pm) { err = -ENOMEM; goto out2; } + /* + * Get parameters from user space. + */ + for (i = 0; i < nr_pages; i++) { + + pm[i].page = ZERO_PAGE(0); + err = -EFAULT; + if (get_user(&pm[i].addr, pages + i)) + goto out3; + if (nodes) { + int node; + + if (get_user(&node, nodes + i)) + goto out3; + + err = -ENOENT; + if (!node_online(node)) + goto out3; + + err = -EPERM; + if (!node_isset(node, task_nodes)) + goto out3; + + pm[i].node= node; + } + } + pm[nr_pages].page = NULL; + down_read(&mm->mmap_sem); - for(i = 0 ; i < nr_pages; i++) { - unsigned long addr; - int node; + for (i = 0; i < nr_pages; i++) { struct vm_area_struct *vma; struct page *page; - pm[i].page = ZERO_PAGE(0); - err = -EFAULT; - if (get_user(addr, pages + i)) - goto putback; - - vma = find_vma(mm, addr); + vma = find_vma(mm, pm[i].addr); if (!vma) goto set_status; - page = follow_page(vma, addr, FOLL_GET); + page = follow_page(vma, pm[i].addr, FOLL_GET); err = -ENOENT; if (!page) goto set_status; @@ -844,24 +870,11 @@ asmlinkage long sys_move_pages(int pid, if (err) goto remove; - err = -EFAULT; - if (get_user(node, nodes + i)) - goto remove; - - err = -ENOENT; - if (!node_online(node)) - goto remove; - - err = -EPERM; - if (!node_isset(node, task_nodes)) - goto remove; - - pm[i].node = node; err = -EAGAIN; - if (node != page_to_nid(page)) + if (pm[i].node != page_to_nid(page)) goto set_status; - err = node; + err = pm[i].node; remove: list_del(&page->lru); move_to_lru(page); @@ -872,9 +885,7 @@ set_status: if (!nodes || list_empty(&pagelist)) goto out; - pm[nr_pages].page = NULL; - - err = migrate_pages(&pagelist, new_page_node, (unsigned long)pm); + rr = migrate_pages(&pagelist, new_page_node, (unsigned long)pm); goto out; putback: @@ -884,9 +895,11 @@ out: up_read(&mm->mmap_sem); if (err >= 0) /* Return status information */ - for(i = 0; i < nr_pages; i++) - put_user(pm[i].status, status +i); + for (i = 0; i < nr_pages; i++) + if (put_user(pm[i].status, status +i)) + err = -EFAULT; +out3: kfree(pm); out2: mmput(mm);