diff options
-rw-r--r-- | arch/x86/mm/kmemcheck/kmemcheck.c | 14 | ||||
-rw-r--r-- | include/linux/kmemcheck.h | 7 | ||||
-rw-r--r-- | mm/kmemleak.c | 12 |
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 | ||
334 | bool 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 */ |
335 | static void kmemcheck_read(struct pt_regs *regs, | 349 | static 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); | |||
34 | int kmemcheck_show_addr(unsigned long address); | 34 | int kmemcheck_show_addr(unsigned long address); |
35 | int kmemcheck_hide_addr(unsigned long address); | 35 | int kmemcheck_hide_addr(unsigned long address); |
36 | 36 | ||
37 | bool 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 | ||
104 | static 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; |