Messages in this thread Patch in this message |  | | | Date | Tue, 12 Apr 2011 21:08:04 +0200 | | From | Oleg Nesterov <> | | Subject | [PATCH 1/1] __mlock_vma_pages_range: stack_guard_page() case returns the wrong value |
| |
__mlock_vma_pages_range() simply changes addr/nr_pages when stack_guard_page(vma, start). But this means that __get_user_pages() returns a number which doesn't match the [start, end) interval and the caller can be confused.
If we skip the first page, we should return 1 if gup fails, or add 1 to the number it returns.
Signed-off-by: Oleg Nesterov <oleg@redhat.com> --- mm/mlock.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) --- sigprocmask/mm/mlock.c~do_mlock_pages_stack_guard_page 2011-04-06 21:33:50.000000000 +0200 +++ sigprocmask/mm/mlock.c 2011-04-12 20:50:30.000000000 +0200 @@ -159,9 +159,8 @@ static long __mlock_vma_pages_range(stru int *nonblocking) { struct mm_struct *mm = vma->vm_mm; - unsigned long addr = start; int nr_pages = (end - start) / PAGE_SIZE; - int gup_flags; + int gup_flags, skip_page, ret; VM_BUG_ON(start & ~PAGE_MASK); VM_BUG_ON(end & ~PAGE_MASK); @@ -189,13 +188,22 @@ static long __mlock_vma_pages_range(stru gup_flags |= FOLL_MLOCK; /* We don't try to access the guard page of a stack vma */ + skip_page = 0; if (stack_guard_page(vma, start)) { - addr += PAGE_SIZE; + skip_page = 1; + start += PAGE_SIZE; nr_pages--; } - return __get_user_pages(current, mm, addr, nr_pages, gup_flags, + ret = __get_user_pages(current, mm, start, nr_pages, gup_flags, NULL, NULL, nonblocking); + + if (ret >= 0) + ret += skip_page; + else if (skip_page) + ret = 1; + + return ret; } /*
|  |