On Friday 26 January 2007 16:13, Jeff Dike wrote:
> On Fri, Jan 26, 2007 at 04:07:05AM -0500, William Stearns wrote:
> >     After bisecting the difference between the two root filesystems,
> > the critical change was a line in /etc/fstab:
> >
> > none            /mirrors        hostfs  defaults,/home/mirrors  0 0
> >
> >     Woah.

Ok, I think I have found it from code analisys (no testing done). Please test 
the attached patch, since the bug is repeatable for you.

Ok, we have a double kfree inside hostfs_fill_sb_common; since name is 
assigned to host_filename, it is owned by the inode, and freed both by dput 
and by kfree(name).

The path from dput to the first free is:
dput->iput->hostfs_destroy_inode->kfree(... ->host_filename)

The simplest fix is to clear 'name' after assigning it to ->host_filename. 
Patch attached - the second hunk is totally optional, it avoids a 
kfree(NULL);. The goal was maximum simplicity here.

Also, I discovered that in read_inode, failure from file_type (which calls 
lstat64) is ignored. read_name is subsequently called, it calls lstat again, 
so this should not be a problem; however, the other call to file_type (in 
init_inode) is also unchecked, and that is less robust.
-- 
Inform me of my mistakes, so I can add them to my list!
Paolo Giarrusso, aka Blaisorblade
http://www.user-mode-linux.org/~blaisorblade
Subject: uml - hostfs: fix double free

From: Paolo 'Blaisorblade' Giarrusso <[EMAIL PROTECTED]>

Fix double free in the error path - when name is assigned into root_inode we do
not own it any more and we must not kfree() it - see patch for details.

Thanks to William Stearns for the initial report.

CC: William Stearns <[EMAIL PROTECTED]>
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <[EMAIL PROTECTED]>
Index: linux-2.6.git/fs/hostfs/hostfs_kern.c
===================================================================
--- linux-2.6.git.orig/fs/hostfs/hostfs_kern.c
+++ linux-2.6.git/fs/hostfs/hostfs_kern.c
@@ -966,6 +966,9 @@ static int hostfs_fill_sb_common(struct 
 		goto out_put;
 
 	HOSTFS_I(root_inode)->host_filename = name;
+	/* Avoid that in the error path, iput(root_inode) frees again name through
+	 * hostfs_destroy_inode! */
+	name = NULL;
 
 	err = -ENOMEM;
 	sb->s_root = d_alloc_root(root_inode);
@@ -977,7 +980,7 @@ static int hostfs_fill_sb_common(struct 
                 /* No iput in this case because the dput does that for us */
                 dput(sb->s_root);
                 sb->s_root = NULL;
-		goto out_free;
+		goto out;
         }
 
 	return(0);
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

Reply via email to