On Fri, Jul 25, 2014 at 10:35:15AM +0800, Qiang Huang wrote:
> Hi Greg,
> 
>   7f88f88f83ed609650a01b18572e605ea50cd163
>   mm: kmemleak: avoid false negatives on vmalloc'ed objects
> 
> This patch looks applicable to stable-3.4, it fixed a regression that
> kmemleak was rarely reporting vmalloc() leaks. It was tested fine
> by me.
> 
> This patch needs some adjustments, before apply this patch, please
> cherry-pick a preparation patch:
> 
>   a3860c1c5dd1137db23d7786d284939c5761d517
>   introduce SIZE_MAX
>

Looks like this could also be applied to the 3.11 kernel as well.
Thanks!

Cheers,
--
Luís

> ----------------------------------
> 
> From: Catalin Marinas <[email protected]>
> 
> commit 7f88f88f83ed609650a01b18572e605ea50cd163 upstream.
> 
> Commit 248ac0e1943a ("mm/vmalloc: remove guard page from between vmap
> blocks") had the side effect of making vmap_area.va_end member point to
> the next vmap_area.va_start.  This was creating an artificial reference
> to vmalloc'ed objects and kmemleak was rarely reporting vmalloc() leaks.
> 
> This patch marks the vmap_area containing pointers explicitly and
> reduces the min ref_count to 2 as vm_struct still contains a reference
> to the vmalloc'ed object.  The kmemleak add_scan_area() function has
> been improved to allow a SIZE_MAX argument covering the rest of the
> object (for simpler calling sites).
> 
> Signed-off-by: Catalin Marinas <[email protected]>
> Signed-off-by: Andrew Morton <[email protected]>
> Signed-off-by: Linus Torvalds <[email protected]>
> [hq: Backported to 3.4: Adjust context]
> Signed-off-by: Qiang Huang <[email protected]>
> ---
>  mm/kmemleak.c |  4 +++-
>  mm/vmalloc.c  | 14 ++++++++++----
>  2 files changed, 13 insertions(+), 5 deletions(-)
> 
> diff --git a/mm/kmemleak.c b/mm/kmemleak.c
> index 45eb621..ad6ee88 100644
> --- a/mm/kmemleak.c
> +++ b/mm/kmemleak.c
> @@ -750,7 +750,9 @@ static void add_scan_area(unsigned long ptr, size_t size, 
> gfp_t gfp)
>       }
> 
>       spin_lock_irqsave(&object->lock, flags);
> -     if (ptr + size > object->pointer + object->size) {
> +     if (size == SIZE_MAX) {
> +             size = object->pointer + object->size - ptr;
> +     } else if (ptr + size > object->pointer + object->size) {
>               kmemleak_warn("Scan area larger than object 0x%08lx\n", ptr);
>               dump_object_info(object);
>               kmem_cache_free(scan_area_cache, area);
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 1196c77..ad9d900 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -349,6 +349,12 @@ static struct vmap_area *alloc_vmap_area(unsigned long 
> size,
>       if (unlikely(!va))
>               return ERR_PTR(-ENOMEM);
> 
> +     /*
> +      * Only scan the relevant parts containing pointers to other objects
> +      * to avoid false negatives.
> +      */
> +     kmemleak_scan_area(&va->rb_node, SIZE_MAX, gfp_mask & GFP_RECLAIM_MASK);
> +
>  retry:
>       spin_lock(&vmap_area_lock);
>       /*
> @@ -1669,11 +1675,11 @@ void *__vmalloc_node_range(unsigned long size, 
> unsigned long align,
>       insert_vmalloc_vmlist(area);
> 
>       /*
> -      * A ref_count = 3 is needed because the vm_struct and vmap_area
> -      * structures allocated in the __get_vm_area_node() function contain
> -      * references to the virtual address of the vmalloc'ed block.
> +      * A ref_count = 2 is needed because vm_struct allocated in
> +      * __get_vm_area_node() contains a reference to the virtual address of
> +      * the vmalloc'ed block.
>        */
> -     kmemleak_alloc(addr, real_size, 3, gfp_mask);
> +     kmemleak_alloc(addr, real_size, 2, gfp_mask);
> 
>       return addr;
> 
> -- 1.8.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe stable" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to