tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

FFS: memory corruption



There is a kmem inconsistency in ffs_reload().

676	newfs = kmem_alloc(fs->fs_sbsize, KM_SLEEP);
677	memcpy(newfs, bp->b_data, fs->fs_sbsize);

and later:

705	memcpy(fs, newfs, (u_int)fs->fs_sbsize);
706	brelse(bp, 0);
707	kmem_free(newfs, fs->fs_sbsize);

The memcpy here overwrites fs->fs_sbsize with the new superblock
size read on the disk; so the value may change. kmem_free may
then pick up the wrong cache - and panic.

This looks like a proper bug, not "intentional". I would suggest
the following:

Index: ffs_vfsops.c
===================================================================
RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.300
diff -u -r1.300 ffs_vfsops.c
--- ffs_vfsops.c	24 Oct 2014 13:18:51 -0000	1.300
+++ ffs_vfsops.c	27 Oct 2014 18:34:17 -0000
@@ -648,6 +648,7 @@
 	struct ufsmount *ump;
 	daddr_t sblockloc;
 	struct vnode_iterator *marker;
+	u_int32_t sbsize;
 
 	if ((mp->mnt_flag & MNT_RDONLY) == 0)
 		return (EINVAL);
@@ -666,15 +667,16 @@
 	 * Step 2: re-read superblock from disk.
 	 */
 	fs = ump->um_fs;
+	sbsize = fs->fs_sbsize;
 
 	/* XXX we don't handle possibility that superblock moved. */
-	error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, fs->fs_sbsize,
+	error = bread(devvp, fs->fs_sblockloc / DEV_BSIZE, sbsize,
 		      NOCRED, 0, &bp);
 	if (error) {
 		return (error);
 	}
-	newfs = kmem_alloc(fs->fs_sbsize, KM_SLEEP);
-	memcpy(newfs, bp->b_data, fs->fs_sbsize);
+	newfs = kmem_alloc(sbsize, KM_SLEEP);
+	memcpy(newfs, bp->b_data, sbsize);
 #ifdef FFS_EI
 	if (ump->um_flags & UFS_NEEDSWAP) {
 		ffs_sb_swap((struct fs*)bp->b_data, newfs);
@@ -687,7 +689,7 @@
 	     newfs->fs_bsize > MAXBSIZE ||
 	     newfs->fs_bsize < sizeof(struct fs)) {
 		brelse(bp, 0);
-		kmem_free(newfs, fs->fs_sbsize);
+		kmem_free(newfs, sbsize);
 		return (EIO);		/* XXX needs translation */
 	}
 	/* Store off old fs_sblockloc for fs_oldfscompat_read. */
@@ -702,9 +704,9 @@
 	newfs->fs_contigdirs = fs->fs_contigdirs;
 	newfs->fs_ronly = fs->fs_ronly;
 	newfs->fs_active = fs->fs_active;
-	memcpy(fs, newfs, (u_int)fs->fs_sbsize);
+	memcpy(fs, newfs, sbsize);
 	brelse(bp, 0);
-	kmem_free(newfs, fs->fs_sbsize);
+	kmem_free(newfs, sbsize);
 
 	/* Recheck for apple UFS filesystem */
 	ump->um_flags &= ~UFS_ISAPPLEUFS;


Ok/Comments?


Home | Main Index | Thread Index | Old Index