lkml.org 
[lkml]   [2012]   [May]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 25/55] mm: mempolicy: Let vma_merge and vma_split handle vma->vm_policy linkages
    3.0-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Mel Gorman <mgorman@suse.de>

    commit 05f144a0d5c2207a0349348127f996e104ad7404 upstream.

    Dave Jones' system call fuzz testing tool "trinity" triggered the
    following bug error with slab debugging enabled

    =============================================================================
    BUG numa_policy (Not tainted): Poison overwritten
    -----------------------------------------------------------------------------

    INFO: 0xffff880146498250-0xffff880146498250. First byte 0x6a instead of 0x6b
    INFO: Allocated in mpol_new+0xa3/0x140 age=46310 cpu=6 pid=32154
    __slab_alloc+0x3d3/0x445
    kmem_cache_alloc+0x29d/0x2b0
    mpol_new+0xa3/0x140
    sys_mbind+0x142/0x620
    system_call_fastpath+0x16/0x1b
    INFO: Freed in __mpol_put+0x27/0x30 age=46268 cpu=6 pid=32154
    __slab_free+0x2e/0x1de
    kmem_cache_free+0x25a/0x260
    __mpol_put+0x27/0x30
    remove_vma+0x68/0x90
    exit_mmap+0x118/0x140
    mmput+0x73/0x110
    exit_mm+0x108/0x130
    do_exit+0x162/0xb90
    do_group_exit+0x4f/0xc0
    sys_exit_group+0x17/0x20
    system_call_fastpath+0x16/0x1b
    INFO: Slab 0xffffea0005192600 objects=27 used=27 fp=0x (null) flags=0x20000000004080
    INFO: Object 0xffff880146498250 @offset=592 fp=0xffff88014649b9d0

    This implied a reference counting bug and the problem happened during
    mbind().

    mbind() applies a new memory policy to a range and uses mbind_range() to
    merge existing VMAs or split them as necessary. In the event of splits,
    mpol_dup() will allocate a new struct mempolicy and maintain existing
    reference counts whose rules are documented in
    Documentation/vm/numa_memory_policy.txt .

    The problem occurs with shared memory policies. The vm_op->set_policy
    increments the reference count if necessary and split_vma() and
    vma_merge() have already handled the existing reference counts.
    However, policy_vma() screws it up by replacing an existing
    vma->vm_policy with one that potentially has the wrong reference count
    leading to a premature free. This patch removes the damage caused by
    policy_vma().

    With this patch applied Dave's trinity tool runs an mbind test for 5
    minutes without error. /proc/slabinfo reported that there are no
    numa_policy or shared_policy_node objects allocated after the test
    completed and the shared memory region was deleted.

    Signed-off-by: Mel Gorman <mgorman@suse.de>
    Cc: Dave Jones <davej@redhat.com>
    Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
    Cc: Stephen Wilson <wilsons@start.ca>
    Cc: Christoph Lameter <cl@linux.com>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    mm/mempolicy.c | 41 +++++++++++++++++------------------------
    1 file changed, 17 insertions(+), 24 deletions(-)

    --- a/mm/mempolicy.c
    +++ b/mm/mempolicy.c
    @@ -606,27 +606,6 @@ check_range(struct mm_struct *mm, unsign
    return first;
    }

    -/* Apply policy to a single VMA */
    -static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
    -{
    - int err = 0;
    - struct mempolicy *old = vma->vm_policy;
    -
    - pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
    - vma->vm_start, vma->vm_end, vma->vm_pgoff,
    - vma->vm_ops, vma->vm_file,
    - vma->vm_ops ? vma->vm_ops->set_policy : NULL);
    -
    - if (vma->vm_ops && vma->vm_ops->set_policy)
    - err = vma->vm_ops->set_policy(vma, new);
    - if (!err) {
    - mpol_get(new);
    - vma->vm_policy = new;
    - mpol_put(old);
    - }
    - return err;
    -}
    -
    /* Step 2: apply policy to a range and do splits. */
    static int mbind_range(struct mm_struct *mm, unsigned long start,
    unsigned long end, struct mempolicy *new_pol)
    @@ -666,9 +645,23 @@ static int mbind_range(struct mm_struct
    if (err)
    goto out;
    }
    - err = policy_vma(vma, new_pol);
    - if (err)
    - goto out;
    +
    + /*
    + * Apply policy to a single VMA. The reference counting of
    + * policy for vma_policy linkages has already been handled by
    + * vma_merge and split_vma as necessary. If this is a shared
    + * policy then ->set_policy will increment the reference count
    + * for an sp node.
    + */
    + pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
    + vma->vm_start, vma->vm_end, vma->vm_pgoff,
    + vma->vm_ops, vma->vm_file,
    + vma->vm_ops ? vma->vm_ops->set_policy : NULL);
    + if (vma->vm_ops && vma->vm_ops->set_policy) {
    + err = vma->vm_ops->set_policy(vma, new_pol);
    + if (err)
    + goto out;
    + }
    }

    out:



    \
     
     \ /
      Last update: 2012-05-27 03:41    [W:4.202 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site