Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107033336
D35219.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D35219.diff
View Options
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -35,6 +35,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/limits.h>
#ifndef _KERNEL
#include <stdio.h>
@@ -50,6 +51,7 @@
struct malloc_type;
#define UFS_MALLOC(size, type, flags) malloc(size)
#define UFS_FREE(ptr, type) free(ptr)
+#define maxphys MAXPHYS
#else /* _KERNEL */
#include <sys/systm.h>
@@ -125,6 +127,7 @@
static off_t sblock_try[] = SBLOCKSEARCH;
static int readsuper(void *, struct fs **, off_t, int, int,
int (*)(void *, off_t, void **, int));
+static int validate_sblock(struct fs *, int);
/*
* Read a superblock from the devfd device.
@@ -141,7 +144,7 @@
* EIO: non-existent or truncated superblock.
* EIO: error reading summary information.
* ENOENT: no usable known superblock found.
- * ENOSPC: failed to allocate space for the superblock.
+ * ENOMEM: failed to allocate space for the superblock.
* EINVAL: The previous newfs operation on this volume did not complete.
* The administrator must complete newfs before using this volume.
*/
@@ -152,7 +155,8 @@
{
struct fs *fs;
struct fs_summary_info *fs_si;
- int i, error, size, blks;
+ int i, error;
+ uint64_t size, blks;
uint8_t *space;
int32_t *lp;
char *buf;
@@ -190,17 +194,16 @@
if (fs->fs_contigsumsize > 0)
size += fs->fs_ncg * sizeof(int32_t);
size += fs->fs_ncg * sizeof(u_int8_t);
- /* When running in libufs or libsa, UFS_MALLOC may fail */
- if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_WAITOK)) == NULL) {
+ if ((fs_si = UFS_MALLOC(sizeof(*fs_si), filltype, M_NOWAIT)) == NULL) {
UFS_FREE(fs, filltype);
- return (ENOSPC);
+ return (ENOMEM);
}
bzero(fs_si, sizeof(*fs_si));
fs->fs_si = fs_si;
- if ((space = UFS_MALLOC(size, filltype, M_WAITOK)) == NULL) {
+ if ((space = UFS_MALLOC(size, filltype, M_NOWAIT)) == NULL) {
UFS_FREE(fs->fs_si, filltype);
UFS_FREE(fs, filltype);
- return (ENOSPC);
+ return (ENOMEM);
}
fs->fs_csp = (struct csum *)space;
for (i = 0; i < blks; i += fs->fs_frag) {
@@ -253,16 +256,8 @@
fs = *fsp;
if (fs->fs_magic == FS_BAD_MAGIC)
return (EINVAL);
- if (!(((fs->fs_magic == FS_UFS1_MAGIC && (isaltsblk ||
- sblockloc <= SBLOCK_UFS1)) ||
- (fs->fs_magic == FS_UFS2_MAGIC && (isaltsblk ||
- sblockloc == fs->fs_sblockloc))) &&
- fs->fs_ncg >= 1 &&
- fs->fs_bsize >= MINBSIZE &&
- fs->fs_bsize <= MAXBSIZE &&
- fs->fs_bsize >= roundup(sizeof(struct fs), DEV_BSIZE) &&
- fs->fs_sbsize <= SBLOCKSIZE))
- return (ENOENT);
+ if ((error = validate_sblock(fs, isaltsblk)) != 0)
+ return (error);
/*
* If the filesystem has been run on a kernel without
* metadata check hashes, disable them.
@@ -310,6 +305,140 @@
return (0);
}
+/*
+ * Verify the filesystem values.
+ */
+#define ILOG2(num) (fls(num) - 1)
+
+static int
+validate_sblock(struct fs *fs, int isaltsblk)
+{
+ int i, sectorsize;
+ u_int64_t maxfilesize, minfpg, sizepb;
+
+ sectorsize = dbtob(1);
+ if (fs->fs_magic == FS_UFS2_MAGIC) {
+ if ((!isaltsblk && (fs->fs_sblockloc != SBLOCK_UFS2 ||
+ fs->fs_sblockactualloc != SBLOCK_UFS2)) ||
+ fs->fs_maxsymlinklen != ((UFS_NDADDR + UFS_NIADDR) *
+ sizeof(ufs2_daddr_t)) ||
+ fs->fs_nindir != fs->fs_bsize / sizeof(ufs2_daddr_t) ||
+ fs->fs_inopb != fs->fs_bsize / sizeof(struct ufs2_dinode))
+ return (ENOENT);
+ } else if (fs->fs_magic == FS_UFS1_MAGIC) {
+ if ((!isaltsblk && (fs->fs_sblockloc > SBLOCK_UFS1 ||
+ fs->fs_sblockactualloc != SBLOCK_UFS1)) ||
+ fs->fs_nindir != fs->fs_bsize / sizeof(ufs1_daddr_t) ||
+ fs->fs_inopb != fs->fs_bsize / sizeof(struct ufs1_dinode) ||
+ fs->fs_maxsymlinklen != ((UFS_NDADDR + UFS_NIADDR) *
+ sizeof(ufs1_daddr_t)) ||
+ fs->fs_old_inodefmt != FS_44INODEFMT ||
+ fs->fs_old_cgoffset != 0 ||
+ fs->fs_old_cgmask != 0xffffffff ||
+ fs->fs_old_size != fs->fs_size ||
+ fs->fs_old_rotdelay != 0 ||
+ fs->fs_old_rps != 60 ||
+ fs->fs_old_nspf != fs->fs_fsize / sectorsize ||
+ fs->fs_old_cpg != 1 ||
+ fs->fs_old_interleave != 1 ||
+ fs->fs_old_trackskew != 0 ||
+ fs->fs_old_cpc != 0 ||
+ fs->fs_old_postblformat != 1 ||
+ fs->fs_old_nrpos != 1 ||
+ fs->fs_old_spc != fs->fs_fpg * fs->fs_old_nspf ||
+ fs->fs_old_nsect != fs->fs_old_spc ||
+ fs->fs_old_npsect != fs->fs_old_spc ||
+ fs->fs_old_dsize != fs->fs_dsize ||
+ fs->fs_old_ncyl != fs->fs_ncg)
+ return (ENOENT);
+ } else {
+ return (ENOENT);
+ }
+ if (fs->fs_bsize < MINBSIZE || fs->fs_bsize > MAXBSIZE ||
+ fs->fs_bsize < roundup(sizeof(struct fs), DEV_BSIZE) ||
+ fs->fs_sbsize > SBLOCKSIZE || fs->fs_sbsize < fs->fs_fsize ||
+ !powerof2(fs->fs_bsize))
+ return (ENOENT);
+ if (fs->fs_fsize < sectorsize || fs->fs_fsize > fs->fs_bsize ||
+ fs->fs_fsize * MAXFRAG < fs->fs_bsize || !powerof2(fs->fs_fsize))
+ return (ENOENT);
+ if (fs->fs_maxbsize < fs->fs_bsize || !powerof2(fs->fs_maxbsize) ||
+ fs->fs_maxbsize > FS_MAXCONTIG * fs->fs_bsize)
+ return (ENOENT);
+ if (fs->fs_bmask != ~(fs->fs_bsize - 1) ||
+ fs->fs_fmask != ~(fs->fs_fsize - 1) ||
+ fs->fs_qbmask != ~fs->fs_bmask ||
+ fs->fs_qfmask != ~fs->fs_fmask ||
+ fs->fs_bshift != ILOG2(fs->fs_bsize) ||
+ fs->fs_fshift != ILOG2(fs->fs_fsize) ||
+ fs->fs_frag != numfrags(fs, fs->fs_bsize) ||
+ fs->fs_fragshift != ILOG2(fs->fs_frag) ||
+ fs->fs_frag > MAXFRAG ||
+ fs->fs_fsbtodb != ILOG2(fs->fs_fsize / sectorsize))
+ return (ENOENT);
+ if (fs->fs_sblkno !=
+ roundup(howmany(fs->fs_sblockloc + SBLOCKSIZE, fs->fs_fsize),
+ fs->fs_frag) ||
+ fs->fs_cblkno != fs->fs_sblkno +
+ roundup(howmany(SBLOCKSIZE, fs->fs_fsize), fs->fs_frag) ||
+ fs->fs_iblkno != fs->fs_cblkno + fs->fs_frag ||
+ fs->fs_dblkno != fs->fs_iblkno + fs->fs_ipg / INOPF(fs) ||
+ fs->fs_cgsize != fragroundup(fs, CGSIZE(fs)))
+ return (ENOENT);
+ if (fs->fs_csaddr != cgdmin(fs, 0) ||
+ fs->fs_cssize !=
+ fragroundup(fs, fs->fs_ncg * sizeof(struct csum)) ||
+ fs->fs_dsize != fs->fs_size - fs->fs_sblkno -
+ fs->fs_ncg * (fs->fs_dblkno - fs->fs_sblkno) -
+ howmany(fs->fs_cssize, fs->fs_fsize) ||
+ fs->fs_metaspace < 0 || fs->fs_metaspace > fs->fs_fpg / 2 ||
+ fs->fs_minfree > 99)
+ return (ENOENT);
+ maxfilesize = fs->fs_bsize * UFS_NDADDR - 1;
+ for (sizepb = fs->fs_bsize, i = 0; i < UFS_NIADDR; i++) {
+ sizepb *= NINDIR(fs);
+ maxfilesize += sizepb;
+ }
+ if (fs->fs_maxfilesize != maxfilesize)
+ return (ENOENT);
+ /*
+ * These values have a tight interaction with each other that
+ * makes it hard to tightly bound them. So we can only check
+ * that they are within a broader possible range.
+ *
+ * Calculate minfpg, the minimum number of fragments that can be
+ * in a cylinder group. The value 12289 is calculated in newfs(8)
+ * when creating the smallest block size UFS version 1 filesystem
+ * (4096 block size) with no fragments (4096 fragment size). That
+ * number may be depressed even further for very small filesystems
+ * since newfs(8) strives to have at least four cylinder groups.
+ */
+ minfpg = MIN(12289, fs->fs_size / 4);
+ if (fs->fs_ncg < 1 || fs->fs_ncg > (fs->fs_size / minfpg) + 1 ||
+ fs->fs_fpg < minfpg || fs->fs_fpg > fs->fs_size ||
+ fs->fs_ipg * fs->fs_ncg > (((int64_t)(1)) << 32) - INOPB(fs) ||
+ fs->fs_ipg > fs->fs_fpg || fs->fs_size < 8 * fs->fs_frag)
+ return (ENOENT);
+ if (fs->fs_size <= (fs->fs_ncg - 1) * fs->fs_fpg ||
+ fs->fs_size > fs->fs_ncg * fs->fs_fpg)
+ return (ENOENT);
+ /*
+ * Maxcontig sets the default for the maximum number of blocks
+ * that may be allocated sequentially. With file system clustering
+ * it is possible to allocate contiguous blocks up to the maximum
+ * transfer size permitted by the controller or buffering.
+ */
+ if (fs->fs_maxcontig < 1 ||
+ fs->fs_maxcontig > MAX(1, maxphys / fs->fs_bsize))
+ return (ENOENT);
+ if (fs->fs_maxcontig < 0 ||
+ (fs->fs_maxcontig == 0 && fs->fs_contigsumsize != 0) ||
+ (fs->fs_maxcontig > 1 &&
+ fs->fs_contigsumsize != MIN(fs->fs_maxcontig, FS_MAXCONTIG)))
+ return (ENOENT);
+ return (0);
+}
+
/*
* Write a superblock to the devfd device from the memory pointed to by fs.
* Write out the superblock summary information if it is present.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 10, 6:48 AM (12 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15740329
Default Alt Text
D35219.diff (8 KB)
Attached To
Mode
D35219: Comprehensive UFS/FFS superblock integrity checks made when a superblock is read
Attached
Detach File
Event Timeline
Log In to Comment