Skip to content

Commit

Permalink
kmemleak: Don't scan uninitialized memory when kmemcheck is enabled
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Ingo Molnar <[email protected]>
Acked-by: Catalin Marinas <[email protected]>
Signed-off-by: Pekka Enberg <[email protected]>
  • Loading branch information
Pekka Enberg authored and ctmarinas committed Sep 4, 2009
1 parent acde31d commit 8e01936
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
14 changes: 14 additions & 0 deletions arch/x86/mm/kmemcheck/kmemcheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions include/linux/kmemcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 */

/*
Expand Down
12 changes: 10 additions & 2 deletions mm/kmemleak.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
#include <asm/processor.h>
#include <asm/atomic.h>

#include <linux/kmemcheck.h>
#include <linux/kmemleak.h>

/*
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 8e01936

Please sign in to comment.