aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Enberg <penberg@cs.helsinki.fi>2009-08-27 09:50:00 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2009-09-04 11:05:55 -0400
commit8e019366ba749a536131cde1947af6dcaccf8e8f (patch)
treefc44a33fc43265652b93f6f3251d5a73cda2e5ee
parentacde31dc467797ccae3a55b791a77af446cce018 (diff)
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>
-rw-r--r--arch/x86/mm/kmemcheck/kmemcheck.c14
-rw-r--r--include/linux/kmemcheck.h7
-rw-r--r--mm/kmemleak.c12
3 files changed, 31 insertions, 2 deletions
diff --git a/arch/x86/mm/kmemcheck/kmemcheck.c b/arch/x86/mm/kmemcheck/kmemcheck.c
index 2c55ed098654..528bf954eb74 100644
--- a/arch/x86/mm/kmemcheck/kmemcheck.c
+++ b/arch/x86/mm/kmemcheck/kmemcheck.c
@@ -331,6 +331,20 @@ static void kmemcheck_read_strict(struct pt_regs *regs,
331 kmemcheck_shadow_set(shadow, size); 331 kmemcheck_shadow_set(shadow, size);
332} 332}
333 333
334bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
335{
336 enum kmemcheck_shadow status;
337 void *shadow;
338
339 shadow = kmemcheck_shadow_lookup(addr);
340 if (!shadow)
341 return true;
342
343 status = kmemcheck_shadow_test(shadow, size);
344
345 return status == KMEMCHECK_SHADOW_INITIALIZED;
346}
347
334/* Access may cross page boundary */ 348/* Access may cross page boundary */
335static void kmemcheck_read(struct pt_regs *regs, 349static void kmemcheck_read(struct pt_regs *regs,
336 unsigned long addr, unsigned int size) 350 unsigned long addr, unsigned int size)
diff --git a/include/linux/kmemcheck.h b/include/linux/kmemcheck.h
index 47b39b7c7e84..dc2fd545db00 100644
--- a/include/linux/kmemcheck.h
+++ b/include/linux/kmemcheck.h
@@ -34,6 +34,8 @@ void kmemcheck_mark_initialized_pages(struct page *p, unsigned int n);
34int kmemcheck_show_addr(unsigned long address); 34int kmemcheck_show_addr(unsigned long address);
35int kmemcheck_hide_addr(unsigned long address); 35int kmemcheck_hide_addr(unsigned long address);
36 36
37bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size);
38
37#else 39#else
38#define kmemcheck_enabled 0 40#define kmemcheck_enabled 0
39 41
@@ -99,6 +101,11 @@ static inline void kmemcheck_mark_initialized_pages(struct page *p,
99{ 101{
100} 102}
101 103
104static inline bool kmemcheck_is_obj_initialized(unsigned long addr, size_t size)
105{
106 return true;
107}
108
102#endif /* CONFIG_KMEMCHECK */ 109#endif /* CONFIG_KMEMCHECK */
103 110
104/* 111/*
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 1d7645b0a97c..c494fee7a2b5 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -97,6 +97,7 @@
97#include <asm/processor.h> 97#include <asm/processor.h>
98#include <asm/atomic.h> 98#include <asm/atomic.h>
99 99
100#include <linux/kmemcheck.h>
100#include <linux/kmemleak.h> 101#include <linux/kmemleak.h>
101 102
102/* 103/*
@@ -967,15 +968,22 @@ static void scan_block(void *_start, void *_end,
967 unsigned long *end = _end - (BYTES_PER_POINTER - 1); 968 unsigned long *end = _end - (BYTES_PER_POINTER - 1);
968 969
969 for (ptr = start; ptr < end; ptr++) { 970 for (ptr = start; ptr < end; ptr++) {
970 unsigned long flags;
971 unsigned long pointer = *ptr;
972 struct kmemleak_object *object; 971 struct kmemleak_object *object;
972 unsigned long flags;
973 unsigned long pointer;
973 974
974 if (allow_resched) 975 if (allow_resched)
975 cond_resched(); 976 cond_resched();
976 if (scan_should_stop()) 977 if (scan_should_stop())
977 break; 978 break;
978 979
980 /* don't scan uninitialized memory */
981 if (!kmemcheck_is_obj_initialized((unsigned long)ptr,
982 BYTES_PER_POINTER))
983 continue;
984
985 pointer = *ptr;
986
979 object = find_and_get_object(pointer, 1); 987 object = find_and_get_object(pointer, 1);
980 if (!object) 988 if (!object)
981 continue; 989 continue;