Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/ufs/ffs In fact, we need to sanitize the superblock *aft...
details: https://anonhg.NetBSD.org/src/rev/c2d3328ba6bb
branches: trunk
changeset: 336139:c2d3328ba6bb
user: maxv <maxv%NetBSD.org@localhost>
date: Sat Feb 14 09:55:53 2015 +0000
description:
In fact, we need to sanitize the superblock *after* swapping it. Therefore,
move the swap code inside the loop.
'fs->fs_sbsize' is swapped twice: the first time in order to get the
correct superblock size, and later when swapping the whole superblock
structure. As a result, we need to check 'fs->fs_sbsize' twice.
This:
- fixes my previous changes for swapped FSes
- allows the kernel to look for other superblock locations if the
current superblock is not validated
And now:
- ffs_superblock_validate() takes only one argument: the fs structure
- 'fs_bsize' is unused, so delete it
Add some comments to explain a bit what we are doing.
diffstat:
sys/ufs/ffs/ffs_vfsops.c | 64 ++++++++++++++++++++++++++++-------------------
1 files changed, 38 insertions(+), 26 deletions(-)
diffs (162 lines):
diff -r 8bc453ee93fa -r c2d3328ba6bb sys/ufs/ffs/ffs_vfsops.c
--- a/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 09:06:11 2015 +0000
+++ b/sys/ufs/ffs/ffs_vfsops.c Sat Feb 14 09:55:53 2015 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_vfsops.c,v 1.313 2015/02/14 09:00:12 maxv Exp $ */
+/* $NetBSD: ffs_vfsops.c,v 1.314 2015/02/14 09:55:53 maxv Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.313 2015/02/14 09:00:12 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.314 2015/02/14 09:55:53 maxv Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -115,7 +115,7 @@
ffs_vfs_fsync(vnode_t *, int);
static int
-ffs_superblock_validate(struct fs *fs, u_int32_t fs_sbsize, int32_t fs_bsize);
+ffs_superblock_validate(struct fs *fs);
static struct sysctllog *ffs_sysctl_log;
@@ -758,7 +758,7 @@
kmem_free(newfs, fs_sbsize);
return (EIO); /* XXX needs translation */
}
- if (!ffs_superblock_validate(newfs, newfs->fs_sbsize, newfs->fs_bsize)) {
+ if (!ffs_superblock_validate(newfs)) {
brelse(bp, 0);
kmem_free(newfs, fs_sbsize);
return (EINVAL);
@@ -923,16 +923,16 @@
static int
-ffs_superblock_validate(struct fs *fs, u_int32_t fs_sbsize, int32_t fs_bsize)
+ffs_superblock_validate(struct fs *fs)
{
/* Check the superblock size */
- if (fs_sbsize > SBLOCKSIZE || fs_sbsize < sizeof(struct fs))
+ if (fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < sizeof(struct fs))
return 0;
/* Check the file system blocksize */
- if (fs_bsize > MAXBSIZE || fs_bsize < MINBSIZE)
+ if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < MINBSIZE)
return 0;
- if (!powerof2(fs_bsize))
+ if (!powerof2(fs->fs_bsize))
return 0;
/* Check the size of frag blocks */
@@ -945,11 +945,11 @@
return 0;
/* Block size cannot be smaller than fragment size */
- if (fs_bsize < fs->fs_fsize)
+ if (fs->fs_bsize < fs->fs_fsize)
return 0;
/* Check the number of frag blocks */
- if ((fs_bsize / fs->fs_fsize) > MAXFRAG)
+ if ((fs->fs_bsize / fs->fs_fsize) > MAXFRAG)
return 0;
return 1;
@@ -1015,7 +1015,6 @@
*/
for (i = 0; ; i++) {
daddr_t fsblockloc;
- int32_t fs_bsize;
if (bp != NULL) {
brelse(bp, BC_NOCACHE);
@@ -1040,28 +1039,30 @@
fsblockloc = sblockloc = sblock_try[i];
DPRINTF(("%s: fs_magic 0x%x\n", __func__, fs->fs_magic));
+
+ /*
+ * Swap: here, we swap fs->fs_sbsize in order to get the correct
+ * size to read the superblock. Once read, we swap the whole
+ * superblock structure.
+ */
if (fs->fs_magic == FS_UFS1_MAGIC) {
fs_sbsize = fs->fs_sbsize;
fstype = UFS1;
- fs_bsize = fs->fs_bsize;
#ifdef FFS_EI
needswap = 0;
} else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED) {
fs_sbsize = bswap32(fs->fs_sbsize);
fstype = UFS1;
- fs_bsize = bswap32(fs->fs_bsize);
needswap = 1;
#endif
} else if (fs->fs_magic == FS_UFS2_MAGIC) {
fs_sbsize = fs->fs_sbsize;
fstype = UFS2;
- fs_bsize = fs->fs_bsize;
#ifdef FFS_EI
needswap = 0;
} else if (fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) {
fs_sbsize = bswap32(fs->fs_sbsize);
fstype = UFS2;
- fs_bsize = bswap32(fs->fs_bsize);
needswap = 1;
#endif
} else
@@ -1089,25 +1090,36 @@
if (fsblockloc != sblockloc)
continue;
- if (!ffs_superblock_validate(fs, fs_sbsize, fs_bsize))
+ /* Check the superblock size */
+ if (fs_sbsize > SBLOCKSIZE || fs_sbsize < sizeof(struct fs))
continue;
+ fs = kmem_alloc((u_long)fs_sbsize, KM_SLEEP);
+ memcpy(fs, bp->b_data, fs_sbsize);
+
+ /* Swap the whole superblock structure, if necessary. */
+#ifdef FFS_EI
+ if (needswap) {
+ ffs_sb_swap((struct fs*)bp->b_data, fs);
+ fs->fs_flags |= FS_SWAPPED;
+ } else
+#endif
+ fs->fs_flags &= ~FS_SWAPPED;
+
+ /*
+ * Now that everything is swapped, the superblock is ready to
+ * be sanitized.
+ */
+ if (!ffs_superblock_validate(fs)) {
+ kmem_free(fs, fs_sbsize);
+ continue;
+ }
/* Ok seems to be a good superblock */
break;
}
- fs = kmem_alloc((u_long)fs_sbsize, KM_SLEEP);
- memcpy(fs, bp->b_data, fs_sbsize);
ump->um_fs = fs;
-#ifdef FFS_EI
- if (needswap) {
- ffs_sb_swap((struct fs*)bp->b_data, fs);
- fs->fs_flags |= FS_SWAPPED;
- } else
-#endif
- fs->fs_flags &= ~FS_SWAPPED;
-
#ifdef WAPBL
if ((mp->mnt_wapbl_replay == 0) && (fs->fs_flags & FS_DOWAPBL)) {
error = ffs_wapbl_replay_start(mp, fs, devvp);
Home |
Main Index |
Thread Index |
Old Index