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 <catalin.marinas@xxxxxxx> > > 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 <catalin.marinas@xxxxxxx> > Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> > Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> > [hq: Backported to 3.4: Adjust context] > Signed-off-by: Qiang Huang <h.huangqiang@xxxxxxxxxx> > --- > 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 majordomo@xxxxxxxxxxxxxxx > 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html