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>
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)
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
{
}
+static inline bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
+{
+ return true;
+}
+
#endif /* CONFIG_KMEMCHECK */
/*
#include <asm/processor.h>
#include <asm/atomic.h>
+#include <linux/kmemcheck.h>
#include <linux/kmemleak.h>
/*
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;