// SPDX-License-Identifier: GPL-2.0-only /* * mm/kmemleak.c * * Copyright (C) 2008 ARM Limited * Written by Catalin Marinas <catalin.marinas@arm.com> * * For more information on the algorithm and kmemleak usage, please see * Documentation/dev-tools/kmemleak.rst. * * Notes on locking * ---------------- * * The following locks and mutexes are used by kmemleak: * * - kmemleak_lock (raw_spinlock_t): protects the object_list as well as * del_state modifications and accesses to the object trees * (object_tree_root, object_phys_tree_root, object_percpu_tree_root). The * object_list is the main list holding the metadata (struct * kmemleak_object) for the allocated memory blocks. The object trees are * red black trees used to look-up metadata based on a pointer to the * corresponding memory block. The kmemleak_object structures are added to * the object_list and the object tree root in the create_object() function * called from the kmemleak_alloc{,_phys,_percpu}() callback and removed in * delete_object() called from the kmemleak_free{,_phys,_percpu}() callback * - kmemleak_object.lock (raw_spinlock_t): protects a kmemleak_object. * Accesses to the metadata (e.g. count) are protected by this lock. Note * that some members of this structure may be protected by other means * (atomic or kmemleak_lock). This lock is also held when scanning the * corresponding memory block to avoid the kernel freeing it via the * kmemleak_free() callback. This is less heavyweight than holding a global * lock like kmemleak_lock during scanning. * - scan_mutex (mutex): ensures that only one thread may scan the memory for * unreferenced objects at a time. The gray_list contains the objects which * are already referenced or marked as false positives and need to be * scanned. This list is only modified during a scanning episode when the * scan_mutex is held. At the end of a scan, the gray_list is always empty. * Note that the kmemleak_object.use_count is incremented when an object is * added to the gray_list and therefore cannot be freed. This mutex also * prevents multiple users of the "kmemleak" debugfs file together with * modifications to the memory scanning parameters including the scan_thread * pointer * * Locks and mutexes are acquired/nested in the following order: * * scan_mutex [-> object->lock] -> kmemleak_lock -> other_object->lock (SINGLE_DEPTH_NESTING) * * No kmemleak_lock and object->lock nesting is allowed outside scan_mutex * regions. * * The kmemleak_object structures have a use_count incremented or decremented * using the get_object()/put_object() functions. When the use_count becomes * 0, this count can no longer be incremented and put_object() schedules the * kmemleak_object freeing via an RCU callback. All calls to the get_object() * function must be protected by rcu_read_lock() to avoid accessing a freed * structure.
*/
/* * Kmemleak configuration and common defines.
*/ #define MAX_TRACE 16 /* stack trace length */ #define MSECS_MIN_AGE 5000 /* minimum object age for reporting */ #define SECS_FIRST_SCAN 60 /* delay before the first scan */ #define SECS_SCAN_WAIT 600 /* subsequent auto scanning delay */ #define MAX_SCAN_SIZE 4096 /* maximum size of a scanned block */
#define BYTES_PER_POINTER sizeof(void *)
/* scanning area inside a memory block */ struct kmemleak_scan_area { struct hlist_node node; unsignedlong start;
size_t size;
};
#define KMEMLEAK_GREY 0 #define KMEMLEAK_BLACK -1
/* * Structure holding the metadata for each allocated memory block. * Modifications to such objects should be made while holding the * object->lock. Insertions or deletions from object_list, gray_list or * rb_node are already protected by the corresponding locks or mutex (see * the notes on locking above). These objects are reference-counted * (use_count) and freed using the RCU mechanism.
*/ struct kmemleak_object {
raw_spinlock_t lock; unsignedint flags; /* object status flags */ struct list_head object_list; struct list_head gray_list; struct rb_node rb_node; struct rcu_head rcu; /* object_list lockless traversal */ /* object usage count; object freed when use_count == 0 */
atomic_t use_count; unsignedint del_state; /* deletion state */ unsignedlong pointer;
size_t size; /* pass surplus references to this pointer */ unsignedlong excess_ref; /* minimum number of a pointers found before it is considered leak */ int min_count; /* the total number of pointers found pointing to this object */ int count; /* checksum for detecting modified objects */
u32 checksum;
depot_stack_handle_t trace_handle; /* memory ranges to be scanned inside an object (empty for all) */ struct hlist_head area_list; unsignedlong jiffies; /* creation timestamp */
pid_t pid; /* pid of the current task */ char comm[TASK_COMM_LEN]; /* executable name */
};
/* flag representing the memory block allocation status */ #define OBJECT_ALLOCATED (1 << 0) /* flag set after the first reporting of an unreference object */ #define OBJECT_REPORTED (1 << 1) /* flag set to not scan the object */ #define OBJECT_NO_SCAN (1 << 2) /* flag set to fully scan the object when scan_area allocation failed */ #define OBJECT_FULL_SCAN (1 << 3) /* flag set for object allocated with physical address */ #define OBJECT_PHYS (1 << 4) /* flag set for per-CPU pointers */ #define OBJECT_PERCPU (1 << 5)
/* set when __remove_object() called */ #define DELSTATE_REMOVED (1 << 0) /* set to temporarily prevent deletion from object_list */ #define DELSTATE_NO_DELETE (1 << 1)
#define HEX_PREFIX " " /* number of bytes to print per line; must be 16 or 32 */ #define HEX_ROW_SIZE 16 /* number of bytes to print at a time (1, 2, 4, 8) */ #define HEX_GROUP_SIZE 1 /* include ASCII after the hex output */ #define HEX_ASCII 1 /* max number of lines to be printed */ #define HEX_MAX_LINES 2
/* the list of all allocated objects */ static LIST_HEAD(object_list); /* the list of gray-colored objects (see color_gray comment below) */ static LIST_HEAD(gray_list); /* memory pool allocation */ staticstruct kmemleak_object mem_pool[CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE]; staticint mem_pool_free_count = ARRAY_SIZE(mem_pool); static LIST_HEAD(mem_pool_free_list); /* search tree for object boundaries */ staticstruct rb_root object_tree_root = RB_ROOT; /* search tree for object (with OBJECT_PHYS flag) boundaries */ staticstruct rb_root object_phys_tree_root = RB_ROOT; /* search tree for object (with OBJECT_PERCPU flag) boundaries */ staticstruct rb_root object_percpu_tree_root = RB_ROOT; /* protecting the access to object_list, object_tree_root (or object_phys_tree_root) */ static DEFINE_RAW_SPINLOCK(kmemleak_lock);
/* allocation caches for kmemleak internal data */ staticstruct kmem_cache *object_cache; staticstruct kmem_cache *scan_area_cache;
/* set if tracing memory operations is enabled */ staticint kmemleak_enabled __read_mostly = 1; /* same as above but only for the kmemleak_free() callback */ staticint kmemleak_free_enabled __read_mostly = 1; /* set in the late_initcall if there were no errors */ staticint kmemleak_late_initialized; /* set if a fatal kmemleak error has occurred */ staticint kmemleak_error;
/* minimum and maximum address that may be valid pointers */ staticunsignedlong min_addr = ULONG_MAX; staticunsignedlong max_addr;
/* minimum and maximum address that may be valid per-CPU pointers */ staticunsignedlong min_percpu_addr = ULONG_MAX; staticunsignedlong max_percpu_addr;
staticstruct task_struct *scan_thread; /* used to avoid reporting of recently allocated objects */ staticunsignedlong jiffies_min_age; staticunsignedlong jiffies_last_scan; /* delay between automatic memory scannings */ staticunsignedlong jiffies_scan_wait; /* enables or disables the task stacks scanning */ staticint kmemleak_stack_scan = 1; /* protects the memory scanning, parameters and debug/kmemleak file access */ static DEFINE_MUTEX(scan_mutex); /* setting kmemleak=on, will set this var, skipping the disable */ staticint kmemleak_skip_disable; /* If there are leaks that can be reported */ staticbool kmemleak_found_leaks;
/* * Print a warning and dump the stack trace.
*/ #define kmemleak_warn(x...) do { \
pr_warn(x); \
dump_stack(); \
} while (0)
/* * Macro invoked when a serious kmemleak condition occurred and cannot be * recovered from. Kmemleak will be disabled and further allocation/freeing * tracing no longer available.
*/ #define kmemleak_stop(x...) do { \
kmemleak_warn(x); \
kmemleak_disable(); \
} while (0)
#define warn_or_seq_printf(seq, fmt, ...) do { \ if (seq) \
seq_printf(seq, fmt, ##__VA_ARGS__); \ else \
pr_warn(fmt, ##__VA_ARGS__); \
} while (0)
staticvoid warn_or_seq_hex_dump(struct seq_file *seq, int prefix_type, int rowsize, int groupsize, constvoid *buf,
size_t len, bool ascii)
{ if (seq)
seq_hex_dump(seq, HEX_PREFIX, prefix_type, rowsize, groupsize,
buf, len, ascii); else
print_hex_dump(KERN_WARNING, pr_fmt(HEX_PREFIX), prefix_type,
rowsize, groupsize, buf, len, ascii);
}
/* * Printing of the objects hex dump to the seq file. The number of lines to be * printed is limited to HEX_MAX_LINES to prevent seq file spamming. The * actual number of printed bytes depends on HEX_ROW_SIZE. It must be called * with the object->lock held.
*/ staticvoid hex_dump_object(struct seq_file *seq, struct kmemleak_object *object)
{ const u8 *ptr = (const u8 *)object->pointer;
size_t len;
if (WARN_ON_ONCE(object->flags & OBJECT_PHYS)) return;
/* * Object colors, encoded with count and min_count: * - white - orphan object, not enough references to it (count < min_count) * - gray - not orphan, not marked as false positive (min_count == 0) or * sufficient references to it (count >= min_count) * - black - ignore, it doesn't contain references (e.g. text section) * (min_count == -1). No function defined for this color.
*/ staticbool color_white(conststruct kmemleak_object *object)
{ return object->count != KMEMLEAK_BLACK &&
object->count < object->min_count;
}
/* * Objects are considered unreferenced only if their color is white, they have * not be deleted and have a minimum age to avoid false positives caused by * pointers temporarily stored in CPU registers.
*/ staticbool unreferenced_object(struct kmemleak_object *object)
{ return (color_white(object) && object->flags & OBJECT_ALLOCATED) &&
time_before_eq(object->jiffies + jiffies_min_age,
jiffies_last_scan);
}
staticconstchar *__object_type_str(struct kmemleak_object *object)
{ if (object->flags & OBJECT_PHYS) return" (phys)"; if (object->flags & OBJECT_PERCPU) return" (percpu)"; return"";
}
/* * Printing of the unreferenced objects information to the seq file. The * print_unreferenced function must be called with the object->lock held.
*/ staticvoid print_unreferenced(struct seq_file *seq, struct kmemleak_object *object)
{ int i; unsignedlong *entries; unsignedint nr_entries;
for (i = 0; i < nr_entries; i++) { void *ptr = (void *)entries[i];
warn_or_seq_printf(seq, " %pS\n", ptr);
}
}
/* * Print the kmemleak_object information. This function is used mainly for * debugging special cases when kmemleak operations. It must be called with * the object->lock held.
*/ staticvoid dump_object_info(struct kmemleak_object *object)
{
pr_notice("Object%s 0x%08lx (size %zu):\n",
__object_type_str(object), object->pointer, object->size);
pr_notice(" comm \"%s\", pid %d, jiffies %lu\n",
object->comm, object->pid, object->jiffies);
pr_notice(" min_count = %d\n", object->min_count);
pr_notice(" count = %d\n", object->count);
pr_notice(" flags = 0x%x\n", object->flags);
pr_notice(" checksum = %u\n", object->checksum);
pr_notice(" backtrace:\n"); if (object->trace_handle)
stack_depot_print(object->trace_handle);
}
staticstruct rb_root *object_tree(unsignedlong objflags)
{ if (objflags & OBJECT_PHYS) return &object_phys_tree_root; if (objflags & OBJECT_PERCPU) return &object_percpu_tree_root; return &object_tree_root;
}
/* * Look-up a memory block metadata (kmemleak_object) in the object search * tree based on a pointer value. If alias is 0, only values pointing to the * beginning of the memory block are allowed. The kmemleak_lock must be held * when calling this function.
*/ staticstruct kmemleak_object *__lookup_object(unsignedlong ptr, int alias, unsignedint objflags)
{ struct rb_node *rb = object_tree(objflags)->rb_node; unsignedlong untagged_ptr = (unsignedlong)kasan_reset_tag((void *)ptr);
while (rb) { struct kmemleak_object *object; unsignedlong untagged_objp;
if (untagged_ptr < untagged_objp)
rb = object->rb_node.rb_left; elseif (untagged_objp + object->size <= untagged_ptr)
rb = object->rb_node.rb_right; elseif (untagged_objp == untagged_ptr || alias) return object; else { /* * Printk deferring due to the kmemleak_lock held. * This is done to avoid deadlock.
*/
printk_deferred_enter();
kmemleak_warn("Found object by alias at 0x%08lx\n",
ptr);
dump_object_info(object);
printk_deferred_exit(); break;
}
} return NULL;
}
/* Look-up a kmemleak object which allocated with virtual address. */ staticstruct kmemleak_object *lookup_object(unsignedlong ptr, int alias)
{ return __lookup_object(ptr, alias, 0);
}
/* * Increment the object use_count. Return 1 if successful or 0 otherwise. Note * that once an object's use_count reached 0, the RCU freeing was already * registered and the object should no longer be used. This function must be * called under the protection of rcu_read_lock().
*/ staticint get_object(struct kmemleak_object *object)
{ return atomic_inc_not_zero(&object->use_count);
}
/* * Memory pool allocation and freeing. kmemleak_lock must not be held.
*/ staticstruct kmemleak_object *mem_pool_alloc(gfp_t gfp)
{ unsignedlong flags; struct kmemleak_object *object; bool warn = false;
/* try the slab allocator first */ if (object_cache) {
object = kmem_cache_alloc_noprof(object_cache,
gfp_nested_mask(gfp)); if (object) return object;
}
/* slab allocation failed, try the memory pool */
raw_spin_lock_irqsave(&kmemleak_lock, flags);
object = list_first_entry_or_null(&mem_pool_free_list,
typeof(*object), object_list); if (object)
list_del(&object->object_list); elseif (mem_pool_free_count)
object = &mem_pool[--mem_pool_free_count]; else
warn = true;
raw_spin_unlock_irqrestore(&kmemleak_lock, flags); if (warn)
pr_warn_once("Memory pool empty, consider increasing CONFIG_DEBUG_KMEMLEAK_MEM_POOL_SIZE\n");
return object;
}
/* * Return the object to either the slab allocator or the memory pool.
*/ staticvoid mem_pool_free(struct kmemleak_object *object)
{ unsignedlong flags;
/* add the object to the memory pool free list */
raw_spin_lock_irqsave(&kmemleak_lock, flags);
list_add(&object->object_list, &mem_pool_free_list);
raw_spin_unlock_irqrestore(&kmemleak_lock, flags);
}
/* * Once use_count is 0 (guaranteed by put_object), there is no other * code accessing this object, hence no need for locking.
*/
hlist_for_each_entry_safe(area, tmp, &object->area_list, node) {
hlist_del(&area->node);
kmem_cache_free(scan_area_cache, area);
}
mem_pool_free(object);
}
/* * Decrement the object use_count. Once the count is 0, free the object using * an RCU callback. Since put_object() may be called via the kmemleak_free() -> * delete_object() path, the delayed RCU freeing ensures that there is no * recursive call to the kernel allocator. Lock-less RCU object_list traversal * is also possible.
*/ staticvoid put_object(struct kmemleak_object *object)
{ if (!atomic_dec_and_test(&object->use_count)) return;
/* should only get here after delete_object was called */
WARN_ON(object->flags & OBJECT_ALLOCATED);
/* * It may be too early for the RCU callbacks, however, there is no * concurrent object_list traversal when !object_cache and all objects * came from the memory pool. Free the object directly.
*/ if (object_cache)
call_rcu(&object->rcu, free_object_rcu); else
free_object_rcu(&object->rcu);
}
/* * Look up an object in the object search tree and increase its use_count.
*/ staticstruct kmemleak_object *__find_and_get_object(unsignedlong ptr, int alias, unsignedint objflags)
{ unsignedlong flags; struct kmemleak_object *object;
/* check whether the object is still available */ if (object && !get_object(object))
object = NULL;
rcu_read_unlock();
return object;
}
/* Look up and get an object which allocated with virtual address. */ staticstruct kmemleak_object *find_and_get_object(unsignedlong ptr, int alias)
{ return __find_and_get_object(ptr, alias, 0);
}
/* * Remove an object from its object tree and object_list. Must be called with * the kmemleak_lock held _if_ kmemleak is still enabled.
*/ staticvoid __remove_object(struct kmemleak_object *object)
{
rb_erase(&object->rb_node, object_tree(object->flags)); if (!(object->del_state & DELSTATE_NO_DELETE))
list_del_rcu(&object->object_list);
object->del_state |= DELSTATE_REMOVED;
}
object = __lookup_object(ptr, alias, objflags); if (object)
__remove_object(object);
return object;
}
/* * Look up an object in the object search tree and remove it from both object * tree root and object_list. The returned object's use_count should be at * least 1, as initially set by create_object().
*/ staticstruct kmemleak_object *find_and_remove_object(unsignedlong ptr, int alias, unsignedint objflags)
{ unsignedlong flags; struct kmemleak_object *object;
/* * Use object_cache to determine whether kmemleak_init() has * been invoked. stack_depot_early_init() is called before * kmemleak_init() in mm_core_init().
*/ if (!object_cache) return 0;
nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 3);
trace_handle = stack_depot_save(entries, nr_entries, GFP_NOWAIT);
/* task information */ if (in_hardirq()) {
object->pid = 0;
strscpy(object->comm, "hardirq");
} elseif (in_serving_softirq()) {
object->pid = 0;
strscpy(object->comm, "softirq");
} else {
object->pid = current->pid; /* * There is a small chance of a race with set_task_comm(), * however using get_task_comm() here may cause locking * dependency issues with current->alloc_lock. In the worst * case, the command line is not correct.
*/
strscpy(object->comm, current->comm);
}
untagged_ptr = (unsignedlong)kasan_reset_tag((void *)ptr); /* * Only update min_addr and max_addr with object storing virtual * address. And update min_percpu_addr max_percpu_addr for per-CPU * objects.
*/ if (objflags & OBJECT_PERCPU) {
min_percpu_addr = min(min_percpu_addr, untagged_ptr);
max_percpu_addr = max(max_percpu_addr, untagged_ptr + size);
} elseif (!(objflags & OBJECT_PHYS)) {
min_addr = min(min_addr, untagged_ptr);
max_addr = max(max_addr, untagged_ptr + size);
}
link = &object_tree(objflags)->rb_node;
rb_parent = NULL; while (*link) {
rb_parent = *link;
parent = rb_entry(rb_parent, struct kmemleak_object, rb_node);
untagged_objp = (unsignedlong)kasan_reset_tag((void *)parent->pointer); if (untagged_ptr + size <= untagged_objp)
link = &parent->rb_node.rb_left; elseif (untagged_objp + parent->size <= untagged_ptr)
link = &parent->rb_node.rb_right; else { /* * Printk deferring due to the kmemleak_lock held. * This is done to avoid deadlock.
*/
printk_deferred_enter();
kmemleak_stop("Cannot insert 0x%lx into the object search tree (overlaps existing)\n",
ptr); /* * No need for parent->lock here since "parent" cannot * be freed while the kmemleak_lock is held.
*/
dump_object_info(parent);
printk_deferred_exit(); return -EEXIST;
}
}
rb_link_node(&object->rb_node, rb_parent, link);
rb_insert_color(&object->rb_node, object_tree(objflags));
list_add_tail_rcu(&object->object_list, &object_list);
return 0;
}
/* * Create the metadata (struct kmemleak_object) corresponding to an allocated * memory block and add it to the object_list and object tree.
*/ staticvoid __create_object(unsignedlong ptr, size_t size, int min_count, gfp_t gfp, unsignedint objflags)
{ struct kmemleak_object *object; unsignedlong flags; int ret;
object = __alloc_object(gfp); if (!object) return;
raw_spin_lock_irqsave(&kmemleak_lock, flags);
ret = __link_object(object, ptr, size, min_count, objflags);
raw_spin_unlock_irqrestore(&kmemleak_lock, flags); if (ret)
mem_pool_free(object);
}
/* Create kmemleak object which allocated with virtual address. */ staticvoid create_object(unsignedlong ptr, size_t size, int min_count, gfp_t gfp)
{
__create_object(ptr, size, min_count, gfp, 0);
}
/* Create kmemleak object which allocated with physical address. */ staticvoid create_object_phys(unsignedlong ptr, size_t size, int min_count, gfp_t gfp)
{
__create_object(ptr, size, min_count, gfp, OBJECT_PHYS);
}
/* Create kmemleak object corresponding to a per-CPU allocation. */ staticvoid create_object_percpu(unsignedlong ptr, size_t size, int min_count, gfp_t gfp)
{
__create_object(ptr, size, min_count, gfp, OBJECT_PERCPU);
}
/* * Mark the object as not allocated and schedule RCU freeing via put_object().
*/ staticvoid __delete_object(struct kmemleak_object *object)
{ unsignedlong flags;
/* * Locking here also ensures that the corresponding memory block * cannot be freed when it is being scanned.
*/
raw_spin_lock_irqsave(&object->lock, flags);
object->flags &= ~OBJECT_ALLOCATED;
raw_spin_unlock_irqrestore(&object->lock, flags);
put_object(object);
}
/* * Look up the metadata (struct kmemleak_object) corresponding to ptr and * delete it.
*/ staticvoid delete_object_full(unsignedlong ptr, unsignedint objflags)
{ struct kmemleak_object *object;
/* * Look up the metadata (struct kmemleak_object) corresponding to ptr and * delete it. If the memory block is partially freed, the function may create * additional metadata for the remaining parts of the block.
*/ staticvoid delete_object_part(unsignedlong ptr, size_t size, unsignedint objflags)
{ struct kmemleak_object *object, *object_l, *object_r; unsignedlong start, end, flags;
object_l = __alloc_object(GFP_KERNEL); if (!object_l) return;
object_r = __alloc_object(GFP_KERNEL); if (!object_r) goto out;
/* * Create one or two objects that may result from the memory block * split. Note that partial freeing is only done by free_bootmem() and * this happens before kmemleak_init() is called.
*/
start = object->pointer;
end = object->pointer + object->size; if ((ptr > start) &&
!__link_object(object_l, start, ptr - start,
object->min_count, objflags))
object_l = NULL; if ((ptr + size < end) &&
!__link_object(object_r, ptr + size, end - ptr - size,
object->min_count, objflags))
object_r = NULL;
object = __find_and_get_object(ptr, 0, objflags); if (!object) {
kmemleak_warn("Trying to color unknown object at 0x%08lx as %s\n",
ptr,
(color == KMEMLEAK_GREY) ? "Grey" :
(color == KMEMLEAK_BLACK) ? "Black" : "Unknown"); return;
}
paint_it(object, color);
put_object(object);
}
/* * 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.
*/ staticvoid make_gray_object(unsignedlong ptr)
{
paint_ptr(ptr, KMEMLEAK_GREY, 0);
}
/* * Mark the object as black-colored so that it is ignored from scans and * reporting.
*/ staticvoid make_black_object(unsignedlong ptr, unsignedint objflags)
{
paint_ptr(ptr, KMEMLEAK_BLACK, objflags);
}
/* * Reset the checksum of an object. The immediate effect is that it will not * be reported as a leak during the next scan until its checksum is updated.
*/ staticvoid reset_checksum(unsignedlong ptr)
{ unsignedlong flags; struct kmemleak_object *object;
object = find_and_get_object(ptr, 0); if (!object) {
kmemleak_warn("Not resetting the checksum of an unknown object at 0x%08lx\n",
ptr); return;
}
/* * Add a scanning area to the object. If at least one such area is added, * kmemleak will only scan these ranges rather than the whole memory block.
*/ staticvoid add_scan_area(unsignedlong ptr, size_t size, gfp_t gfp)
{ unsignedlong flags; struct kmemleak_object *object; struct kmemleak_scan_area *area = NULL; unsignedlong untagged_ptr; unsignedlong untagged_objp;
object = find_and_get_object(ptr, 1); if (!object) {
kmemleak_warn("Adding scan area to unknown object at 0x%08lx\n",
ptr); return;
}
/* * Any surplus references (object already gray) to 'ptr' are passed to * 'excess_ref'. This is used in the vmalloc() case where a pointer to * vm_struct may be used as an alternative reference to the vmalloc'ed object * (see free_thread_stack()).
*/ staticvoid object_set_excess_ref(unsignedlong ptr, unsignedlong excess_ref)
{ unsignedlong flags; struct kmemleak_object *object;
object = find_and_get_object(ptr, 0); if (!object) {
kmemleak_warn("Setting excess_ref on unknown object at 0x%08lx\n",
ptr); return;
}
/* * Set the OBJECT_NO_SCAN flag for the object corresponding to the given * pointer. Such object will not be scanned by kmemleak but references to it * are searched.
*/ staticvoid object_no_scan(unsignedlong ptr)
{ unsignedlong flags; struct kmemleak_object *object;
object = find_and_get_object(ptr, 0); if (!object) {
kmemleak_warn("Not scanning unknown object at 0x%08lx\n", ptr); return;
}
/** * 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 etc.).
*/ void __ref kmemleak_alloc(constvoid *ptr, size_t size, int min_count,
gfp_t gfp)
{
pr_debug("%s(0x%px, %zu, %d)\n", __func__, ptr, size, min_count);
/** * kmemleak_alloc_percpu - register a newly allocated __percpu object * @ptr: __percpu pointer to beginning of the object * @size: size of the object * @gfp: flags used for kmemleak internal memory allocations * * This function is called from the kernel percpu allocator when a new object * (memory block) is allocated (alloc_percpu).
*/ void __ref kmemleak_alloc_percpu(constvoid __percpu *ptr, size_t size,
gfp_t gfp)
{
pr_debug("%s(0x%px, %zu)\n", __func__, ptr, size);
/** * kmemleak_vmalloc - register a newly vmalloc'ed object * @area: pointer to vm_struct * @size: size of the object * @gfp: __vmalloc() flags used for kmemleak internal memory allocations * * This function is called from the vmalloc() kernel allocator when a new * object (memory block) is allocated.
*/ void __ref kmemleak_vmalloc(conststruct vm_struct *area, size_t size, gfp_t gfp)
{
pr_debug("%s(0x%px, %zu)\n", __func__, area, size);
/* * A min_count = 2 is needed because vm_struct contains a reference to * the virtual address of the vmalloc'ed block.
*/ if (kmemleak_enabled) {
create_object((unsignedlong)area->addr, size, 2, gfp);
object_set_excess_ref((unsignedlong)area,
(unsignedlong)area->addr);
}
}
EXPORT_SYMBOL_GPL(kmemleak_vmalloc);
/** * 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(constvoid *ptr)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
if (kmemleak_free_enabled && ptr && !IS_ERR(ptr))
delete_object_full((unsignedlong)ptr, 0);
}
EXPORT_SYMBOL_GPL(kmemleak_free);
/** * 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(constvoid *ptr, size_t size)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
/** * kmemleak_free_percpu - unregister a previously registered __percpu object * @ptr: __percpu pointer to beginning of the object * * This function is called from the kernel percpu allocator when an object * (memory block) is freed (free_percpu).
*/ void __ref kmemleak_free_percpu(constvoid __percpu *ptr)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
/** * kmemleak_update_trace - update object allocation stack trace * @ptr: pointer to beginning of the object * * Override the object allocation stack trace for cases where the actual * allocation place is not always useful.
*/ void __ref kmemleak_update_trace(constvoid *ptr)
{ struct kmemleak_object *object;
depot_stack_handle_t trace_handle; unsignedlong flags;
pr_debug("%s(0x%px)\n", __func__, ptr);
if (!kmemleak_enabled || IS_ERR_OR_NULL(ptr)) return;
object = find_and_get_object((unsignedlong)ptr, 1); if (!object) { #ifdef DEBUG
kmemleak_warn("Updating stack trace for unknown object at %p\n",
ptr); #endif return;
}
/** * 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(constvoid *ptr)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
if (kmemleak_enabled && ptr && !IS_ERR(ptr))
make_gray_object((unsignedlong)ptr);
}
EXPORT_SYMBOL(kmemleak_not_leak);
/** * kmemleak_transient_leak - mark an allocated object as transient false positive * @ptr: pointer to beginning of the object * * Calling this function on an object will cause the memory block to not be * reported as a leak temporarily. This may happen, for example, if the object * is part of a singly linked list and the ->next reference to it is changed.
*/ void __ref kmemleak_transient_leak(constvoid *ptr)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
if (kmemleak_enabled && ptr && !IS_ERR(ptr))
reset_checksum((unsignedlong)ptr);
}
EXPORT_SYMBOL(kmemleak_transient_leak);
/** * kmemleak_ignore_percpu - similar to kmemleak_ignore but taking a percpu * address argument * @ptr: percpu address of the object
*/ void __ref kmemleak_ignore_percpu(constvoid __percpu *ptr)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
if (kmemleak_enabled && ptr && !IS_ERR_PCPU(ptr))
make_black_object((unsignedlong)ptr, OBJECT_PERCPU);
}
EXPORT_SYMBOL_GPL(kmemleak_ignore_percpu);
/** * 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(constvoid *ptr)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
if (kmemleak_enabled && ptr && !IS_ERR(ptr))
make_black_object((unsignedlong)ptr, 0);
}
EXPORT_SYMBOL(kmemleak_ignore);
/** * 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(constvoid *ptr, size_t size, gfp_t gfp)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
/** * 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(constvoid *ptr)
{
pr_debug("%s(0x%px)\n", __func__, ptr);
if (kmemleak_enabled && ptr && !IS_ERR(ptr))
object_no_scan((unsignedlong)ptr);
}
EXPORT_SYMBOL(kmemleak_no_scan);
/** * kmemleak_alloc_phys - similar to kmemleak_alloc but taking a physical * address argument * @phys: physical address of the object * @size: size of the object * @gfp: kmalloc() flags used for kmemleak internal memory allocations
*/ void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, gfp_t gfp)
{
pr_debug("%s(0x%px, %zu)\n", __func__, &phys, size);
if (kmemleak_enabled) /* * Create object with OBJECT_PHYS flag and * assume min_count 0.
*/
create_object_phys((unsignedlong)phys, size, 0, gfp);
}
EXPORT_SYMBOL(kmemleak_alloc_phys);
/** * kmemleak_free_part_phys - similar to kmemleak_free_part but taking a * physical address argument * @phys: physical address if the beginning or inside an object. This * also represents the start of the range to be freed * @size: size to be unregistered
*/ void __ref kmemleak_free_part_phys(phys_addr_t phys, size_t size)
{
pr_debug("%s(0x%px)\n", __func__, &phys);
if (kmemleak_enabled)
delete_object_part((unsignedlong)phys, size, OBJECT_PHYS);
}
EXPORT_SYMBOL(kmemleak_free_part_phys);
/** * kmemleak_ignore_phys - similar to kmemleak_ignore but taking a physical * address argument * @phys: physical address of the object
*/ void __ref kmemleak_ignore_phys(phys_addr_t phys)
{
pr_debug("%s(0x%px)\n", __func__, &phys);
if (kmemleak_enabled)
make_black_object((unsignedlong)phys, OBJECT_PHYS);
}
EXPORT_SYMBOL(kmemleak_ignore_phys);
/* * Update an object's checksum and return true if it was modified.
*/ staticbool update_checksum(struct kmemleak_object *object)
{
u32 old_csum = object->checksum;
if (WARN_ON_ONCE(object->flags & OBJECT_PHYS)) returnfalse;
kasan_disable_current();
kcsan_disable_current(); if (object->flags & OBJECT_PERCPU) { unsignedint cpu;
/* * Update an object's references. object->lock must be held by the caller.
*/ staticvoid update_refs(struct kmemleak_object *object)
{ if (!color_white(object)) { /* non-orphan, ignored or new */ return;
}
/* * Increase the object's reference count (number of pointers to the * memory block). If this count reaches the required minimum, the * object's color will become gray and it will be added to the * gray_list.
*/
object->count++; if (color_gray(object)) { /* put_object() called when removing from gray_list */
WARN_ON(!get_object(object));
list_add_tail(&object->gray_list, &gray_list);
}
}
/* * No need for get_object() here since we hold kmemleak_lock. * object->use_count cannot be dropped to 0 while the object * is still present in object_tree_root and object_list * (with updates protected by kmemleak_lock).
*/
object = __lookup_object(pointer, 1, objflags); if (!object) return; if (object == scanned) /* self referenced, ignore */ return;
/* * Avoid the lockdep recursive warning on object->lock being * previously acquired in scan_object(). These locks are * enclosed by scan_mutex.
*/
raw_spin_lock_nested(&object->lock, SINGLE_DEPTH_NESTING); /* only pass surplus references (object already gray) */ if (color_gray(object)) {
excess_ref = object->excess_ref; /* no need for update_refs() if object already gray */
} else {
excess_ref = 0;
update_refs(object);
}
raw_spin_unlock(&object->lock);
if (excess_ref) {
object = lookup_object(excess_ref, 0); if (!object) return; if (object == scanned) /* circular reference, ignore */ return;
raw_spin_lock_nested(&object->lock, SINGLE_DEPTH_NESTING);
update_refs(object);
raw_spin_unlock(&object->lock);
}
}
/* * Memory scanning is a long process and it needs to be interruptible. This * function checks whether such interrupt condition occurred.
*/ staticint scan_should_stop(void)
{ if (!kmemleak_enabled) return 1;
/* * This function may be called from either process or kthread context, * hence the need to check for both stop conditions.
*/ if (current->mm) return signal_pending(current); else return kthread_should_stop();
return 0;
}
/* * Scan a memory block (exclusive range) for valid pointers and add those * found to the gray list.
*/ staticvoid scan_block(void *_start, void *_end, struct kmemleak_object *scanned)
{ unsignedlong *ptr; unsignedlong *start = PTR_ALIGN(_start, BYTES_PER_POINTER); unsignedlong *end = _end - (BYTES_PER_POINTER - 1); unsignedlong flags;
/* * Scan a large memory block in MAX_SCAN_SIZE chunks to reduce the latency.
*/ #ifdef CONFIG_SMP staticvoid scan_large_block(void *start, void *end)
{ void *next;
/* * Scan a memory block corresponding to a kmemleak_object. A condition is * that object->use_count >= 1.
*/ staticvoid scan_object(struct kmemleak_object *object)
{ struct kmemleak_scan_area *area; unsignedlong flags;
/* * Once the object->lock is acquired, the corresponding memory block * cannot be freed (the same lock is acquired in delete_object).
*/
raw_spin_lock_irqsave(&object->lock, flags); if (object->flags & OBJECT_NO_SCAN) goto out; if (!(object->flags & OBJECT_ALLOCATED)) /* already freed object */ goto out;
if (object->flags & OBJECT_PERCPU) { unsignedint cpu;
/* * Scan the objects already referenced (gray objects). More objects will be * referenced and, if there are no memory leaks, all the objects are scanned.
*/ staticvoid scan_gray_list(void)
{ struct kmemleak_object *object, *tmp;
/* * The list traversal is safe for both tail additions and removals * from inside the loop. The kmemleak objects cannot be freed from * outside the loop because their use_count was incremented.
*/
object = list_entry(gray_list.next, typeof(*object), gray_list); while (&object->gray_list != &gray_list) {
cond_resched();
/* may add new objects to the list */ if (!scan_should_stop())
scan_object(object);
/* * Conditionally call resched() in an object iteration loop while making sure * that the given object won't go away without RCU read lock by performing a * get_object() if necessaary.
*/ staticvoid kmemleak_cond_resched(struct kmemleak_object *object)
{ if (!get_object(object)) return; /* Try next object */
/* * Scan data sections and all the referenced memory blocks allocated via the * kernel's standard allocators. This function must be called with the * scan_mutex held.
*/ staticvoid kmemleak_scan(void)
{ struct kmemleak_object *object; struct zone *zone; int __maybe_unused i; int new_leaks = 0;
jiffies_last_scan = jiffies;
/* prepare the kmemleak_object's */
rcu_read_lock();
list_for_each_entry_rcu(object, &object_list, object_list) {
raw_spin_lock_irq(&object->lock); #ifdef DEBUG /* * With a few exceptions there should be a maximum of * 1 reference to any object at this point.
*/ if (atomic_read(&object->use_count) > 1) {
pr_debug("object->use_count = %d\n",
atomic_read(&object->use_count));
dump_object_info(object);
} #endif
/* only scan pages belonging to this zone */ if (page_zone(page) != zone) continue; /* only scan if page is in use */ if (page_count(page) == 0) continue;
scan_block(page, page + 1, NULL);
}
}
put_online_mems();
/* * Scanning the task stacks (may introduce false negatives).
*/ if (kmemleak_stack_scan) { struct task_struct *p, *g;
/* * Scan the objects already referenced from the sections scanned * above.
*/
scan_gray_list();
/* * Check for new or unreferenced objects modified since the previous * scan and color them gray until the next scan.
*/
rcu_read_lock();
list_for_each_entry_rcu(object, &object_list, object_list) { if (need_resched())
kmemleak_cond_resched(object);
/* * This is racy but we can save the overhead of lock/unlock * calls. The missed objects, if any, should be caught in * the next scan.
*/ if (!color_white(object)) continue;
raw_spin_lock_irq(&object->lock); if (color_white(object) && (object->flags & OBJECT_ALLOCATED)
&& update_checksum(object) && get_object(object)) { /* color it gray temporarily */
object->count = object->min_count;
list_add_tail(&object->gray_list, &gray_list);
}
raw_spin_unlock_irq(&object->lock);
}
rcu_read_unlock();
/* * Re-scan the gray list for modified unreferenced objects.
*/
scan_gray_list();
/* * If scanning was stopped do not report any new unreferenced objects.
*/ if (scan_should_stop()) return;
/* * Scanning result reporting.
*/
rcu_read_lock();
list_for_each_entry_rcu(object, &object_list, object_list) { if (need_resched())
kmemleak_cond_resched(object);
/* * This is racy but we can save the overhead of lock/unlock * calls. The missed objects, if any, should be caught in * the next scan.
*/ if (!color_white(object)) continue;
raw_spin_lock_irq(&object->lock); if (unreferenced_object(object) &&
!(object->flags & OBJECT_REPORTED)) {
object->flags |= OBJECT_REPORTED;
if (kmemleak_verbose)
print_unreferenced(NULL, object);
pr_info("%d new suspected memory leaks (see /sys/kernel/debug/kmemleak)\n",
new_leaks);
}
}
/* * Thread function performing automatic memory scanning. Unreferenced objects * at the end of a memory scan are reported but only the first time.
*/ staticint kmemleak_scan_thread(void *arg)
{ staticint first_run = IS_ENABLED(CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN);
/* * Wait before the first scan to allow the system to fully initialize.
*/ if (first_run) { signedlong timeout = secs_to_jiffies(SECS_FIRST_SCAN);
first_run = 0; while (timeout && !kthread_should_stop())
timeout = schedule_timeout_interruptible(timeout);
}
while (!kthread_should_stop()) { signedlong timeout = READ_ONCE(jiffies_scan_wait);
/* * Start the automatic memory scanning thread. This function must be called * with the scan_mutex held.
*/ staticvoid start_scan_thread(void)
{ if (scan_thread) return;
scan_thread = kthread_run(kmemleak_scan_thread, NULL, "kmemleak"); if (IS_ERR(scan_thread)) {
pr_warn("Failed to create the scan thread\n");
scan_thread = NULL;
}
}
/* * Iterate over the object_list and return the first valid object at or after * the required position with its use_count incremented. The function triggers * a memory scanning when the pos argument points to the first position.
*/ staticvoid *kmemleak_seq_start(struct seq_file *seq, loff_t *pos)
{ struct kmemleak_object *object;
loff_t n = *pos; int err;
err = mutex_lock_interruptible(&scan_mutex); if (err < 0) return ERR_PTR(err);
/* * Return the next object in the object_list. The function decrements the * use_count of the previous object and increases that of the next one.
*/ staticvoid *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ struct kmemleak_object *prev_obj = v; struct kmemleak_object *next_obj = NULL; struct kmemleak_object *obj = prev_obj;
/* * Decrement the use_count of the last object required, if any.
*/ staticvoid kmemleak_seq_stop(struct seq_file *seq, void *v)
{ if (!IS_ERR(v)) { /* * kmemleak_seq_start may return ERR_PTR if the scan_mutex * waiting was interrupted, so only release it if !IS_ERR.
*/
rcu_read_unlock();
mutex_unlock(&scan_mutex); if (v)
put_object(v);
}
}
/* * Print the information for an unreferenced object to the seq file.
*/ staticint kmemleak_seq_show(struct seq_file *seq, void *v)
{ struct kmemleak_object *object = v; unsignedlong flags;
staticint dump_str_object_info(constchar *str)
{ unsignedlong addr; bool found = false;
if (kstrtoul(str, 0, &addr)) return -EINVAL;
found |= __dump_str_object_info(addr, 0);
found |= __dump_str_object_info(addr, OBJECT_PHYS);
found |= __dump_str_object_info(addr, OBJECT_PERCPU);
if (!found) {
pr_info("Unknown object at 0x%08lx\n", addr); return -EINVAL;
}
return 0;
}
/* * We use grey instead of black to ensure we can do future scans on the same * objects. If we did not do future scans these black objects could * potentially contain references to newly allocated objects in the future and * we'd end up with false positives.
*/ staticvoid kmemleak_clear(void)
{ struct kmemleak_object *object;
/* * File write operation to configure kmemleak at run-time. The following * commands can be written to the /sys/kernel/debug/kmemleak file: * off - disable kmemleak (irreversible) * stack=on - enable the task stacks scanning * stack=off - disable the tasks stacks scanning * scan=on - start the automatic memory scanning thread * scan=off - stop the automatic memory scanning thread * scan=... - set the automatic memory scanning period in seconds (0 to * disable it) * scan - trigger a memory scan * clear - mark all current reported unreferenced kmemleak objects as * grey to ignore printing them, or free all kmemleak objects * if kmemleak has been disabled. * dump=... - dump information about the object found at the given address
*/ static ssize_t kmemleak_write(struct file *file, constchar __user *user_buf,
size_t size, loff_t *ppos)
{ char buf[64]; int buf_size; int ret;
/* * Kmemleak has already been disabled, no need for RCU list traversal * or kmemleak_lock held.
*/
list_for_each_entry_safe(object, tmp, &object_list, object_list) {
__remove_object(object);
__delete_object(object);
/* Call cond_resched() once per 64 iterations to avoid soft lockup */ if (!(++cnt & 0x3f))
cond_resched();
}
}
/* * Stop the memory scanning thread and free the kmemleak internal objects if * no previous scan thread (otherwise, kmemleak may still have some useful * information on memory leaks).
*/ staticvoid kmemleak_do_cleanup(struct work_struct *work)
{
stop_scan_thread();
mutex_lock(&scan_mutex); /* * Once it is made sure that kmemleak_scan has stopped, it is safe to no * longer track object freeing. Ordering of the scan thread stopping and * the memory accesses below is guaranteed by the kthread_stop() * function.
*/
kmemleak_free_enabled = 0;
mutex_unlock(&scan_mutex);
if (!kmemleak_found_leaks)
__kmemleak_do_cleanup(); else
pr_info("Kmemleak disabled without freeing internal data. Reclaim the memory with \"echo clear > /sys/kernel/debug/kmemleak\".\n");
}
/* * Disable kmemleak. No memory allocation/freeing will be traced once this * function is called. Disabling kmemleak is an irreversible operation.
*/ staticvoid kmemleak_disable(void)
{ /* atomically check whether it was already invoked */ if (cmpxchg(&kmemleak_error, 0, 1)) return;
/* stop any memory operation tracing */
kmemleak_enabled = 0;
/* check whether it is too early for a kernel thread */ if (kmemleak_late_initialized)
schedule_work(&cleanup_work); else
kmemleak_free_enabled = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.