kmemleak: Don't scan uninitialized memory when kmemcheck is enabled
Ingo Molnar reported the following kmemcheck warning when running both kmemleak and kmemcheck enabled: PM: Adding info for No Bus:vcsa7 WARNING: kmemcheck: Caught 32-bit read from uninitialized memory (f6f6e1a4) d873f9f600000000c42ae4c1005c87f70000000070665f666978656400000000 i i i i u u u u i i i i i i i i i i i i i i i i i i i i i u u u ^ Pid: 3091, comm: kmemleak Not tainted (2.6.31-rc7-tip #1303) P4DC6 EIP: 0060:[<c110301f>] EFLAGS: 00010006 CPU: 0 EIP is at scan_block+0x3f/0xe0 EAX: f40bd700 EBX: f40bd780 ECX: f16b46c0 EDX: 00000001 ESI: f6f6e1a4 EDI: 00000000 EBP: f10f3f4c ESP: c2605fcc DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 CR0: 8005003b CR2: e89a4844 CR3: 30ff1000 CR4: 000006f0 DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 DR6: ffff4ff0 DR7: 00000400 [<c110313c>] scan_object+0x7c/0xf0 [<c1103389>] kmemleak_scan+0x1d9/0x400 [<c1103a3c>] kmemleak_scan_thread+0x4c/0xb0 [<c10819d4>] kthread+0x74/0x80 [<c10257db>] kernel_thread_helper+0x7/0x3c [<ffffffff>] 0xffffffff kmemleak: 515 new suspected memory leaks (see /sys/kernel/debug/kmemleak) kmemleak: 42 new suspected memory leaks (see /sys/kernel/debug/kmemleak) The problem here is that kmemleak will scan partially initialized objects that makes kmemcheck complain. Fix that up by skipping uninitialized memory regions when kmemcheck is enabled. Reported-by: Ingo Molnar <mingo@elte.hu> Acked-by: Ingo Molnar <mingo@elte.hu> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
This commit is contained in:
parent
acde31dc46
commit
8e019366ba
|
@ -331,6 +331,20 @@ static void kmemcheck_read_strict(struct pt_regs *regs,
|
|||
kmemcheck_shadow_set(shadow, size);
|
||||
}
|
||||
|
||||
bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
|
||||
{
|
||||
enum kmemcheck_shadow status;
|
||||
void *shadow;
|
||||
|
||||
shadow = kmemcheck_shadow_lookup(addr);
|
||||
if (!shadow)
|
||||
return true;
|
||||
|
||||
status = kmemcheck_shadow_test(shadow, size);
|
||||
|
||||
return status == KMEMCHECK_SHADOW_INITIALIZED;
|
||||
}
|
||||
|
||||
/* Access may cross page boundary */
|
||||
static void kmemcheck_read(struct pt_regs *regs,
|
||||
unsigned long addr, unsigned int size)
|
||||
|
|
|
@ -34,6 +34,8 @@ void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n);
|
|||
int kmemcheck_show_addr(unsigned long address);
|
||||
int kmemcheck_hide_addr(unsigned long address);
|
||||
|
||||
bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);
|
||||
|
||||
#else
|
||||
#define kmemcheck_enabled 0
|
||||
|
||||
|
@ -99,6 +101,11 @@ static inline void kmemcheck_mark_initialized_pages(struct page *p,
|
|||
{
|
||||
}
|
||||
|
||||
static inline bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KMEMCHECK */
|
||||
|
||||
/*
|
||||
|
|
|
@ -97,6 +97,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#include <linux/kmemcheck.h>
|
||||
#include <linux/kmemleak.h>
|
||||
|
||||
/*
|
||||
|
@ -967,15 +968,22 @@ static void scan_block(void *_start, void *_end,
|
|||
unsigned long *end = _end - (BYTES_PER_POINTER - 1);
|
||||
|
||||
for (ptr = start; ptr < end; ptr++) {
|
||||
unsigned long flags;
|
||||
unsigned long pointer = *ptr;
|
||||
struct kmemleak_object *object;
|
||||
unsigned long flags;
|
||||
unsigned long pointer;
|
||||
|
||||
if (allow_resched)
|
||||
cond_resched();
|
||||
if (scan_should_stop())
|
||||
break;
|
||||
|
||||
/* don't scan uninitialized memory */
|
||||
if (!kmemcheck_is_obj_initialized((unsigned long)ptr,
|
||||
BYTES_PER_POINTER))
|
||||
continue;
|
||||
|
||||
pointer = *ptr;
|
||||
|
||||
object = find_and_get_object(pointer, 1);
|
||||
if (!object)
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue