Skip to contentSkip to conversation

Kernel memory leak detector 0.8

PATCH In review Catalin Marinas 6 participants 49 messages Jul 10, 2006 – Jul 14, 2006

Subsystems (13)
lore
Share & tools
lore
#0 lore raw

cover Kernel memory leak detector 0.8

This is a new version (0.8) of the kernel memory leak detector. See the Documentation/kmemleak.txt file for a more detailed description. The patches are downloadable from (the whole patch or the broken-out series):

http://homepage.ntlworld.com/cmarinas/kmemleak/patch-2.6.18-rc1-kmemleak-0.8.bz2
http://homepage.ntlworld.com/cmarinas/kmemleak/patches-kmemleak-0.8.tar.bz2

What's new in this version:

- reviewers comments implemented
- added support for type ids (currently approximated by sizeof)
- NUMA support
- reduced the memory allocation/freeing overhead by adding the pointer aliases to the radix tree only when scanning the memory
- improved documentation and in-code comments

To do:

- more testing
- more investigation into the task stacks scanning
- precise type identification (after first assessing the efficiency of the current method as it requires changes to the kernel API)
- (support for ioremap tracking)

Signature · 1 line
Catalin
#1 lore raw

PATCH 1/10 Base support for kmemleak

From: Catalin Marinas <[email protected]>

This patch adds the base support for the kernel memory leak detector. It traces the memory allocation/freeing in a way similar to the Boehm's conservative garbage collector, the difference being that the orphan pointers are not freed but only shown in /proc/memleak. Enabling this feature would introduce an overhead to memory allocations.

---

 include/linux/kernel.h  |    7 
 include/linux/memleak.h |  111 ++++
 init/main.c             |    3 
 lib/Kconfig.debug       |   66 ++
 mm/Makefile             |    2 
 mm/memleak.c            | 1309 +++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 1495 insertions(+), 3 deletions(-)
include/linux/kernel.h +6 -1
index 5c1ec1f..c031c18 100644
@@ -13,6 +13,7 @@ #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/bitops.h>
+#include <linux/memleak.h>
 #include <asm/byteorder.h>
 #include <asm/bug.h>
 
@@ -290,9 +291,13 @@ #define max_t(type,x,y) \
  * @member:	the name of the member within the struct.
  *
  */
-#define container_of(ptr, type, member) ({			\
+#define __container_of(ptr, type, member) ({			\
         const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
         (type *)( (char *)__mptr - offsetof(type,member) );})
+#define container_of(ptr, type, member) ({			\
+	DECLARE_MEMLEAK_OFFSET(container_of, type, member);	\
+	__container_of(ptr, type, member);			\
+})
 
 /*
  * Check at compile time that something is of a particular type.
include/linux/memleak.h new file +111 -0

111 lines not on this page · raw message

init/main.c +2 -1
index 628b8e9..7db97ab 100644
@@ -546,6 +546,8 @@ #endif
 	cpuset_init_early();
 	mem_init();
 	kmem_cache_init();
+	radix_tree_init();
+	memleak_init();
 	setup_per_cpu_pageset();
 	numa_policy_init();
 	if (late_time_init)
@@ -566,7 +568,6 @@ #endif
 	key_init();
 	security_init();
 	vfs_caches_init(num_physpages);
-	radix_tree_init();
 	signals_init();
 	/* rootfs populating might need page-writeback */
 	page_writeback_init();
lib/Kconfig.debug +66 -0

72 lines not on this page · raw message

mm/Makefile +1 -1
index 9dd824c..edccbc0 100644
@@ -23,4 +23,4 @@ obj-$(CONFIG_SLAB) += slab.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
-
+obj-$(CONFIG_DEBUG_MEMLEAK) += memleak.o
mm/memleak.c new file +1309 -0

1,309 lines not on this page · raw message

#2 lore raw

PATCH 2/10 Some documentation for kmemleak

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

---

 Documentation/kmemleak.txt |  157 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 157 insertions(+), 0 deletions(-)
Documentation/kmemleak.txt new file +157 -0
new file mode 100644
index 0000000..4d2f608
@@ -0,0 +1,157 @@
+Kernel Memory Leak Detector
+===========================
+
+
+Introduction
+------------
+
+Kmemleak provides a way of detecting possible kernel memory leaks in a
+way similar to a tracing garbage collector
+(http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29#Tracing_garbage_collectors),
+with the difference that the orphan pointers are not freed but only
+reported via /sys/kernel/debug/memleak. A similar method is used by
+the Valgrind tool (memcheck --leak-check) to detect the memory leaks
+in user-space applications.
+
+
+Usage
+-----
+
+CONFIG_DEBUG_MEMLEAK has to be enabled. For additional config options,
+look in:
+
+  -> Kernel hacking
+    -> Kernel debugging
+      -> Debug slab memory allocations
+        -> Kernel memory leak detector
+
+To display the possible memory leaks:
+
+  # mount -t debugfs nodev /sys/kernel/debug/
+  # cat /sys/kernel/debug/memleak
+
+In order to reduce the run-time overhead, memory scanning is only
+performed when reading the /sys/kernel/debug/memleak file.
+
+
+Basic Algorithm
+---------------
+
+The memory allocations via kmalloc, vmalloc, kmem_cache_alloc and
+friends are tracked and the pointers, together with additional
+information like size and stack trace, are stored in a radix tree. The
+corresponding freeing function calls are tracked and the pointers
+removed from the radix tree.
+
+An allocated block of memory is considered orphan if a pointer to its
+start address or to an alias (pointer aliases are explained later)
+cannot be found by scanning the memory (including saved
+registers). This means that there might be no way for the kernel to
+pass the address of the allocated block to a freeing function and
+therefore the block is considered a leak.
+
+The scanning algorithm steps:
+
+  1. mark all pointers as white (remaining white pointers will later
+     be considered orphan)
+  2. scan the memory starting with the data section and stacks,
+     checking the values against the addresses stored in the radix
+     tree. If a white pointer is found, it is added to the grey list
+  3. scan the grey pointers for matching addresses (some white
+     pointers can become grey and added at the end of the grey list)
+     until the grey set is finished
+  4. the remaining white pointers are considered orphan and reported
+     via /sys/kernel/debug/memleak
+
+
+Improvements
+------------
+
+Because the Linux kernel calculates many pointers at run-time via the
+container_of macro (see the lists implementation), a lot of false
+positives would be reported. This tool re-writes the container_of
+macro so that the offset and type information is stored in the
+.init.memleak_offsets section. The memleak_init() function creates a
+radix tree with corresponding offsets for every encountered block
+type. The memory allocations hook stores the pointer address together
+with its aliases based on the type of the allocated block.
+
+While one level of offsets should be enough for most cases, a second
+level, i.e. container_of(container_of(...)), can be enabled via the
+configuration options (one false positive is the "struct socket_alloc"
+allocation in the sock_alloc_inode() function).
+
+Some allocated memory blocks have pointers stored in the kernel's
+internal data structures and they cannot be detected as orphans. To
+avoid this, kmemleak can also store the number of values equal to the
+pointer (or aliases) that need to be found so that the block is not
+considered a leak. One example is __vmalloc().
+
+
+Limitations and Drawbacks
+-------------------------
+
+The biggest drawback is the reduced performance of memory allocation
+and freeing. To avoid other penalties, the memory scanning is only
+performed when the /sys/kernel/debug/memleak file is read. Anyway,
+this tool is intended for debugging purposes where the performance
+might not be the most important requirement.
+
+Kmemleak currently approximates the type id using the sizeof()
+compiler built-in function. This is not accurate and can lead to false
+negatives. The aim is to gradually change the kernel and kmemleak to
+do more precise type identification.
+
+Another source of false negatives is the data stored in non-pointer
+values. Together with the more precise type identification, kmemleak
+could only scan the pointer members in the allocated structures.
+
+The tool can report false positives. These are cases where an
+allocated block doesn't need to be freed (some cases in the init_call
+functions), the pointer is calculated by other methods than the
+container_of macro or the pointer is stored in a location not scanned
+by kmemleak. If the "member" argument in the offsetof(type, member)
+call is not constant, kmemleak considers the offset as zero since it
+cannot be determined at compilation time.
+
+Page allocations and ioremap are not tracked. Only the ARM and i386
+architectures are currently supported.
+
+
+Kmemleak API
+------------
+
+See the include/linux/memleak.h header for the functions prototype.
+
+memleak_init		- initialize kmemleak
+memleak_alloc		- notify of a memory block allocation
+memleak_free		- notify of a memory block freeing
+memleak_padding		- mark the boundaries of the data inside the block
+memleak_not_leak	- mark a pointer as not a leak
+memleak_ignore		- do not scan or report a pointer as leak
+memleak_scan_area	- add scan areas inside a memory block
+memleak_insert_aliases	- add aliases for a given type
+memleak_erase		- erase an old value in a pointer variable
+memleak_typeid_raw	- set the typeid for an allocated block
+memleak_container	- statically declare a pointer alias
+memleak_typeid		- set the typeid for an allocated block (takes
+			  a type rather than typeid as argument)
+
+
+Dealing with false positives/negatives
+--------------------------------------
+
+To reduce the false negatives, kmemleak provides the memleak_ignore,
+memleak_scan_area and memleak_erase functions. The task stacks also
+increase the amount of false negatives and their scanning is not
+enabled by default.
+
+To eliminate the false positives caused by code allocating a different
+size from the object one (either for alignment or for extra memory
+after the end of the structure), kmemleak provides the memleak_padding
+and memleak_typeid functions.
+
+For pointers known not to be leaks, kmemleak provides the
+memleak_not_leak function. The memleak_ignore could also be used if
+the memory block is known not to contain other pointers as it will no
+longer be scanned.
#3 lore raw

PATCH 3/10 Add the memory allocation/freeing hooks for kmemleak

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

This patch adds the callbacks to memleak_(alloc|free) functions from kmalloc/kfree, kmem_cache_(alloc|free), vmalloc/vfree etc.

---

 include/linux/slab.h |    6 ++++++
 mm/page_alloc.c      |    2 ++
 mm/slab.c            |   26 +++++++++++++++++++++++---
 mm/vmalloc.c         |   22 ++++++++++++++++++++--
 4 files changed, 51 insertions(+), 5 deletions(-)
include/linux/slab.h +6 -0
index 45ad55b..e3f5945 100644
@@ -133,6 +133,8 @@ #endif
  */
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
+#ifndef CONFIG_DEBUG_MEMLEAK
+	/* this block removes the size information needed by kmemleak */
 	if (__builtin_constant_p(size)) {
 		int i = 0;
 #define CACHE(x) \
@@ -151,6 +153,7 @@ found:
 			malloc_sizes[i].cs_dmacachep :
 			malloc_sizes[i].cs_cachep, flags);
 	}
+#endif
 	return __kmalloc(size, flags);
 }
 
@@ -163,6 +166,8 @@ extern void *__kzalloc(size_t, gfp_t);
  */
 static inline void *kzalloc(size_t size, gfp_t flags)
 {
+#ifndef CONFIG_DEBUG_MEMLEAK
+	/* this block removes the size information needed by kmemleak */
 	if (__builtin_constant_p(size)) {
 		int i = 0;
 #define CACHE(x) \
@@ -181,6 +186,7 @@ found:
 			malloc_sizes[i].cs_dmacachep :
 			malloc_sizes[i].cs_cachep, flags);
 	}
+#endif
 	return __kzalloc(size, flags);
 }
 
mm/page_alloc.c +2 -0
index 54a4f53..bdf6445 100644
@@ -2450,6 +2450,8 @@ void *__init alloc_large_system_hash(con
 	if (_hash_mask)
 		*_hash_mask = (1 << log2qty) - 1;
 
+	memleak_alloc(table, size, 1);
+
 	return table;
 }
 
mm/slab.c +23 -3
index 85c2e03..2752272 100644
@@ -2967,6 +2967,7 @@ #endif
 		STATS_INC_ALLOCMISS(cachep);
 		objp = cache_alloc_refill(cachep, flags);
 	}
+	memleak_erase(&ac->entry[ac->avail]);
 	return objp;
 }
 
@@ -3183,6 +3184,7 @@ static void __cache_free(struct kmem_cac
 	struct array_cache *ac = cpu_cache_get(cachep);
 
 	check_irq_off();
+	memleak_free(objp);
 	objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
 	if (cache_free_alien(cachep, objp, nesting))
@@ -3209,7 +3211,11 @@ static void __cache_free(struct kmem_cac
  */
 void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
-	return __cache_alloc(cachep, flags, __builtin_return_address(0));
+	void *ptr = __cache_alloc(cachep, flags, __builtin_return_address(0));
+
+	memleak_alloc(ptr, obj_size(cachep), 1);
+
+	return ptr;
 }
 EXPORT_SYMBOL(kmem_cache_alloc);
 
@@ -3224,6 +3230,9 @@ EXPORT_SYMBOL(kmem_cache_alloc);
 void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t flags)
 {
 	void *ret = __cache_alloc(cache, flags, __builtin_return_address(0));
+
+	memleak_alloc(ret, obj_size(cache), 1);
+
 	if (ret)
 		memset(ret, 0, obj_size(cache));
 	return ret;
@@ -3302,6 +3311,7 @@ void *kmem_cache_alloc_node(struct kmem_
 
 	ptr = cache_alloc_debugcheck_after(cachep, flags, ptr,
 					   __builtin_return_address(0));
+	memleak_alloc(ptr, obj_size(cachep), 1);
 
 	return ptr;
 }
@@ -3310,11 +3320,15 @@ EXPORT_SYMBOL(kmem_cache_alloc_node);
 void *kmalloc_node(size_t size, gfp_t flags, int node)
 {
 	struct kmem_cache *cachep;
+	void *ptr;
 
 	cachep = kmem_find_general_cachep(size, flags);
 	if (unlikely(cachep == NULL))
 		return NULL;
-	return kmem_cache_alloc_node(cachep, flags, node);
+	ptr = kmem_cache_alloc_node(cachep, flags, node);
+	memleak_typeid_raw(ptr, ml_guess_typeid(size));
+	memleak_padding(ptr, 0, size);
+	return ptr;
 }
 EXPORT_SYMBOL(kmalloc_node);
 #endif
@@ -3329,6 +3343,7 @@ static __always_inline void *__do_kmallo
 					  void *caller)
 {
 	struct kmem_cache *cachep;
+	void *ptr;
 
 	/* If you want to save a few bytes .text space: replace
 	 * __ with kmem_.
@@ -3338,7 +3353,11 @@ static __always_inline void *__do_kmallo
 	cachep = __find_general_cachep(size, flags);
 	if (unlikely(cachep == NULL))
 		return NULL;
-	return __cache_alloc(cachep, flags, caller);
+	ptr = __cache_alloc(cachep, flags, caller);
+
+	memleak_alloc(ptr, size, 1);
+
+	return ptr;
 }
 
 
@@ -3447,6 +3466,7 @@ void kfree(const void *objp)
 		return;
 	local_irq_save(flags);
 	kfree_debugcheck(objp);
+
 	c = virt_to_cache(objp);
 	debug_check_no_locks_freed(objp, obj_size(c));
 	__cache_free(c, (void *)objp, 0);
mm/vmalloc.c +20 -2
index 7b45079..b84a862 100644
@@ -364,6 +364,9 @@ void __vunmap(void *addr, int deallocate
 void vfree(void *addr)
 {
 	BUG_ON(in_interrupt());
+
+	memleak_free(addr);
+
 	__vunmap(addr, 1);
 }
 EXPORT_SYMBOL(vfree);
@@ -462,7 +465,14 @@ fail:
 
 void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
 {
-	return __vmalloc_area_node(area, gfp_mask, prot, -1);
+	void *addr = __vmalloc_area_node(area, gfp_mask, prot, -1);
+
+	/* this needs ref_count = 2 since vm_struct also contains a
+	   pointer to this address. The guard page is also subtracted
+	   from the size */
+	memleak_alloc(addr, area->size - PAGE_SIZE, 2);
+
+	return addr;
 }
 
 /**
@@ -481,6 +491,8 @@ void *__vmalloc_node(unsigned long size,
 			int node)
 {
 	struct vm_struct *area;
+	void *addr;
+	unsigned long real_size = size;
 
 	size = PAGE_ALIGN(size);
 	if (!size || (size >> PAGE_SHIFT) > num_physpages)
@@ -490,7 +502,13 @@ void *__vmalloc_node(unsigned long size,
 	if (!area)
 		return NULL;
 
-	return __vmalloc_area_node(area, gfp_mask, prot, node);
+	addr = __vmalloc_area_node(area, gfp_mask, prot, node);
+
+	/* this needs ref_count = 2 since the vm_struct also contains
+	   a pointer to this address */
+	memleak_alloc(addr, real_size, 2);
+
+	return addr;
 }
 EXPORT_SYMBOL(__vmalloc_node);
 
#4 lore raw

Re: [PATCH 03/10] Add the memory allocation/freeing hooks for kmemleak

Hi Catalin

mm/slab.c #endif · line 2972

Quoted 11 lines · Catalin Marinas
mm/slab.c +1 -0
index 85c2e03..2752272 100644
@@ -2967,6 +2967,7 @@ #endif
                STATS_INC_ALLOCMISS(cachep);
                objp = cache_alloc_refill(cachep, flags);
        }
+       memleak_erase(&ac->entry[ac->avail]);
        return objp;
 }

Can't we tell the GC not to scan any of the array cache structs? You could put that in alloc_arraycache(), I think.

mm/slab.c static void __cache_free(struct kmem_cac · line 3216

Quoted 8 lines
mm/slab.c +3 -1
@@ -3209,7 +3211,11 @@ static void __cache_free(struct kmem_cac
  */
 void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
-       return __cache_alloc(cachep, flags, __builtin_return_address(0));
+       void *ptr = __cache_alloc(cachep, flags, __builtin_return_address(0));
+
+       memleak_alloc(ptr, obj_size(cachep), 1);

Can you move memleak_alloc() call to __cache_alloc() instead to avoid duplication?

#5 lore raw

Re: [PATCH 03/10] Add the memory allocation/freeing hooks for kmemleak

Hi Pekka,

Quoted 15 lines · Pekka Enberg

mm/slab.c #endif · line 2972

Quoted 11 lines · Catalin Marinas
mm/slab.c +1 -0
index 85c2e03..2752272 100644
@@ -2967,6 +2967,7 @@ #endif
                STATS_INC_ALLOCMISS(cachep);
                objp = cache_alloc_refill(cachep, flags);
        }
+       memleak_erase(&ac->entry[ac->avail]);
        return objp;
 }

Can't we tell the GC not to scan any of the array cache structs? You could put that in alloc_arraycache(), I think.

Yes, we can. I'll give it a try before updating the patches.

Quoted 11 lines

mm/slab.c static void __cache_free(struct kmem_cac · line 3216

Quoted 8 lines
mm/slab.c +3 -1
@@ -3209,7 +3211,11 @@ static void __cache_free(struct kmem_cac
  */
 void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
-       return __cache_alloc(cachep, flags, __builtin_return_address(0));
+       void *ptr = __cache_alloc(cachep, flags, __builtin_return_address(0));
+
+       memleak_alloc(ptr, obj_size(cachep), 1);

Can you move memleak_alloc() call to __cache_alloc() instead to avoid duplication?

It might clutter the code because __cache_alloc is used by kmalloc as well and the exact size information is lost. It would be to explicitely give the type information to kmemleak in kmalloc and have memleak_alloc called in __cache_alloc (with slight overhead of calling kmemleak functions twice). The other option is to pass an extra argument (guessed typeid) to __cache_alloc but this means adding extra ifdefs.

Thanks.

Signature · 1 line
Catalin
#6 lore raw

PATCH 4/10 Modules support for kmemleak

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

This patch handles the kmemleak operations needed for modules loading so that memory allocations from inside a module are properly tracked.

---

 kernel/module.c |   41 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)
kernel/module.c +41 -0
index 35e1b1f..3b88c06 100644
@@ -1481,6 +1481,11 @@ static struct module *load_module(void _
 	unsigned int unusedcrcindex;
 	unsigned int unusedgplindex;
 	unsigned int unusedgplcrcindex;
+#ifdef CONFIG_DEBUG_MEMLEAK
+	unsigned int dataindex;
+	unsigned int bssindex;
+	unsigned int mloffindex;
+#endif
 	struct module *mod;
 	long err = 0;
 	void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1577,6 +1582,11 @@ #endif
 #ifdef ARCH_UNWIND_SECTION_NAME
 	unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME);
 #endif
+#ifdef CONFIG_DEBUG_MEMLEAK
+	dataindex = find_sec(hdr, sechdrs, secstrings, ".data");
+	bssindex = find_sec(hdr, sechdrs, secstrings, ".bss");
+	mloffindex = find_sec(hdr, sechdrs, secstrings, ".init.memleak_offsets");
+#endif
 
 	/* Don't keep modinfo section */
 	sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
@@ -1646,6 +1656,10 @@ #endif
 
 	/* Do the allocs. */
 	ptr = module_alloc(mod->core_size);
+	/* the pointer to this block is stored in the module structure
+	 * which is inside the block. Just mark it as not being a
+	 * leak */
+	memleak_not_leak(ptr);
 	if (!ptr) {
 		err = -ENOMEM;
 		goto free_percpu;
@@ -1654,6 +1668,11 @@ #endif
 	mod->module_core = ptr;
 
 	ptr = module_alloc(mod->init_size);
+	/* the pointer to this block is stored in the module structure
+	 * which is inside the block. This block doesn't need to be
+	 * scanned as it contains data and code that will be freed
+	 * after the module is initialized */
+	memleak_ignore(ptr);
 	if (!ptr && mod->init_size) {
 		err = -ENOMEM;
 		goto free_core;
@@ -1685,6 +1704,28 @@ #endif
 	/* Module has been moved. */
 	mod = (void *)sechdrs[modindex].sh_addr;
 
+#ifdef CONFIG_DEBUG_MEMLEAK
+	if (mloffindex)
+		memleak_insert_aliases((void *)sechdrs[mloffindex].sh_addr,
+				       (void *)sechdrs[mloffindex].sh_addr
+				         + sechdrs[mloffindex].sh_size);
+
+	/* only scan the sections containing data */
+	memleak_scan_area(mod->module_core,
+			  (unsigned long)mod - (unsigned long)mod->module_core,
+			  sizeof(struct module));
+	if (dataindex)
+		memleak_scan_area(mod->module_core,
+				  sechdrs[dataindex].sh_addr
+				    - (unsigned long)mod->module_core,
+				  sechdrs[dataindex].sh_size);
+	if (bssindex)
+		memleak_scan_area(mod->module_core,
+				  sechdrs[bssindex].sh_addr
+				    - (unsigned long)mod->module_core,
+				  sechdrs[bssindex].sh_size);
+#endif
+
 	/* Now we've moved module, initialize linked lists, etc. */
 	module_unload_init(mod);
 
#7 lore raw

PATCH 5/10 Add kmemleak support for i386

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

This patch modifies the vmlinux.lds.S script and adds the backtrace support for i386 to be used with kmemleak.

---

 arch/i386/kernel/vmlinux.lds.S |    4 ++++
 include/asm-i386/processor.h   |   12 ++++++++++++
 include/asm-i386/thread_info.h |   10 +++++++++-
 3 files changed, 25 insertions(+), 1 deletions(-)
arch/i386/kernel/vmlinux.lds.S +4 -0
index 2d4f138..34fccf1 100644
@@ -45,6 +45,7 @@ SECTIONS
   __tracedata_end = .;
 
   /* writeable */
+  _sdata = .;			/* Start of data section */
   .data : AT(ADDR(.data) - LOAD_OFFSET) {	/* Data */
 	*(.data)
 	CONSTRUCTORS
@@ -156,6 +157,9 @@ #endif
   __per_cpu_start = .;
   .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
   __per_cpu_end = .;
+  __memleak_offsets_start = .;
+  .init.memleak_offsets : AT(ADDR(.init.memleak_offsets) - LOAD_OFFSET) { *(.init.memleak_offsets) }
+  __memleak_offsets_end = .;
   . = ALIGN(4096);
   __init_end = .;
   /* freed after init ends here */
include/asm-i386/processor.h +12 -0
index b32346d..0884122 100644
@@ -731,4 +731,16 @@ extern unsigned long boot_option_idle_ov
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
+#ifdef CONFIG_FRAME_POINTER
+static inline unsigned long arch_call_address(void *frame)
+{
+	return *(unsigned long *) (frame + 4);
+}
+
+static inline void *arch_prev_frame(void *frame)
+{
+	return *(void **) frame;
+}
+#endif
+
 #endif /* __ASM_I386_PROCESSOR_H */
include/asm-i386/thread_info.h +9 -1
index 2833fa2..80b9451 100644
@@ -100,12 +100,20 @@ #define alloc_thread_info(tsk)					\
 		struct thread_info *ret;			\
 								\
 		ret = kmalloc(THREAD_SIZE, GFP_KERNEL);		\
+		memleak_ignore(ret);				\
 		if (ret)					\
 			memset(ret, 0, THREAD_SIZE);		\
 		ret;						\
 	})
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info(tsk)					\
+	({							\
+		struct thread_info *ret;			\
+								\
+		ret = kmalloc(THREAD_SIZE, GFP_KERNEL);		\
+		memleak_ignore(ret);				\
+		ret;						\
+	})
 #endif
 
 #define free_thread_info(info)	kfree(info)
#8 lore raw

PATCH 6/10 Add kmemleak support for ARM

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

This patch modifies the vmlinux.lds.S script and adds the backtrace support for ARM to be used with kmemleak.

---

 arch/arm/kernel/vmlinux.lds.S |    7 +++++++
 include/asm-arm/processor.h   |   12 ++++++++++++
 2 files changed, 19 insertions(+), 0 deletions(-)
arch/arm/kernel/vmlinux.lds.S +7 -0
index 3ca574e..59976b8 100644
@@ -67,6 +67,11 @@ #endif
 		__per_cpu_start = .;
 			*(.data.percpu)
 		__per_cpu_end = .;
+#ifdef CONFIG_DEBUG_MEMLEAK
+		__memleak_offsets_start = .;
+			*(.init.memleak_offsets)
+		__memleak_offsets_end = .;
+#endif
 #ifndef CONFIG_XIP_KERNEL
 		__init_begin = _stext;
 		*(.init.data)
@@ -115,6 +120,7 @@ #endif
 
 	.data : AT(__data_loc) {
 		__data_start = .;	/* address in memory */
+		_sdata = .;
 
 		/*
 		 * first, the init task union, aligned
@@ -165,6 +171,7 @@ #endif
 		__bss_start = .;	/* BSS				*/
 		*(.bss)
 		*(COMMON)
+		__bss_stop = .;
 		_end = .;
 	}
 					/* Stabs debugging sections.	*/
include/asm-arm/processor.h +12 -0
index 04f4d34..feaf017 100644
@@ -121,6 +121,18 @@ #define spin_lock_prefetch(x) do { } whi
 
 #endif
 
+#ifdef CONFIG_FRAME_POINTER
+static inline unsigned long arch_call_address(void *frame)
+{
+	return *(unsigned long *) (frame - 4) - 4;
+}
+
+static inline void *arch_prev_frame(void *frame)
+{
+	return *(void **) (frame - 12);
+}
+#endif
+
 #endif
 
 #endif /* __ASM_ARM_PROCESSOR_H */
#9 lore raw

PATCH 7/10 Remove some of the kmemleak false positives

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

There are allocations for which the main pointer cannot be found but they are not memory leaks. This patch fixes some of them.

---

 drivers/base/platform.c  |    3 +++
 drivers/hwmon/w83627hf.c |    4 ++++
 drivers/scsi/hosts.c     |    3 +++
 fs/ext3/dir.c            |    3 +++
 ipc/util.c               |    6 ++++++
 kernel/params.c          |    8 +++++++-
 mm/slab.c                |    4 ++++
 net/core/dev.c           |    6 ++++++
 net/sched/sch_generic.c  |    6 ++++++
 9 files changed, 42 insertions(+), 1 deletions(-)
drivers/base/platform.c +3 -0
index 2b8755d..1521fe4 100644
@@ -166,6 +166,9 @@ struct platform_device *platform_device_
 	struct platform_object *pa;
 
 	pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
+	/* kmemleak cannot guess the object type because the block
+	 * size is different from the object size */
+	memleak_typeid(pa, struct platform_object);
 	if (pa) {
 		strcpy(pa->name, name);
 		pa->pdev.name = pa->name;
drivers/hwmon/w83627hf.c +4 -0
index 79368d5..f952f02 100644
@@ -1065,6 +1065,10 @@ static int w83627hf_detect(struct i2c_ad
 		err = -ENOMEM;
 		goto ERROR1;
 	}
+	/* the pointer to member is stored but the code doesn't use
+	 * container_of for access and the alias need to be
+	 * explicitely declared here */
+	memleak_container(struct w83627hf_data, client);
 
 	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
drivers/scsi/hosts.c +3 -0
index dfcb96f..9516d37 100644
@@ -297,6 +297,9 @@ struct Scsi_Host *scsi_host_alloc(struct
 	shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask);
 	if (!shost)
 		return NULL;
+	/* kmemleak cannot guess the object type because the block
+	 * size is different from the object size */
+	memleak_typeid(shost, struct Scsi_Host);
 
 	spin_lock_init(&shost->default_lock);
 	scsi_assign_lock(shost, &shost->default_lock);
fs/ext3/dir.c +3 -0
index fbb0d4e..a34814d 100644
@@ -346,6 +346,9 @@ int ext3_htree_store_dirent(struct file 
 	new_fn = kmalloc(len, GFP_KERNEL);
 	if (!new_fn)
 		return -ENOMEM;
+	/* kmemleak cannot guess the object type because the block
+	 * size is different from the object size */
+	memleak_typeid(new_fn, struct fname);
 	memset(new_fn, 0, len);
 	new_fn->hash = hash;
 	new_fn->minor_hash = minor_hash;
ipc/util.c +6 -0
index 67b6d17..17cc294 100644
@@ -388,6 +388,9 @@ void* ipc_rcu_alloc(int size)
 	 */
 	if (rcu_use_vmalloc(size)) {
 		out = vmalloc(HDRLEN_VMALLOC + size);
+		/* the stored pointer is different from the address of
+		 * the allocated block because of padding */
+		memleak_padding(out, HDRLEN_VMALLOC, size);
 		if (out) {
 			out += HDRLEN_VMALLOC;
 			container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 1;
@@ -395,6 +398,9 @@ void* ipc_rcu_alloc(int size)
 		}
 	} else {
 		out = kmalloc(HDRLEN_KMALLOC + size, GFP_KERNEL);
+		/* the stored pointer is different from the address of
+		 * the allocated block because of padding */
+		memleak_padding(out, HDRLEN_KMALLOC, size);
 		if (out) {
 			out += HDRLEN_KMALLOC;
 			container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 0;
kernel/params.c +7 -1
index 91aea7a..b957b86 100644
@@ -547,6 +547,7 @@ static void __init kernel_param_sysfs_se
 					    unsigned int name_skip)
 {
 	struct module_kobject *mk;
+	struct module_param_attrs *mp;
 
 	mk = kzalloc(sizeof(struct module_kobject), GFP_KERNEL);
 	BUG_ON(!mk);
@@ -556,8 +557,13 @@ static void __init kernel_param_sysfs_se
 	kobject_set_name(&mk->kobj, name);
 	kobject_register(&mk->kobj);
 
+	mp = param_sysfs_setup(mk, kparam, num_params, name_skip);
+	/* this structure is not freed but the pointer is
+	 * lost. However, there are other pointers to its members and
+	 * the object has to be kept */
+	memleak_not_leak(mp);
 	/* no need to keep the kobject if no parameter is exported */
-	if (!param_sysfs_setup(mk, kparam, num_params, name_skip)) {
+	if (!mp) {
 		kobject_unregister(&mk->kobj);
 		kfree(mk);
 	}
mm/slab.c +4 -0
index 2752272..0949c45 100644
@@ -3413,6 +3413,10 @@ void *__alloc_percpu(size_t size)
 		memset(pdata->ptrs[i], 0, size);
 	}
 
+	/* the code below changes the value of the returned pointer
+	 * and kmemleak cannot find the original value during
+	 * scanning. It is marked as not being a leak */
+	memleak_not_leak(pdata);
 	/* Catch derefs w/o wrappers */
 	return (void *)(~(unsigned long)pdata);
 
net/core/dev.c +6 -0
index 066a60a..3b30423 100644
@@ -3193,6 +3193,12 @@ struct net_device *alloc_netdev(int size
 	dev = (struct net_device *)
 		(((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
 	dev->padded = (char *)dev - (char *)p;
+	/* kmemleak cannot guess the object type because the block
+	 * size is different from the object size. The stored pointer
+	 * is also different from the address of the allocated block
+	 * because of padding */
+	memleak_padding(p, dev->padded, sizeof(struct net_device));
+	memleak_typeid(p, struct net_device);
 
 	if (sizeof_priv)
 		dev->priv = netdev_priv(dev);
net/sched/sch_generic.c +6 -0
index d735f51..ae3e145 100644
@@ -438,6 +438,12 @@ struct Qdisc *qdisc_alloc(struct net_dev
 	memset(p, 0, size);
 	sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p);
 	sch->padded = (char *) sch - (char *) p;
+	/* kmemleak cannot guess the object type because the block
+	 * size is different from the object size. The stored pointer
+	 * is also different from the address of the allocated block
+	 * because of padding */
+	memleak_padding(p, sch->padded, sizeof(struct Qdisc));
+	memleak_typeid(p, struct Qdisc);
 
 	INIT_LIST_HEAD(&sch->list);
 	skb_queue_head_init(&sch->q);
#10 lore raw

Re: [PATCH 07/10] Remove some of the kmemleak false positives

drivers/base/platform.c struct platform_device *platform_device_ · line 171

Quoted 7 lines · Catalin Marinas
drivers/base/platform.c +3 -0
@@ -166,6 +166,9 @@ struct platform_device *platform_device_
        struct platform_object *pa;
 
        pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
+       /* kmemleak cannot guess the object type because the block
+        * size is different from the object size */
+       memleak_typeid(pa, struct platform_object);

AFAICT, we about 300 kmalloc and kzalloc calls in the kernel that would need this annotation. If we really can't fix the detector to deal with these, I would prefer we introduce another memory allocator function such as:

   void *kzalloc_extra(size_t obj_size, size_t nr_extra, gfp_t flags);

That would do the right thing for memleak too.

Pekka

#11 lore raw

Re: [PATCH 07/10] Remove some of the kmemleak false positives

Quoted 11 lines · Pekka Enberg

drivers/base/platform.c struct platform_device *platform_device_ · line 171

Quoted 7 lines · Catalin Marinas
drivers/base/platform.c +3 -0
@@ -166,6 +166,9 @@ struct platform_device *platform_device_
        struct platform_object *pa;
 
        pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
+       /* kmemleak cannot guess the object type because the block
+        * size is different from the object size */
+       memleak_typeid(pa, struct platform_object);

AFAICT, we about 300 kmalloc and kzalloc calls in the kernel that would need this annotation.

Most of them wouldn't need this annotation. The problem here is that the stored pointer is usually pointing to &pa->pdev.dev and "pa" is accessed via two container_of macros. There might be a few more cases like this which I didn't find but I don't expect a large number.

Quoted 1 line

If we really can't fix the detector to deal with these,

As I posted a few weeks ago, this cannot be done without introducing a lot of false negatives.

Quoted 6 lines

I would prefer we introduce another memory allocator function such as:

    void *kzalloc_extra(size_t obj_size, size_t nr_extra, gfp_t flags);

That would do the right thing for memleak too.

There is another case where extra bytes are added in front of the structure for alignment (the function could have "before" and "after" arguments). As I said above there aren't many places where kmemleak needs this.

As Ingo said in the past, we could better go for precise type identification/checking in kmalloc and both the kernel and kmemleak would benefit from this (but that's a pretty large patch).

Signature · 1 line
Catalin
#12 lore raw

PATCH 8/10 Keep the __init functions after initialization

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

This patch adds the CONFIG_DEBUG_KEEP_INIT option which preserves the .init.text section after initialization. Memory leaks happening during this phase can be more easily tracked.

---

 include/linux/init.h |    4 ++++
 lib/Kconfig.debug    |   10 ++++++++++
 2 files changed, 14 insertions(+), 0 deletions(-)
include/linux/init.h +4 -0
index 6667785..1590e9a 100644
@@ -40,7 +40,11 @@ #include <linux/compiler.h>
 
 /* These are for everybody (although not all archs will actually
    discard it in modules) */
+#ifdef CONFIG_DEBUG_KEEP_INIT
+#define __init
+#else
 #define __init		__attribute__ ((__section__ (".init.text")))
+#endif
 #define __initdata	__attribute__ ((__section__ (".init.data")))
 #define __exitdata	__attribute__ ((__section__(".exit.data")))
 #define __exit_call	__attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
lib/Kconfig.debug +10 -0
index 6c56be2..5013375 100644
@@ -171,6 +171,16 @@ config DEBUG_MEMLEAK_ORPHAN_FREEING
 	  information displayed allow an easier identification of
 	  false positives.
 
+config DEBUG_KEEP_INIT
+	bool "Do not free the __init functions"
+	default n
+	depends on DEBUG_MEMLEAK
+	help
+	  This option moves the __init functions out of the .init.text
+	  section and therefore they are no longer freed after the
+	  kernel initialization. It is useful for identifying memory
+	  leaks happening during the kernel or modules initialization.
+
 config DEBUG_PREEMPT
 	bool "Debug preemptible kernel"
 	depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
#13 lore raw

PATCH 9/10 Simple testing for kmemleak

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

This patch only contains some very simple testing at the moment. Proper testing will be needed.

---

 lib/Kconfig.debug |    9 ++++++
 mm/Makefile       |    1 +
 mm/memleak-test.c |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 93 insertions(+), 0 deletions(-)
lib/Kconfig.debug +9 -0
index 5013375..5240d62 100644
@@ -181,6 +181,15 @@ config DEBUG_KEEP_INIT
 	  kernel initialization. It is useful for identifying memory
 	  leaks happening during the kernel or modules initialization.
 
+config DEBUG_MEMLEAK_TEST
+	tristate "Test the kernel memory leak detector"
+	default n
+	depends on DEBUG_MEMLEAK
+	help
+	  Say Y here to build the test harness for the kernel memory
+	  leak detector. At the moment, this option enables a module
+	  that explicitly leaks memory.
+
 config DEBUG_PREEMPT
 	bool "Debug preemptible kernel"
 	depends on DEBUG_KERNEL && PREEMPT && TRACE_IRQFLAGS_SUPPORT
mm/Makefile +1 -0
index edccbc0..fd46a73 100644
@@ -24,3 +24,4 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += memory_h
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
 obj-$(CONFIG_DEBUG_MEMLEAK) += memleak.o
+obj-$(CONFIG_DEBUG_MEMLEAK_TEST) += memleak-test.o
mm/memleak-test.c new file +83 -0

83 lines not on this page · raw message

#14 lore raw

PATCH 10/10 Update the MAINTAINERS file for kmemleak

In reply to Catalin Marinas

From: Catalin Marinas <[email protected]>

---

 MAINTAINERS |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)
MAINTAINERS +6 -0
index 196a31c..808b75e 100644
@@ -1635,6 +1635,12 @@ W:	http://www.kerneljanitors.org/
 W:	http://sf.net/projects/kernel-janitor/
 S:	Maintained
 
+KERNEL MEMORY LEAK DETECTOR
+P:	Catalin Marinas
+M:	[email protected]
+W:	http://www.procode.org/
+S:	Maintained
+
 KERNEL NFSD
 P:	Neil Brown
 M:	[email protected]
#15 lore raw
In reply to Catalin Marinas

Hi Catalin,

Quoted 8 lines · Catalin Marinas

This is a new version (0.8) of the kernel memory leak detector. See the Documentation/kmemleak.txt file for a more detailed description. The patches are downloadable from (the whole patch or the broken-out series):

http://homepage.ntlworld.com/cmarinas/kmemleak/patch-2.6.18-rc1-kmemleak-0.8.bz2
http://homepage.ntlworld.com/cmarinas/kmemleak/patches-kmemleak-0.8.tar.bz2

Unfortunately, it doesn't compile for me.

make O=/dir
[..]
CC arch/i386/kernel/alternative.o
{standard input}: Assembler messages:
{standard input}:1954: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1955: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1959: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1960: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1964: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1965: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1972: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1973: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1979: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1980: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1984: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1985: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1989: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1990: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1997: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:1998: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2004: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2005: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2009: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2010: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2014: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2015: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2022: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
{standard input}:2023: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}
make[2]: *** [arch/i386/kernel/alternative.o] Error 1 make[1]: *** [arch/i386/kernel] Error 2
make: *** [_all] Error 2

Quoted 3 lines

--
Catalin
-

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#16 lore raw
Quoted 12 lines · Michal Piotrowski

Hi Catalin,

Quoted 8 lines · Catalin Marinas

This is a new version (0.8) of the kernel memory leak detector. See the Documentation/kmemleak.txt file for a more detailed description. The patches are downloadable from (the whole patch or the broken-out series):

http://homepage.ntlworld.com/cmarinas/kmemleak/patch-2.6.18-rc1-kmemleak-0.8.bz2
http://homepage.ntlworld.com/cmarinas/kmemleak/patches-kmemleak-0.8.tar.bz2

Quoted 5 lines

Unfortunately, it doesn't compile for me.

make O=/dir
[..]
CC arch/i386/kernel/alternative.o

[snip]

When I set DEBUG_KEEP_INIT=n everything works fine.

Here is the culprit 08-kmemleak-keep-init.patch

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#17 lore raw
Quoted 13 lines · Michal Piotrowski
Quoted 12 lines · Michal Piotrowski

Hi Catalin,

Quoted 8 lines · Catalin Marinas

This is a new version (0.8) of the kernel memory leak detector. See the Documentation/kmemleak.txt file for a more detailed description. The patches are downloadable from (the whole patch or the broken-out series):

http://homepage.ntlworld.com/cmarinas/kmemleak/patch-2.6.18-rc1-kmemleak-0.8.bz2
http://homepage.ntlworld.com/cmarinas/kmemleak/patches-kmemleak-0.8.tar.bz2

Quoted 8 lines
Quoted 5 lines

Unfortunately, it doesn't compile for me.

make O=/dir
[..]
CC arch/i386/kernel/alternative.o

[snip]

When I set DEBUG_KEEP_INIT=n everything works fine.

I was wrong. Here is the new error /usr/src/linux-work4/kernel/pid.c: In function 'pid_task':
/usr/src/linux-work4/kernel/pid.c:262: error: initializer element is not constant
/usr/src/linux-work4/kernel/pid.c:262: error: (near initialization for '__memleak_offset__container_of.offset')
make[2]: *** [kernel/pid.o] Error 1
make[1]: *** [kernel] Error 2
make: *** [_all] Error 2

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#18 lore raw
Quoted 4 lines · Michal Piotrowski
Quoted 1 line · Michal Piotrowski

When I set DEBUG_KEEP_INIT=n everything works fine.

I was wrong.

You mean the previous e-mail wasn't a kmemleak bug?

Quoted 9 lines

Here is the new error
/usr/src/linux-work4/kernel/pid.c: In function 'pid_task':
/usr/src/linux-work4/kernel/pid.c:262: error: initializer element is not constant
/usr/src/linux-work4/kernel/pid.c:262: error: (near initialization for '__memleak_offset__container_of.offset')
make[2]: *** [kernel/pid.o] Error 1
make[1]: *** [kernel] Error 2
make: *** [_all] Error 2

That's a bug in gcc-4. The __builtin_constant_p() function always returns true even when the argument is not a constant. You could try a gcc-3.4 or a patched gcc.

Signature · 1 line
Catalin
#19 lore raw
Quoted 7 lines · Catalin Marinas
Quoted 4 lines · Michal Piotrowski
Quoted 1 line · Michal Piotrowski

When I set DEBUG_KEEP_INIT=n everything works fine.

I was wrong.

You mean the previous e-mail wasn't a kmemleak bug?

It is kmemleak bug. I wrote "I was wrog" concerning "everything works fine" :)

Quoted 11 lines
Quoted 10 lines

Here is the new error
/usr/src/linux-work4/kernel/pid.c: In function 'pid_task':
/usr/src/linux-work4/kernel/pid.c:262: error: initializer element is not constant
/usr/src/linux-work4/kernel/pid.c:262: error: (near initialization for '__memleak_offset__container_of.offset')
make[2]: *** [kernel/pid.o] Error 1
make[1]: *** [kernel] Error 2
make: *** [_all] Error 2

Quoted 1 line

That's a bug in gcc-4.

Yes of course. I forgot about this.

Quoted 7 lines

The __builtin_constant_p() function always
returns true even when the argument is not a constant. You could try a gcc-3.4 or a patched gcc.

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#20 lore raw
In reply to Catalin Marinas
Quoted 18 lines · Catalin Marinas
Quoted 4 lines · Michal Piotrowski
Quoted 1 line · Michal Piotrowski

When I set DEBUG_KEEP_INIT=n everything works fine.

I was wrong.

You mean the previous e-mail wasn't a kmemleak bug?

Quoted 9 lines

Here is the new error
/usr/src/linux-work4/kernel/pid.c: In function 'pid_task':
/usr/src/linux-work4/kernel/pid.c:262: error: initializer element is not constant
/usr/src/linux-work4/kernel/pid.c:262: error: (near initialization for '__memleak_offset__container_of.offset')
make[2]: *** [kernel/pid.o] Error 1
make[1]: *** [kernel] Error 2
make: *** [_all] Error 2

Quoted 3 lines

That's a bug in gcc-4. The __builtin_constant_p() function always returns true even when the argument is not a constant. You could try a gcc-3.4 or a patched gcc.

Which gcc versions are affected by this?
--
Joseph Fannin
[email protected]

"Bull in pure form is rare; there is usually some contamination by data."
-- William Graves Perry Jr.

#21 lore raw
Quoted 8 lines · Joseph Fannin
Quoted 3 lines · Catalin Marinas

That's a bug in gcc-4. The __builtin_constant_p() function always returns true even when the argument is not a constant. You could try a gcc-3.4 or a patched gcc.

Which gcc versions are affected by this?

From gcc-4.0 I think but I don't know when/if it was fixed in the

latest. I use CodeSourcery's toolchain and they fixed in in gcc-4.1 but that's with their own patches. Try to compile the code below. It should work if the toolchain is OK:

       #include <stdlib.h>

       #define EXPR    atoi(argv[1])

       int main(int argc, char *argv[])
       {
           static int a[] = {
               __builtin_constant_p(EXPR) ? EXPR : 0
           };

           return a[0];
       }
Signature · 1 line
Catalin
#22 lore raw
Quoted 10 lines · Catalin Marinas
Quoted 6 lines · Joseph Fannin
Quoted 3 lines · Catalin Marinas

That's a bug in gcc-4. The __builtin_constant_p() function always returns true even when the argument is not a constant. You could try a gcc-3.4 or a patched gcc.

Which gcc versions are affected by this?

From gcc-4.0 I think but I don't know when/if it was fixed in the latest.

gcc-4.2 --version
gcc-4.2 (GCC) 4.2.0 20060701 (experimental)

works fine for me.

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#23 lore raw
In reply to Catalin Marinas
Quoted 13 lines · Catalin Marinas
Quoted 6 lines · Joseph Fannin
Quoted 3 lines · Catalin Marinas

That's a bug in gcc-4. The __builtin_constant_p() function always returns true even when the argument is not a constant. You could try a gcc-3.4 or a patched gcc.

Which gcc versions are affected by this?

From gcc-4.0 I think but I don't know when/if it was fixed in the latest. I use CodeSourcery's toolchain and they fixed in in gcc-4.1 but that's with their own patches. Try to compile the code below. It should work if the toolchain is OK:

Quoted 12 lines
       #include <stdlib.h>

       #define EXPR    atoi(argv[1])

       int main(int argc, char *argv[])
       {
           static int a[] = {
               __builtin_constant_p(EXPR) ? EXPR : 0
           };

           return a[0];
       }

Fails with gcc-4.1.1-7 from Fedora Core development.

Signature · 4 lines
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513
#24 lore raw
In reply to Michal Piotrowski
Quoted 8 lines · Michal Piotrowski

Unfortunately, it doesn't compile for me.

make O=/dir
[..]
CC arch/i386/kernel/alternative.o
{standard input}: Assembler messages:
{standard input}:1954: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}

I don't get any error (and kmemleak doesn't touch this file). Is this with the 2.6.18-rc1 kernel?

Signature · 1 line
Catalin
#25 lore raw
Quoted 10 lines · Catalin Marinas
Quoted 8 lines · Michal Piotrowski

Unfortunately, it doesn't compile for me.

make O=/dir
[..]
CC arch/i386/kernel/alternative.o
{standard input}: Assembler messages:
{standard input}:1954: Error: can't resolve .data' {.data section} - .Ltext0' {.text section}

Quoted 2 lines

I don't get any error (and kmemleak doesn't touch this file). Is this with the 2.6.18-rc1 kernel?

It's a gcc 4.1 issue
gcc --version
gcc (GCC) 4.1.1 20060525 (Red Hat 4.1.1-1)

With gcc 3.4 it build.

Quoted 4 lines

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#26 lore raw
Quoted 1 line · Michal Piotrowski

With gcc 3.4 it build.

Could you try with CONFIG_DEBUG_KEEP_INIT=y and gcc-3.4? It seems to work OK for me. Maybe I miss something but just defining an empty __init shouldn't cause problems.

Thanks.

Signature · 1 line
Catalin
#27 lore raw
Quoted 5 lines · Catalin Marinas
Quoted 1 line · Michal Piotrowski

With gcc 3.4 it build.

Could you try with CONFIG_DEBUG_KEEP_INIT=y and gcc-3.4? It seems to work OK for me.

It builds fine.

System hangs when I try "cat /sys/kernel/debug/memleak". Here is what I found in a log file.

Jul 11 15:40:13 ltg01-fedora kernel:  [<c0106e09>] show_trace_log_lvl+0x54/0xff
Jul 11 15:40:11 ltg01-fedora kernel:  [<c0106ec1>] show_trace+0xd/0xf
Jul 11 15:40:12 ltg01-fedora kernel:  [<c0106f93>] dump_stack+0x17/0x19
Jul 11 15:40:12 ltg01-fedora kernel:  [<c017572c>] memleak_free+0x10e/0x183
Jul 11 15:40:13 ltg01-fedora kernel:  [<c01734c2>] __cache_free+0x1e/0x5a
Jul 11 15:40:13 ltg01-fedora kernel:  [<c0173a42>] kmem_cache_free+0x54/0x6e
Jul 11 15:40:11 ltg01-fedora kernel:  [<c01205cd>] pgd_free+0xf/0x12
Jul 11 15:40:12 ltg01-fedora kernel:  [<c0127254>] __mmdrop+0x1d/0x33
Jul 11 15:40:13 ltg01-fedora kernel:  [<c02f1d32>] schedule+0x64a/0x6a9
Jul 11 15:40:14 ltg01-fedora kernel:  [<fd962493>] evdev_read+0xe2/0x174 [evdev]
Jul 11 15:40:11 ltg01-fedora kernel:  [<c0177fb7>] vfs_read+0xa9/0x151
Jul 11 15:40:12 ltg01-fedora kernel:  [<c01782d7>] sys_read+0x3b/0x60
Jul 11 15:40:13 ltg01-fedora kernel:  [<c0105ef1>] sysenter_past_esp+0x56/0x8d
Jul 11 15:40:13 ltg01-fedora kernel:  [<b7ff8410>] 0xb7ff8410
Jul 11 15:40:13 ltg01-fedora kernel: kmemleak: pointer 0xf24ad000:
Jul 11 15:40:13 ltg01-fedora kernel:   trace:
Jul 11 15:40:10 ltg01-fedora kernel:     c01735c2: <kmem_cache_alloc>
Jul 11 15:40:11 ltg01-fedora kernel:     c01205bc: <pgd_alloc>
Jul 11 15:40:12 ltg01-fedora kernel:     c01271df: <mm_init>
Jul 11 15:40:12 ltg01-fedora kernel:     c01273f1: <dup_mm>
Jul 11 15:40:11 ltg01-fedora kernel:     c01276b5: <copy_mm>
Jul 11 15:40:11 ltg01-fedora kernel:     c012853c: <copy_process>
Jul 11 15:40:12 ltg01-fedora kernel:     c0128c46: <do_fork>
Jul 11 15:40:13 ltg01-fedora kernel:     c0104cee: <sys_clone>
Jul 11 15:40:12 ltg01-fedora kernel: kmemleak: freeing orphan pointer 0xf24ad000
Jul 11 15:40:12 ltg01-fedora kernel:  [<c0106e09>] show_trace_log_lvl+0x54/0xff
Jul 11 15:40:11 ltg01-fedora kernel:  [<c0106ec1>] show_trace+0xd/0xf
Jul 11 15:40:13 ltg01-fedora kernel:  [<c0106f93>] dump_stack+0x17/0x19
Jul 11 15:40:12 ltg01-fedora kernel:  [<c017572c>] memleak_free+0x10e/0x183
Jul 11 15:40:11 ltg01-fedora kernel:  [<c01734c2>] __cache_free+0x1e/0x5a
Jul 11 15:40:12 ltg01-fedora kernel:  [<c0173a42>] kmem_cache_free+0x54/0x6e
Jul 11 15:40:13 ltg01-fedora kernel:  [<c028f9d9>] uhci_free_urb_priv+0x7a/0x82
Jul 11 15:40:12 ltg01-fedora kernel:  [<c0290803>] uhci_giveback_urb+0xb3/0x148
Jul 11 15:40:12 ltg01-fedora kernel:  [<c029093a>] uhci_scan_qh+0xa2/0x18f
Jul 11 15:40:46 ltg01-fedora kernel:  [<c0290b71>] uhci_scan_schedule+0x89/0x116
Jul 11 15:41:03 ltg01-fedora kernel:  [<c02916ce>] uhci_irq+0x108/0x120
Jul 11 15:42:16 ltg01-fedora kernel:  [<c0282568>] usb_hcd_irq+0x2a/0x53
Jul 11 15:42:29 ltg01-fedora kernel:  [<c0156cd8>] handle_IRQ_event+0x1f/0x4c
Jul 11 15:42:51 ltg01-fedora kernel:  [<c0156d92>] __do_IRQ+0x8d/0xe9
Jul 11 15:43:08 ltg01-fedora kernel:  [<c01086ee>] do_IRQ+0xc2/0xd4
Jul 11 15:46:22 ltg01-fedora kernel:  [<c010695d>] common_interrupt+0x25/0x2c
Jul 11 15:47:31 ltg01-fedora kernel:  [<c012ed44>] __do_softirq+0x65/0xea
Jul 11 15:47:43 ltg01-fedora kernel:  [<c01087f5>] do_softirq+0x60/0xc5
Jul 11 15:48:17 ltg01-fedora kernel:  [<c012ee11>] irq_exit+0x48/0x55
Jul 11 15:49:09 ltg01-fedora kernel:  [<c011a105>]

smp_apic_timer_interrupt+0x69/0x6c

http://www.stardust.webpages.pl/files/o_bugs/kml/kml-config4

Quoted 5 lines

Thanks.

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#28 lore raw
Quoted 2 lines · Michal Piotrowski

System hangs when I try "cat /sys/kernel/debug/memleak". Here is what I found in a log file.

Can you disable DEBUG_MEMLEAK_ORPHAN_FREEING? That's mainly used for debugging but I don't think it is was causing the hang. I haven't changed the locking mechanism since version 0.7 but maybe some other bug made its way in.

Signature · 1 line
Catalin
#29 lore raw
Quoted 8 lines · Catalin Marinas
Quoted 2 lines · Michal Piotrowski

System hangs when I try "cat /sys/kernel/debug/memleak". Here is what I found in a log file.

Can you disable DEBUG_MEMLEAK_ORPHAN_FREEING? That's mainly used for debugging but I don't think it is was causing the hang. I haven't changed the locking mechanism since version 0.7 but maybe some other bug made its way in.

It is DEBUG_MEMLEAK_ORPHAN_FREEING issue. Disabling it solved the problem.

orphan pointer 0xc6113bec (size 28):
c017392a: <__kmalloc_track_caller>
c01631b1: <__kzalloc>
c010b7d7: <legacy_init_iomem_resources>
c010b89c: <request_standard_resources>
c0100b8b: <do_initcalls>
c0100c3d: <do_basic_setup>
c0100cdb: <init>

This is most common
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a88c2: <sock_sendmsg>
c02a9c7a: <sys_sendto>

cat /tmp/ml.txt | grep -c selinux_socket_getpeersec_dgram 8442

Quoted 4 lines

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#30 lore raw
Quoted 2 lines · Michal Piotrowski

It is DEBUG_MEMLEAK_ORPHAN_FREEING issue. Disabling it solved the problem.

OK, thanks for trying.

Quoted 8 lines

orphan pointer 0xc6113bec (size 28):
c017392a: <__kmalloc_track_caller>
c01631b1: <__kzalloc>
c010b7d7: <legacy_init_iomem_resources>
c010b89c: <request_standard_resources>
c0100b8b: <do_initcalls>
c0100c3d: <do_basic_setup>
c0100cdb: <init>

That's a real leak. I posted a patch last night that solves this issue
- http://lkml.org/lkml/2006/7/10/370

Quoted 10 lines

This is most common
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a88c2: <sock_sendmsg>
c02a9c7a: <sys_sendto>

Looking at the call trace, the pointer to the memory allocated in context_struct_to_string() is stored in the "cb" variable in struct sk_buff (argument passed to selinux_socket_getpeersec_dgram from unix_get_peersec_dgram).

This pointer should be found when scanning the "struct sk_buff" blocks, unless you also get a comparable number of "struct sk_buff" reports (from __alloc_skb). If not, it might be a real leak.

Signature · 1 line
Catalin
#31 lore raw
Quoted 11 lines · Catalin Marinas
Quoted 8 lines

orphan pointer 0xc6113bec (size 28):
c017392a: <__kmalloc_track_caller>
c01631b1: <__kzalloc>
c010b7d7: <legacy_init_iomem_resources>
c010b89c: <request_standard_resources>
c0100b8b: <do_initcalls>
c0100c3d: <do_basic_setup>
c0100cdb: <init>

That's a real leak. I posted a patch last night that solves this issue
- http://lkml.org/lkml/2006/7/10/370

Thanks.

Quoted 12 lines
Quoted 11 lines

This is most common
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a88c2: <sock_sendmsg>
c02a9c7a: <sys_sendto>

Quoted 8 lines

Looking at the call trace, the pointer to the memory allocated in context_struct_to_string() is stored in the "cb" variable in struct sk_buff (argument passed to selinux_socket_getpeersec_dgram from unix_get_peersec_dgram).

This pointer should be found when scanning the "struct sk_buff" blocks, unless you also get a comparable number of "struct sk_buff" reports (from __alloc_skb). If not, it might be a real leak.

So if we got 3970
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a88c2: <sock_sendmsg>
c02a9c7a: <sys_sendto>

and 4673
orphan pointer 0xf4249488 (size 29):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a8d68: <do_sock_write>
c02a8e85: <sock_aio_write>

It's not a memleak?

http://www.stardust.webpages.pl/files/o_bugs/kml/ml3.txt

Quoted 4 lines

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#32 lore raw
Quoted 14 lines · Michal Piotrowski
Quoted 8 lines · Catalin Marinas

Looking at the call trace, the pointer to the memory allocated in context_struct_to_string() is stored in the "cb" variable in struct sk_buff (argument passed to selinux_socket_getpeersec_dgram from unix_get_peersec_dgram).

This pointer should be found when scanning the "struct sk_buff" blocks, unless you also get a comparable number of "struct sk_buff" reports (from __alloc_skb). If not, it might be a real leak.

So if we got 3970
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>

[...]

Quoted 4 lines

and 4673
orphan pointer 0xf4249488 (size 29):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>

[...]

Quoted 1 line

It's not a memleak?

Not exactly. What I meant is that if you have a corresponding number of reports from __alloc_skb, maybe they were false positives and the block wasn't scanned leading to other false positive reports

It looks like there are some reports in __alloc_skb. Please try the attached patch.

Thanks.

Signature · 1 line
Catalin

Clear the false positive in __alloc_skb

From: Catalin Marinas <[email protected]>

This happens when fclone is 1 because the allocated size is different from the struct sk_buff one and therefore the pointer aliases are not correctly determined.

---

 net/core/skbuff.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
net/core/skbuff.c +3 -0
index 44f6a18..ee4fd9b 100644
@@ -158,6 +158,9 @@ struct sk_buff *__alloc_skb(unsigned int
 
 	/* Get the HEAD */
 	skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA);
+	/* the skbuff_fclone_cache contains objects larger than
+	 * "struct sk_buff" and kmemleak cannot guess the type */
+	memleak_typeid(skb, struct sk_buff);
 	if (!skb)
 		goto out;
 
#33 lore raw
Quoted 11 lines · Catalin Marinas
Quoted 4 lines · Michal Piotrowski

So if we got 3970
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>

[...]

Quoted 4 lines

and 4673
orphan pointer 0xf4249488 (size 29):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>

[...]

Quoted 8 lines
Quoted 1 line

It's not a memleak?

Not exactly. What I meant is that if you have a corresponding number of reports from __alloc_skb, maybe they were false positives and the block wasn't scanned leading to other false positive reports

It looks like there are some reports in __alloc_skb. Please try the attached patch.

Here is the result
http://www.stardust.webpages.pl/files/o_bugs/kml/ml4.txt

Quoted 8 lines

Thanks.

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#34 lore raw

Michal,

Quoted 6 lines · Michal Piotrowski
Quoted 2 lines · Catalin Marinas

It looks like there are some reports in __alloc_skb. Please try the attached patch.

Here is the result
http://www.stardust.webpages.pl/files/o_bugs/kml/ml4.txt

Some of the __alloc_skb disappeared but there are still a lot of context_struct_to_string (812). Could you let it running for a bit to get more reported leaks (few thousands) and send me the contents of the /proc/slabinfo file (together with the memleak file)? I want to make sure whether it is a kmemleak problem or not.

Thanks.

Signature · 1 line
Catalin
#35 lore raw

Hi Catalin,

Quoted 7 lines · Catalin Marinas

Michal,

Quoted 4 lines · Michal Piotrowski
Quoted 2 lines · Catalin Marinas

It looks like there are some reports in __alloc_skb. Please try the attached patch.

Quoted 8 lines
Quoted 2 lines

Here is the result
http://www.stardust.webpages.pl/files/o_bugs/kml/ml4.txt

Some of the __alloc_skb disappeared but there are still a lot of context_struct_to_string (812). Could you let it running for a bit to get more reported leaks (few thousands) and send me the contents of the /proc/slabinfo file (together with the memleak file)? I want to make sure whether it is a kmemleak problem or not.

Ok.

BTW I have _very_ annoying soft lockup. Can you fix that?

Jul 12 13:15:47 ltg01-fedora kernel: printk: 1527 messages suppressed.
Jul 12 13:15:47 ltg01-fedora kernel: ipt_hook: happy cracking.
Jul 12 13:15:56 ltg01-fedora kernel: printk: 1631 messages suppressed.
Jul 12 13:15:56 ltg01-fedora kernel: Neighbour table overflow.

I don't know why, but clock goes mad.

Jul 12 14:08:21 ltg01-fedora kernel: BUG: soft lockup detected on CPU#0!
Jul 12 14:08:19 ltg01-fedora kernel:  [<c0106e09>] show_trace_log_lvl+0x54/0xff
Jul 12 14:08:20 ltg01-fedora kernel:  [<c0106ec1>] show_trace+0xd/0xf
Jul 12 14:08:19 ltg01-fedora kernel:  [<c0106f93>] dump_stack+0x17/0x19
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0156793>] softlockup_tick+0x9a/0xae
Jul 12 14:08:21 ltg01-fedora kernel:  [<c01332ce>] run_local_timers+0x12/0x14
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0133126>]
update_process_times+0x40/0x65
Jul 12 14:08:20 ltg01-fedora kernel:  [<c011a100>]
smp_apic_timer_interrupt+0x64/0x6c
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0106a1e>]
apic_timer_interrupt+0x2a/0x30
Jul 12 14:08:18 ltg01-fedora kernel:  [<c0116b71>] smp_call_function+0xcc/0xf9
Jul 12 14:08:20 ltg01-fedora kernel:  [<c012f6b6>] on_each_cpu+0x24/0x5e
Jul 12 14:08:21 ltg01-fedora kernel:  [<c017a63f>] invalidate_bh_lrus+0x16/0x18
Jul 12 14:08:21 ltg01-fedora kernel:  [<c017978c>] invalidate_bdev+0xb/0x1c
Jul 12 14:08:19 ltg01-fedora smartd[1736]: Device: /dev/hda, 1 Offline
uncorrectable sectors
Jul 12 14:08:21 ltg01-fedora kernel:  [<c017e81d>] kill_bdev+0x10/0x25
Jul 12 14:08:20 ltg01-fedora kernel:  [<c017fa7f>] __blkdev_put+0x43/0x157
Jul 12 14:08:21 ltg01-fedora kernel:  [<c017fb9d>] blkdev_put+0xa/0xc
Jul 12 14:08:20 ltg01-fedora kernel:  [<c017fbd6>] blkdev_close+0x28/0x2b
Jul 12 14:08:20 ltg01-fedora kernel:  [<c0178e20>] __fput+0xb2/0x18c
Jul 12 14:08:20 ltg01-fedora kernel:  [<c0178d6c>] fput+0x17/0x19
Jul 12 14:08:20 ltg01-fedora kernel:  [<c01778c5>] filp_close+0x4e/0x58
Jul 12 14:08:22 ltg01-fedora kernel:  [<c0177931>] sys_close+0x62/0x7a
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0105ef1>] sysenter_past_esp+0x56/0x8d
Jul 12 14:08:22 ltg01-fedora kernel:  [<b7fc1410>] 0xb7fc1410
Jul 12 14:08:22 ltg01-fedora kernel: BUG: soft lockup detected on CPU#1!
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0106e09>] show_trace_log_lvl+0x54/0xff
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0106ec1>] show_trace+0xd/0xf
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0106f93>] dump_stack+0x17/0x19
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0156793>] softlockup_tick+0x9a/0xae
Jul 12 14:08:20 ltg01-fedora kernel:  [<c01332ce>] run_local_timers+0x12/0x14
Jul 12 14:08:20 ltg01-fedora kernel:  [<c0133126>]
update_process_times+0x40/0x65
Jul 12 14:08:20 ltg01-fedora kernel:  [<c011a100>]
smp_apic_timer_interrupt+0x64/0x6c
Jul 12 14:08:22 ltg01-fedora kernel:  [<c0106a1e>]
apic_timer_interrupt+0x2a/0x30
Jul 12 14:08:20 ltg01-fedora kernel:  [<c02f3dd1>] _spin_unlock_irq+0x28/0x43
Jul 12 14:08:20 ltg01-fedora kernel:  [<c012dcb2>] do_setitimer+0x145/0x4ce
Jul 12 14:08:20 ltg01-fedora kernel:  [<c012e070>] alarm_setitimer+0x35/0x54
Jul 12 14:08:22 ltg01-fedora kernel:  [<c0133371>] sys_alarm+0xb/0xd
Jul 12 14:08:21 ltg01-fedora kernel:  [<c0105ef1>] sysenter_past_esp+0x56/0x8d
Jul 12 14:08:21 ltg01-fedora kernel:  [<b7f83410>] 0xb7f83410
Jul 12 14:08:21 ltg01-fedora kernel: printk: 309 messages suppressed.
Jul 12 14:08:22 ltg01-fedora kernel: ipt_hook: happy cracking.

Here is actual config file
http://www.stardust.webpages.pl/files/o_bugs/kml/kml-config5

Quoted 6 lines

Thanks.

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#36 lore raw
Quoted 10 lines · Michal Piotrowski

BTW I have _very_ annoying soft lockup. Can you fix that?

Jul 12 13:15:47 ltg01-fedora kernel: printk: 1527 messages suppressed.
Jul 12 13:15:47 ltg01-fedora kernel: ipt_hook: happy cracking.
Jul 12 13:15:56 ltg01-fedora kernel: printk: 1631 messages suppressed.
Jul 12 13:15:56 ltg01-fedora kernel: Neighbour table overflow.

I don't know why, but clock goes mad.

Jul 12 14:08:21 ltg01-fedora kernel: BUG: soft lockup detected on CPU#0!

Maybe the soft lockup report is cause by the clock change (it doesn't show any kmemleak functions in the backtrace). You could change SCAN_BLOCK_SIZE in memleak.c to a smaller value as the scanning is done with the interrupt disabled.

I'll try tomorrow on my platforms with the soft lockup enabled.

Signature · 1 line
Catalin
#37 lore raw
Quoted 8 lines · Catalin Marinas
Quoted 7 lines · Michal Piotrowski

BTW I have _very_ annoying soft lockup. Can you fix that?

Jul 12 13:15:47 ltg01-fedora kernel: printk: 1527 messages suppressed.
Jul 12 13:15:47 ltg01-fedora kernel: ipt_hook: happy cracking.
Jul 12 13:15:56 ltg01-fedora kernel: printk: 1631 messages suppressed.
Jul 12 13:15:56 ltg01-fedora kernel: Neighbour table overflow.
Quoted 6 lines
Quoted 3 lines

I don't know why, but clock goes mad.

Jul 12 14:08:21 ltg01-fedora kernel: BUG: soft lockup detected on CPU#0!

Maybe the soft lockup report is cause by the clock change (it doesn't show any kmemleak functions in the backtrace).

I can't reproduce this on clean 2.6.18-rc1.

Quoted 3 lines

You could change
SCAN_BLOCK_SIZE in memleak.c to a smaller value as the scanning is done with the interrupt disabled.

I have tried
#define SCAN_BLOCK_SIZE 2048
and
#define SCAN_BLOCK_SIZE 1024
Unfortunately it doesn't change anything.

Quoted 1 line

I'll try tomorrow on my platforms with the soft lockup enabled.

Please try something like this
on tty1
isic -s rand -d your ip (http://www.packetfactory.net/Projects/ISIC/)
on tty2
kml_collector (http://www.stardust.webpages.pl/files/o_bugs/kml/ml/kml_collector.sh)

(I have tried to read random files from /sys on vanilla kernel, but I can't reproduce that lockup)

Quoted 4 lines

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#38 lore raw
Quoted 5 lines · Michal Piotrowski

I have tried
#define SCAN_BLOCK_SIZE 2048
and
#define SCAN_BLOCK_SIZE 1024
Unfortunately it doesn't change anything.

I realised that this only reduces the time running with interrupts disabled but won't solve the soft lockup.

Quoted 8 lines

Please try something like this
on tty1
isic -s rand -d your ip (http://www.packetfactory.net/Projects/ISIC/)
on tty2
kml_collector (http://www.stardust.webpages.pl/files/o_bugs/kml/ml/kml_collector.sh)

(I have tried to read random files from /sys on vanilla kernel, but I can't reproduce that lockup)

Couldn't get it on my (embedded) platform but I think that's because there are only a few reports in the memleak file. You have thousands of reports and I think reading the memleak file is causing the soft lockup.

Until we identify the leak (or false positive), you can use the attached patch to supress the reports for context_struct_to_string. Hopefully, this should eliminate the soft lockup as well.

Signature · 1 line
Catalin

Ignore the (real) leak report in context_struct_to_string

From: Catalin Marinas <[email protected]>

This might be a real leak but, because of the amount of information kmemleak reports, we ignore it for now to allow testing of other parts of kmemleak.

---

 security/selinux/ss/services.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
security/selinux/ss/services.c +3 -0
index d2e80e6..f8cf098 100644
@@ -548,6 +548,9 @@ static int context_struct_to_string(stru
 
 	/* Allocate space for the context; caller must free this space. */
 	scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
+	/* This might be a real leak but we ignore it for now to allow
+	 * testing other parts of kmemleak */
+	memleak_not_leak(scontextp);
 	if (!scontextp) {
 		return -ENOMEM;
 	}
#39 lore raw

Hi Catalin,

Quoted 10 lines · Catalin Marinas
Quoted 8 lines · Michal Piotrowski

Please try something like this
on tty1
isic -s rand -d your ip (http://www.packetfactory.net/Projects/ISIC/)
on tty2
kml_collector (http://www.stardust.webpages.pl/files/o_bugs/kml/ml/kml_collector.sh)

(I have tried to read random files from /sys on vanilla kernel, but I can't reproduce that lockup)

Quoted 8 lines

Couldn't get it on my (embedded) platform but I think that's because there are only a few reports in the memleak file. You have thousands of reports and I think reading the memleak file is causing the soft lockup.

Until we identify the leak (or false positive), you can use the attached patch to supress the reports for context_struct_to_string. Hopefully, this should eliminate the soft lockup as well.

Thanks.

After applying context_struct_to_string-not-leak.patch and reverting alloc_skb-false-positive.patch I haven't noticed that soft lockup.

Here is something new
orphan pointer 0xf40d61ac (size 1536):
c017392a: <__kmalloc_track_caller>
c01631b1: <__kzalloc>
f98869cd: <skge_ring_alloc>
f9888a1d: <skge_up>
c02b17b6: <dev_open>
c02b2e94: <dev_change_flags>
c02e6e17: <devinet_ioctl>
c02e8a02: <inet_ioctl>

http://www.stardust.webpages.pl/files/o_bugs/kml/ml2/
http://www.stardust.webpages.pl/files/o_bugs/kml/ml3/

After alloc_skb-false-positive.patch revert
http://www.stardust.webpages.pl/files/o_bugs/kml/ml4/

Quoted 3 lines

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#40 lore raw
Quoted 2 lines · Michal Piotrowski

After applying context_struct_to_string-not-leak.patch and reverting alloc_skb-false-positive.patch I haven't noticed that soft lockup.

You still need the apply alloc_skb-false-positive.patch as it just avoids a false positive (I'll add it to kmemleak 0.9). Does anything change with this (and the context_struct_... one)?

Quoted 10 lines

Here is something new
orphan pointer 0xf40d61ac (size 1536):
c017392a: <__kmalloc_track_caller>
c01631b1: <__kzalloc>
f98869cd: <skge_ring_alloc>
f9888a1d: <skge_up>
c02b17b6: <dev_open>
c02b2e94: <dev_change_flags>
c02e6e17: <devinet_ioctl>
c02e8a02: <inet_ioctl>

This looks like a leak but I couldn't find anything obvious with the code. I'll keep looking.

Quoted 2 lines

http://www.stardust.webpages.pl/files/o_bugs/kml/ml2/
http://www.stardust.webpages.pl/files/o_bugs/kml/ml3/

I would also need to investigate why the report shows some orphan pointers without any back-trace information. It seems to disappear after a while.

Thanks.

Signature · 1 line
Catalin
#41 lore raw
In reply to Catalin Marinas
Quoted 7 lines · Catalin Marinas

Michal,

Quoted 4 lines · Michal Piotrowski
Quoted 2 lines · Catalin Marinas

It looks like there are some reports in __alloc_skb. Please try the attached patch.

Quoted 8 lines
Quoted 2 lines

Here is the result
http://www.stardust.webpages.pl/files/o_bugs/kml/ml4.txt

Some of the __alloc_skb disappeared but there are still a lot of context_struct_to_string (812). Could you let it running for a bit to get more reported leaks (few thousands) and send me the contents of the /proc/slabinfo file (together with the memleak file)? I want to make sure whether it is a kmemleak problem or not.

Here is a slabinfo from current 2.6.18-rc1-git4 and 2.6.18-rc1 + kmemleak http://www.stardust.webpages.pl/files/o_bugs/kml/slab.txt

I haven't seen that before
orphan pointer 0xf1283e34 (size 224):
c01735c2: <kmem_cache_alloc>
fdc8c5cf: <ip_conntrack_alloc>
fdc8c6a3: <init_conntrack>
fdc8c894: <ip_conntrack_in>
fdc8b652: <ip_conntrack_local>
c02c15bf: <nf_iterate>
c02c1630: <nf_hook_slow>
c02e127e: <raw_send_hdrinc>

http://www.stardust.webpages.pl/files/o_bugs/kml/ml5.txt (4MB)

Quoted 6 lines

Thanks.

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#42 lore raw
Quoted 2 lines · Michal Piotrowski

Here is a slabinfo from current 2.6.18-rc1-git4 and 2.6.18-rc1 + kmemleak http://www.stardust.webpages.pl/files/o_bugs/kml/slab.txt

Thanks. Does it make any difference if you enable CONFIG_DEBUG_MEMLEAK_TASK_STACKS? Also, if you save the memleak file periodically, do any of the context_struct_to_string reports disappear (I can investigate this if you upload a few ml60.txt, mk61.txt etc.)?

Quoted 10 lines

I haven't seen that before
orphan pointer 0xf1283e34 (size 224):
c01735c2: <kmem_cache_alloc>
fdc8c5cf: <ip_conntrack_alloc>
fdc8c6a3: <init_conntrack>
fdc8c894: <ip_conntrack_in>
fdc8b652: <ip_conntrack_local>
c02c15bf: <nf_iterate>
c02c1630: <nf_hook_slow>
c02e127e: <raw_send_hdrinc>

This looks like a false positive as the conntrack pointer is lost in init_conntrack and only a pointer conntrack->tuplehash[...].list is stored. This cannot be aliased via container_of because tuplehash_to_ctrack doesn't pass a constant argument to it and cannot be determined at compile time. Try the attached patch.

Note that you can get some false positives that might disappear after a while. This is because of the stacks scanning and also pointers stored in CPU registers, especially on SMP systems.

Thanks.

Signature · 1 line
Catalin
#43 lore raw
Quoted 8 lines · Catalin Marinas
Quoted 2 lines · Michal Piotrowski

Here is a slabinfo from current 2.6.18-rc1-git4 and 2.6.18-rc1 + kmemleak http://www.stardust.webpages.pl/files/o_bugs/kml/slab.txt

Thanks. Does it make any difference if you enable CONFIG_DEBUG_MEMLEAK_TASK_STACKS? Also, if you save the memleak file periodically, do any of the context_struct_to_string reports disappear (I can investigate this if you upload a few ml60.txt, mk61.txt etc.)?

Here are the results
http://www.stardust.webpages.pl/files/o_bugs/kml/ml/

Quoted 4 lines

--
Catalin

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)
#44 lore raw
Quoted 5 lines · Michal Piotrowski
Quoted 4 lines · Catalin Marinas
Quoted 2 lines · Michal Piotrowski

Here is a slabinfo from current 2.6.18-rc1-git4 and 2.6.18-rc1 + kmemleak http://www.stardust.webpages.pl/files/o_bugs/kml/slab.txt

Quoted 7 lines
Quoted 4 lines

Thanks. Does it make any difference if you enable CONFIG_DEBUG_MEMLEAK_TASK_STACKS? Also, if you save the memleak file periodically, do any of the context_struct_to_string reports disappear (I can investigate this if you upload a few ml60.txt, mk61.txt etc.)?

Here are the results
http://www.stardust.webpages.pl/files/o_bugs/kml/ml/

The context_struct_to_string leaks do not seem to disappear in subsequent ml?.txt files which makes me think it's a real leak.

Thanks for collecting these statistics.

Signature · 1 line
Catalin
#45 lore raw
In reply to Michal Piotrowski

Hi Catherine,

Quoted 11 lines · Michal Piotrowski

This is most common
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a88c2: <sock_sendmsg>
c02a9c7a: <sys_sendto>

Quoted 2 lines

cat /tmp/ml.txt | grep -c selinux_socket_getpeersec_dgram 8442

I'm looking into the above leak report from kmemleak (the back trace to the kmalloc function). The "datagram getpeersec" patch went in as commit 877ce7c1b3afd69a9b1caeb1b9964c992641f52a. Have you noticed any abnormal increase in the slab statistics (especially size-64)?

Thanks.

Signature · 1 line
Catalin
#46 lore raw

Catalin,

I am looking into this problem.

thanks,
Catherine

"Catalin Marinas" <[email protected]> wrote on 07/12/2006 06:33:54 AM:

Quoted 26 lines

Hi Catherine,

Quoted 11 lines · Michal Piotrowski

This is most common
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a88c2: <sock_sendmsg>
c02a9c7a: <sys_sendto>

Quoted 2 lines

cat /tmp/ml.txt | grep -c selinux_socket_getpeersec_dgram 8442

I'm looking into the above leak report from kmemleak (the back trace to the kmalloc function). The "datagram getpeersec" patch went in as commit 877ce7c1b3afd69a9b1caeb1b9964c992641f52a. Have you noticed any abnormal increase in the slab statistics (especially size-64)?

Thanks.

Signature · 1 line
Catalin
#47 lore raw
In reply to Catalin Marinas

Hi, Catalin,

I have identified the problem and will submit a fix soon. Could you let me know to which tree should I apply the fix against?

thanks,
Catherine

"Catalin Marinas" <[email protected]> wrote on 07/12/2006 06:33:54 AM:

Quoted 26 lines

Hi Catherine,

Quoted 11 lines · Michal Piotrowski

This is most common
orphan pointer 0xf5a6fd60 (size 39):
c0173822: <__kmalloc>
c01df500: <context_struct_to_string>
c01df679: <security_sid_to_context>
c01d7eee: <selinux_socket_getpeersec_dgram>
f884f019: <unix_get_peersec_dgram>
f8850698: <unix_dgram_sendmsg>
c02a88c2: <sock_sendmsg>
c02a9c7a: <sys_sendto>

Quoted 2 lines

cat /tmp/ml.txt | grep -c selinux_socket_getpeersec_dgram 8442

I'm looking into the above leak report from kmemleak (the back trace to the kmalloc function). The "datagram getpeersec" patch went in as commit 877ce7c1b3afd69a9b1caeb1b9964c992641f52a. Have you noticed any abnormal increase in the slab statistics (especially size-64)?

Thanks.

Signature · 1 line
Catalin
#48 lore raw

Hi Catherine,

Quoted 3 lines · Xiaolan Zhang

Hi, Catalin,

I have identified the problem and will submit a fix soon.

Great, thanks!

Quoted 2 lines

Could you let
me know to which tree should I apply the fix against?

2.6.18-rc1.

Quoted 4 lines

thanks,
Catherine

Regards,
Michal

Signature · 3 lines
Michal K. K. Piotrowski
LTG - Linux Testers Group
(http://www.stardust.webpages.pl/ltg/wiki/)