|
@@ -211,6 +211,9 @@ static signed long jiffies_scan_wait;
|
|
static int kmemleak_stack_scan = 1;
|
|
static int kmemleak_stack_scan = 1;
|
|
/* protects the memory scanning, parameters and debug/kmemleak file access */
|
|
/* protects the memory scanning, parameters and debug/kmemleak file access */
|
|
static DEFINE_MUTEX(scan_mutex);
|
|
static DEFINE_MUTEX(scan_mutex);
|
|
|
|
+/* setting kmemleak=on, will set this var, skipping the disable */
|
|
|
|
+static int kmemleak_skip_disable;
|
|
|
|
+
|
|
|
|
|
|
/*
|
|
/*
|
|
* Early object allocation/freeing logging. Kmemleak is initialized after the
|
|
* Early object allocation/freeing logging. Kmemleak is initialized after the
|
|
@@ -398,7 +401,9 @@ static struct kmemleak_object *lookup_object(unsigned long ptr, int alias)
|
|
object = prio_tree_entry(node, struct kmemleak_object,
|
|
object = prio_tree_entry(node, struct kmemleak_object,
|
|
tree_node);
|
|
tree_node);
|
|
if (!alias && object->pointer != ptr) {
|
|
if (!alias && object->pointer != ptr) {
|
|
- kmemleak_warn("Found object by alias");
|
|
|
|
|
|
+ pr_warning("Found object by alias at 0x%08lx\n", ptr);
|
|
|
|
+ dump_stack();
|
|
|
|
+ dump_object_info(object);
|
|
object = NULL;
|
|
object = NULL;
|
|
}
|
|
}
|
|
} else
|
|
} else
|
|
@@ -695,7 +700,7 @@ static void paint_ptr(unsigned long ptr, int color)
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
- * Make a object permanently as gray-colored so that it can no longer be
|
|
|
|
|
|
+ * Mark an object permanently as gray-colored so that it can no longer be
|
|
* reported as a leak. This is used in general to mark a false positive.
|
|
* reported as a leak. This is used in general to mark a false positive.
|
|
*/
|
|
*/
|
|
static void make_gray_object(unsigned long ptr)
|
|
static void make_gray_object(unsigned long ptr)
|
|
@@ -838,10 +843,19 @@ out:
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
}
|
|
}
|
|
|
|
|
|
-/*
|
|
|
|
- * Memory allocation function callback. This function is called from the
|
|
|
|
- * kernel allocators when a new block is allocated (kmem_cache_alloc, kmalloc,
|
|
|
|
- * vmalloc etc.).
|
|
|
|
|
|
+/**
|
|
|
|
+ * kmemleak_alloc - register a newly allocated object
|
|
|
|
+ * @ptr: pointer to beginning of the object
|
|
|
|
+ * @size: size of the object
|
|
|
|
+ * @min_count: minimum number of references to this object. If during memory
|
|
|
|
+ * scanning a number of references less than @min_count is found,
|
|
|
|
+ * the object is reported as a memory leak. If @min_count is 0,
|
|
|
|
+ * the object is never reported as a leak. If @min_count is -1,
|
|
|
|
+ * the object is ignored (not scanned and not reported as a leak)
|
|
|
|
+ * @gfp: kmalloc() flags used for kmemleak internal memory allocations
|
|
|
|
+ *
|
|
|
|
+ * This function is called from the kernel allocators when a new object
|
|
|
|
+ * (memory block) is allocated (kmem_cache_alloc, kmalloc, vmalloc etc.).
|
|
*/
|
|
*/
|
|
void __ref kmemleak_alloc(const void *ptr, size_t size, int min_count,
|
|
void __ref kmemleak_alloc(const void *ptr, size_t size, int min_count,
|
|
gfp_t gfp)
|
|
gfp_t gfp)
|
|
@@ -855,9 +869,12 @@ void __ref kmemleak_alloc(const void *ptr, size_t size, int min_count,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(kmemleak_alloc);
|
|
EXPORT_SYMBOL_GPL(kmemleak_alloc);
|
|
|
|
|
|
-/*
|
|
|
|
- * Memory freeing function callback. This function is called from the kernel
|
|
|
|
- * allocators when a block is freed (kmem_cache_free, kfree, vfree etc.).
|
|
|
|
|
|
+/**
|
|
|
|
+ * kmemleak_free - unregister a previously registered object
|
|
|
|
+ * @ptr: pointer to beginning of the object
|
|
|
|
+ *
|
|
|
|
+ * This function is called from the kernel allocators when an object (memory
|
|
|
|
+ * block) is freed (kmem_cache_free, kfree, vfree etc.).
|
|
*/
|
|
*/
|
|
void __ref kmemleak_free(const void *ptr)
|
|
void __ref kmemleak_free(const void *ptr)
|
|
{
|
|
{
|
|
@@ -870,9 +887,14 @@ void __ref kmemleak_free(const void *ptr)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(kmemleak_free);
|
|
EXPORT_SYMBOL_GPL(kmemleak_free);
|
|
|
|
|
|
-/*
|
|
|
|
- * Partial memory freeing function callback. This function is usually called
|
|
|
|
- * from bootmem allocator when (part of) a memory block is freed.
|
|
|
|
|
|
+/**
|
|
|
|
+ * kmemleak_free_part - partially unregister a previously registered object
|
|
|
|
+ * @ptr: pointer to the beginning or inside the object. This also
|
|
|
|
+ * represents the start of the range to be freed
|
|
|
|
+ * @size: size to be unregistered
|
|
|
|
+ *
|
|
|
|
+ * This function is called when only a part of a memory block is freed
|
|
|
|
+ * (usually from the bootmem allocator).
|
|
*/
|
|
*/
|
|
void __ref kmemleak_free_part(const void *ptr, size_t size)
|
|
void __ref kmemleak_free_part(const void *ptr, size_t size)
|
|
{
|
|
{
|
|
@@ -885,9 +907,12 @@ void __ref kmemleak_free_part(const void *ptr, size_t size)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(kmemleak_free_part);
|
|
EXPORT_SYMBOL_GPL(kmemleak_free_part);
|
|
|
|
|
|
-/*
|
|
|
|
- * Mark an already allocated memory block as a false positive. This will cause
|
|
|
|
- * the block to no longer be reported as leak and always be scanned.
|
|
|
|
|
|
+/**
|
|
|
|
+ * kmemleak_not_leak - mark an allocated object as false positive
|
|
|
|
+ * @ptr: pointer to beginning of the object
|
|
|
|
+ *
|
|
|
|
+ * Calling this function on an object will cause the memory block to no longer
|
|
|
|
+ * be reported as leak and always be scanned.
|
|
*/
|
|
*/
|
|
void __ref kmemleak_not_leak(const void *ptr)
|
|
void __ref kmemleak_not_leak(const void *ptr)
|
|
{
|
|
{
|
|
@@ -900,10 +925,14 @@ void __ref kmemleak_not_leak(const void *ptr)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(kmemleak_not_leak);
|
|
EXPORT_SYMBOL(kmemleak_not_leak);
|
|
|
|
|
|
-/*
|
|
|
|
- * Ignore a memory block. This is usually done when it is known that the
|
|
|
|
- * corresponding block is not a leak and does not contain any references to
|
|
|
|
- * other allocated memory blocks.
|
|
|
|
|
|
+/**
|
|
|
|
+ * kmemleak_ignore - ignore an allocated object
|
|
|
|
+ * @ptr: pointer to beginning of the object
|
|
|
|
+ *
|
|
|
|
+ * Calling this function on an object will cause the memory block to be
|
|
|
|
+ * ignored (not scanned and not reported as a leak). This is usually done when
|
|
|
|
+ * it is known that the corresponding block is not a leak and does not contain
|
|
|
|
+ * any references to other allocated memory blocks.
|
|
*/
|
|
*/
|
|
void __ref kmemleak_ignore(const void *ptr)
|
|
void __ref kmemleak_ignore(const void *ptr)
|
|
{
|
|
{
|
|
@@ -916,8 +945,16 @@ void __ref kmemleak_ignore(const void *ptr)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(kmemleak_ignore);
|
|
EXPORT_SYMBOL(kmemleak_ignore);
|
|
|
|
|
|
-/*
|
|
|
|
- * Limit the range to be scanned in an allocated memory block.
|
|
|
|
|
|
+/**
|
|
|
|
+ * kmemleak_scan_area - limit the range to be scanned in an allocated object
|
|
|
|
+ * @ptr: pointer to beginning or inside the object. This also
|
|
|
|
+ * represents the start of the scan area
|
|
|
|
+ * @size: size of the scan area
|
|
|
|
+ * @gfp: kmalloc() flags used for kmemleak internal memory allocations
|
|
|
|
+ *
|
|
|
|
+ * This function is used when it is known that only certain parts of an object
|
|
|
|
+ * contain references to other objects. Kmemleak will only scan these areas
|
|
|
|
+ * reducing the number false negatives.
|
|
*/
|
|
*/
|
|
void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
|
|
void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
|
|
{
|
|
{
|
|
@@ -930,8 +967,14 @@ void __ref kmemleak_scan_area(const void *ptr, size_t size, gfp_t gfp)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(kmemleak_scan_area);
|
|
EXPORT_SYMBOL(kmemleak_scan_area);
|
|
|
|
|
|
-/*
|
|
|
|
- * Inform kmemleak not to scan the given memory block.
|
|
|
|
|
|
+/**
|
|
|
|
+ * kmemleak_no_scan - do not scan an allocated object
|
|
|
|
+ * @ptr: pointer to beginning of the object
|
|
|
|
+ *
|
|
|
|
+ * This function notifies kmemleak not to scan the given memory block. Useful
|
|
|
|
+ * in situations where it is known that the given object does not contain any
|
|
|
|
+ * references to other objects. Kmemleak will not scan such objects reducing
|
|
|
|
+ * the number of false negatives.
|
|
*/
|
|
*/
|
|
void __ref kmemleak_no_scan(const void *ptr)
|
|
void __ref kmemleak_no_scan(const void *ptr)
|
|
{
|
|
{
|
|
@@ -1602,7 +1645,9 @@ static int kmemleak_boot_config(char *str)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
if (strcmp(str, "off") == 0)
|
|
if (strcmp(str, "off") == 0)
|
|
kmemleak_disable();
|
|
kmemleak_disable();
|
|
- else if (strcmp(str, "on") != 0)
|
|
|
|
|
|
+ else if (strcmp(str, "on") == 0)
|
|
|
|
+ kmemleak_skip_disable = 1;
|
|
|
|
+ else
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -1616,6 +1661,13 @@ void __init kmemleak_init(void)
|
|
int i;
|
|
int i;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
+#ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
|
|
|
|
+ if (!kmemleak_skip_disable) {
|
|
|
|
+ kmemleak_disable();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+
|
|
jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE);
|
|
jiffies_min_age = msecs_to_jiffies(MSECS_MIN_AGE);
|
|
jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000);
|
|
jiffies_scan_wait = msecs_to_jiffies(SECS_SCAN_WAIT * 1000);
|
|
|
|
|