Kernel memleak in jffs2_erase_block() (fs/jffs2/erase.c:78)

Jörn Engel joern at logfs.org
Mon Nov 12 07:28:52 EST 2007


On Mon, 12 November 2007 13:39:02 +0300, Damir Shayhutdinov wrote:
> 
> I'm studying JFFS2 code now, and I believe I've found a kernel memory leak.
> 
> fs/jffs2/erase.c:
> 
> 76         ret = c->mtd->erase(c->mtd, instr);
> 77         if (!ret)
> 78                 return;
> 
> In case of ret == 0 (erase succeeded), line 78 leaves the function
> jffs2_erase_block without kfree-ing previously kmalloc-ed pointer
> instr (line 50).
> 
> So, sizeof(struct erase_info) + sizeof(struct erase_priv_struct) bytes
> are leaking each time block is erased successfully.

Makes 64 Bytes, including kmalloc overhead.  On every successful erase.
David, please apply.

Jörn

-- 
It does not require a majority to prevail, but rather an irate,
tireless minority keen to set brush fires in people's minds.
-- Samuel Adams

Plug memleak in jffs2_erase_block()

Also does a kzalloc conversion, while in the area.

Signed-off-by: Jörn Engel <joern at logfs.org>
Reported-by: Damir Shayhutdinov <lost404 at gmail.com>
---

 fs/jffs2/erase.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

--- linux-2.6.23logfs/fs/jffs2/erase.c~jffs2_erase	2007-08-08 19:30:19.000000000 +0200
+++ linux-2.6.23logfs/fs/jffs2/erase.c	2007-11-12 13:27:03.000000000 +0100
@@ -47,7 +47,7 @@ static void jffs2_erase_block(struct jff
 
 	D1(printk(KERN_DEBUG "jffs2_erase_block(): erase block %#08x (range %#08x-%#08x)\n",
 				jeb->offset, jeb->offset, jeb->offset + c->sector_size));
-	instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
+	instr = kzalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL);
 	if (!instr) {
 		printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
 		spin_lock(&c->erase_completion_lock);
@@ -59,8 +59,6 @@ static void jffs2_erase_block(struct jff
 		return;
 	}
 
-	memset(instr, 0, sizeof(*instr));
-
 	instr->mtd = c->mtd;
 	instr->addr = jeb->offset;
 	instr->len = c->sector_size;
@@ -72,11 +70,11 @@ static void jffs2_erase_block(struct jff
 	((struct erase_priv_struct *)instr->priv)->c = c;
 
 	ret = c->mtd->erase(c->mtd, instr);
+	bad_offset = instr->fail_addr;
+	kfree(instr);
 	if (!ret)
 		return;
 
-	bad_offset = instr->fail_addr;
-	kfree(instr);
 #endif /* __ECOS */
 
 	if (ret == -ENOMEM || ret == -EAGAIN) {



More information about the linux-mtd mailing list