lkml.org 
[lkml]   [2011]   [Oct]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 3/X] uprobes: xol_add_vma: fix ->uprobes_xol_area initialization
    xol_add_vma() can race with another thread which sets ->uprobes_xol_area,
    in this case we can't rely on per-thread task_lock() and we should unmap
    xol_vma.

    Move the setting of mm->uprobes_xol_area into xol_add_vma(), it has to
    take mmap_sem for writing anyway, this also simplifies the code.

    Change xol_add_vma() to do do_munmap() if it fails after do_mmap_pgoff().
    ---
    kernel/uprobes.c | 34 ++++++++++++++++------------------
    1 files changed, 16 insertions(+), 18 deletions(-)

    diff --git a/kernel/uprobes.c b/kernel/uprobes.c
    index fd9c8e3..6fe2b20 100644
    --- a/kernel/uprobes.c
    +++ b/kernel/uprobes.c
    @@ -1049,18 +1049,18 @@ static int xol_add_vma(struct uprobes_xol_area *area)
    struct vm_area_struct *vma;
    struct mm_struct *mm;
    unsigned long addr;
    - int ret = -ENOMEM;
    + int ret;

    mm = get_task_mm(current);
    if (!mm)
    return -ESRCH;

    down_write(&mm->mmap_sem);
    - if (mm->uprobes_xol_area) {
    - ret = -EALREADY;
    + ret = -EALREADY;
    + if (mm->uprobes_xol_area)
    goto fail;
    - }

    + ret = -ENOMEM;
    /*
    * Find the end of the top mapping and skip a page.
    * If there is no space for PAGE_SIZE above
    @@ -1078,15 +1078,19 @@ static int xol_add_vma(struct uprobes_xol_area *area)

    if (addr & ~PAGE_MASK)
    goto fail;
    - vma = find_vma(mm, addr);

    + vma = find_vma(mm, addr);
    /* Don't expand vma on mremap(). */
    vma->vm_flags |= VM_DONTEXPAND | VM_DONTCOPY;
    area->vaddr = vma->vm_start;
    if (get_user_pages(current, mm, area->vaddr, 1, 1, 1, &area->page,
    - &vma) > 0)
    - ret = 0;
    + &vma) != 1) {
    + do_munmap(mm, addr, PAGE_SIZE);
    + goto fail;
    + }

    + mm->uprobes_xol_area = area;
    + ret = 0;
    fail:
    up_write(&mm->mmap_sem);
    mmput(mm);
    @@ -1102,7 +1106,7 @@ fail:
    */
    static struct uprobes_xol_area *xol_alloc_area(void)
    {
    - struct uprobes_xol_area *area = NULL;
    + struct uprobes_xol_area *area;

    area = kzalloc(sizeof(*area), GFP_KERNEL);
    if (unlikely(!area))
    @@ -1110,22 +1114,16 @@ static struct uprobes_xol_area *xol_alloc_area(void)

    area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long),
    GFP_KERNEL);
    -
    if (!area->bitmap)
    goto fail;

    init_waitqueue_head(&area->wq);
    spin_lock_init(&area->slot_lock);
    - if (!xol_add_vma(area) && !current->mm->uprobes_xol_area) {
    - task_lock(current);
    - if (!current->mm->uprobes_xol_area) {
    - current->mm->uprobes_xol_area = area;
    - task_unlock(current);
    - return area;
    - }
    - task_unlock(current);
    - }

    + if (xol_add_vma(area))
    + goto fail;
    +
    + return area;
    fail:
    kfree(area->bitmap);
    kfree(area);
    --
    1.5.5.1



    \
     
     \ /
      Last update: 2011-10-15 21:07    [W:0.024 / U:32.308 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site