Subject: BUG : Memory leak in Linux 2.4.2 MIPS SMP kernel

From: Krishna Kondaka <[email-masked]>
Date: Tue, 13 Nov 2001 15:36:32 -0800 (PST)

Hi,

	Here is the bug we found in the Linux 2.4.2 MIPS SMP kernel and the
	fix for the bug.
	
1. Summary:
	Memory leak in Linux 2.4.2 MIPS SMP kernel

2. Description:
	Memory leak happens whenever a process is created and destroyed.
	Whatever memory allocated during process creation is not getting
	freed when the process exits. This problem can be easily reproduced
	by writing any program/script which does a lot of process creation
	and termination. my test script is
	
	while true
	do
		cat /proc/meminfo
		ls /bin
		cat /proc/slabinfo
	end
	
	when /proc/slabinfo is printed, we can see that size of 32-byte
	memory chunks growing indefinitely and eventually causing the
	following panic:
	
	kernel BUG at page_alloc.c:75!
Unable to handle kernel paging request at virtual address 00000000, epc == 
8013bcdc, ra == 8013bcdc
Oops in fault.c:do_page_fault, line 172:
$0 : 00000000 10009f00 0000001f 0000000a
$4 : 802afc10 00000001 00000001 00000000
$8 : 802d7636 b0060170 0000001f 0000000d
$12: 00000000 0000001f 10009f00 0000000a
$16: 80329f50 80329f50 00000000 00657a03
$20: 8053000c 806451a0 80b785a0 ffc00000
$24: 802d7617 8036dca1
$28: 8036c000 8036de08 806451a0 8013bcdc
epc    : 000000008013bcdc
Status : 10009f03
Cause  : 1080000c

BadAddr: 00000000ffc00000Process kswapd (pid: 5, stackpage=8036c000)
Stack: 80253434 8025344c 0000004b 00000001 806451a0 00403000 80329f50 00403000
       00000001 00657a03 8053000c 806451a0 80b785a0 ffc00000 806451a0 8013cba8
       00403000 00000000 80329f50 00403000 801395fc 8013967c 00000000 00000000
       00000000 00000000 00000000 00000000 00657a03 00000000 00000000 00000000
       00000000 00000000 00403000 8053000c 00000007 00424000 80b785a0 806451a0
       ffc00000 ...
Call Trace: [<80253434>] [<8025344c>] [<8013cba8>] [<801395fc>] [<8013967c>] 
[<801398b8>]
 [<801399d8>] [<80139ab0>] [<80136a30>] [<8013b42c>] [<80139c1c>] [<80139c24>]
 [<80162fa8>] [<8013b3e8>] [<8013b4a0>] [<8013b524>] [<8013b55c>] [<80107d38>]
 [<80108d9c>] [<80108d8c>]

3. Keywords
	mips, SMP, memory leak

4. Kernel version

	Linux version 2.4.2

5. Output
	(included as part of description)

6. testcase
	(included as part of description)

7. Environment
	7.1 software
		None
	7.2 Processor info
		(NOTE *** cat /proc/cpuinfo does not print information about 
		    both the CPUs ***)
		cpu                     : MIPS
		processor               : 0
		cpu model               : SiByte SB1 V0.1
		BogoMIPS                : 332.59
		processor               : 1
		cpu model               : SiByte SB1 V0.1
		BogoMIPS                : 332.59
		system type             : SiByte unknown
		byteorder               : big endian
		unaligned accesses      : 0
		wait instruction        : no
		microsecond timers      : no
		extra interrupt vector  : yes
		hardware watchpoint     : no
		VCED exceptions         : not available
		VCEI exceptions         : not available
	7.3 Module information
		No modules.
	7.4 Loaded driver and hardware information (/proc/ioports, /proc/iomem)
	
		bash-2.04# cat /proc/ioports
		bash-2.04# cat /proc/iomem
		00000000-0fe94fff : System RAM
		  00100000-00267d77 : Kernel code
		  00299a40-002ad38f : Kernel data
	7.5 PCI information
		No PCI devices attached
	7.6 SCSI information
		No SCSI devices attached
	7.7 Other information

8. Fix

I found that the bug is in destroy_context() in include/asm-mips/mmu_context.h.
destroy_context() is supposed to kfree() the memory that is allocated by
init_new_context() but it is not doing that.

I modified destroy_context as follows:

/*
 * Destroy context related info for an mm_struct that is about
 * to be put to rest.
 */
extern inline void destroy_context(struct mm_struct *mm)
{
#ifdef CONFIG_SMP
        kfree((void *)mm->context);
#else
        /* Nothing to do.  */
#endif
}

And when I tested this I do not see the memory leak any more.

Krishna Kondaka
Sanera Systems Inc.
[email-masked]

---

From: James Simmons <[email-masked]>
Date: Tue, 13 Nov 2001 15:42:26 -0800 (PST)

> 	Memory leak in Linux 2.4.2 MIPS SMP kernel

Fixed in the latest tree.

> And when I tested this I do not see the memory leak any more.

BTW you should check to see if mm->context really exist. It can bomb out
otherwise.

Current function is:

static inline void destroy_context(struct mm_struct *mm)
{
#ifdef CONFIG_SMP
        if (mm->context)
                kfree((void *)mm->context);
#endif
}

---

From: Ralf Baechle <[email-masked]>
Date: Wed, 14 Nov 2001 10:47:53 +1100

> And when I tested this I do not see the memory leak any more.

Almost correct, as James already explained you have to check for a
non-null pointer first.  We got a more elegant implementation of
context switching which I'll add to CVS asap; it gets away without
any memory allocation.

  Ralf

---

From: James Simmons <[email-masked]>
Date: Tue, 13 Nov 2001 16:16:57 -0800 (PST)

> non-null pointer first.  

Hm. It was pointed out that kfree actually does the checking for us. 
Do we really need the check? 

> We got a more elegant implementation of

:-)

---

From: Ralf Baechle <[email-masked]>
Date: Wed, 14 Nov 2001 11:19:36 +1100

> Do we really need the check? 

Seems that check sneaked in without telling me :-)

  Ralf

---

From: James Simmons <[email-masked]>
Date: Tue, 13 Nov 2001 16:28:22 -0800 (PST)

> Seems that check sneaked in without telling me :-)

I didn't know here. I have been bite by kfree when passing a null pointer
to it before. I'm glad their is a nice check.