summaryrefslogtreecommitdiff
path: root/sys/ufs/ffs/ffs_vfsops.c
diff options
context:
space:
mode:
authorGrigoriy Orlov <gluk@cvs.openbsd.org>2001-04-13 02:39:07 +0000
committerGrigoriy Orlov <gluk@cvs.openbsd.org>2001-04-13 02:39:07 +0000
commit9bff9fb87213262bc5d1afd9333ad540d9e99c54 (patch)
tree5797ca5b1e346d54d4606ff7293258862d4b223b /sys/ufs/ffs/ffs_vfsops.c
parent5af2b89b71f9bb495e071539ea9548813c712c7c (diff)
Fix overflow in superblock. From FreeBSD.
FreeBSD's log: > The ffs superblock includes a 128-byte region for use by temporary > in-core pointers to summary information. An array in this region > (fs_csp) could overflow on filesystems with a very large number of > cylinder groups (~16000 on i386 with 8k blocks). When this happens, > other fields in the superblock get corrupted, and fsck refuses to > check the filesystem. > > Solve this problem by replacing the fs_csp array in 'struct fs' > with a single pointer, and add padding to keep the length of the > 128-byte region fixed. Update the kernel and userland utilities > to use just this single pointer. > > With this change, the kernel no longer makes use of the superblock > fields 'fs_csshift' and 'fs_csmask'. Add a comment to newfs/mkfs.c > to indicate that these fields must be calculated for compatibility > with older kernels. art@ ok.
Diffstat (limited to 'sys/ufs/ffs/ffs_vfsops.c')
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 10d31c10e67..3ffd6abf98e 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ffs_vfsops.c,v 1.37 2001/04/12 17:16:52 csapuntz Exp $ */
+/* $OpenBSD: ffs_vfsops.c,v 1.38 2001/04/13 02:39:05 gluk Exp $ */
/* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
/*
@@ -446,7 +446,7 @@ ffs_reload(mountp, cred, p)
{
register struct vnode *vp, *nvp, *devvp;
struct inode *ip;
- struct csum *space;
+ caddr_t space;
struct buf *bp;
struct fs *fs, *newfs;
struct partinfo dpart;
@@ -487,7 +487,7 @@ ffs_reload(mountp, cred, p)
* new superblock. These should really be in the ufsmount. XXX
* Note that important parameters (eg fs_ncg) are unchanged.
*/
- bcopy(&fs->fs_csp[0], &newfs->fs_csp[0], sizeof(fs->fs_csp));
+ newfs->fs_csp = fs->fs_csp;
newfs->fs_maxcluster = fs->fs_maxcluster;
bcopy(newfs, fs, (u_int)fs->fs_sbsize);
if (fs->fs_sbsize < SBSIZE)
@@ -500,7 +500,7 @@ ffs_reload(mountp, cred, p)
* Step 3: re-read summary information from disk.
*/
blks = howmany(fs->fs_cssize, fs->fs_fsize);
- space = fs->fs_csp[0];
+ space = (caddr_t)fs->fs_csp;
for (i = 0; i < blks; i += fs->fs_frag) {
size = fs->fs_bsize;
if (i + fs->fs_frag > blks)
@@ -509,7 +509,8 @@ ffs_reload(mountp, cred, p)
NOCRED, &bp);
if (error)
return (error);
- bcopy(bp->b_data, fs->fs_csp[fragstoblks(fs, i)], (u_int)size);
+ bcopy(bp->b_data, space, (u_int)size);
+ space += size;
brelse(bp);
}
if ((fs->fs_flags & FS_DOSOFTDEP))
@@ -582,7 +583,7 @@ ffs_mountfs(devvp, mp, p)
register struct fs *fs;
dev_t dev;
struct partinfo dpart;
- caddr_t base, space;
+ caddr_t space;
int error, i, blks, size, ronly;
int32_t *lp;
size_t strsize;
@@ -677,7 +678,8 @@ ffs_mountfs(devvp, mp, p)
blks = howmany(size, fs->fs_fsize);
if (fs->fs_contigsumsize > 0)
size += fs->fs_ncg * sizeof(int32_t);
- base = space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
+ space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
+ fs->fs_csp = (struct csum *)space;
for (i = 0; i < blks; i += fs->fs_frag) {
size = fs->fs_bsize;
if (i + fs->fs_frag > blks)
@@ -685,11 +687,10 @@ ffs_mountfs(devvp, mp, p)
error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
cred, &bp);
if (error) {
- free(base, M_UFSMNT);
+ free(fs->fs_csp, M_UFSMNT);
goto out;
}
bcopy(bp->b_data, space, (u_int)size);
- fs->fs_csp[fragstoblks(fs, i)] = (struct csum *)space;
space += size;
brelse(bp);
bp = NULL;
@@ -754,7 +755,7 @@ ffs_mountfs(devvp, mp, p)
if (ronly == 0) {
if ((fs->fs_flags & FS_DOSOFTDEP) &&
(error = softdep_mount(devvp, mp, fs, cred)) != 0) {
- free(base, M_UFSMNT);
+ free(fs->fs_csp, M_UFSMNT);
free(fs->fs_contigdirs, M_UFSMNT);
goto out;
}
@@ -850,7 +851,7 @@ ffs_unmount(mp, mntflags, p)
error = VOP_CLOSE(ump->um_devvp, fs->fs_ronly ? FREAD : FREAD|FWRITE,
NOCRED, p);
vrele(ump->um_devvp);
- free(fs->fs_csp[0], M_UFSMNT);
+ free(fs->fs_csp, M_UFSMNT);
free(fs, M_UFSMNT);
free(ump, M_UFSMNT);
mp->mnt_data = (qaddr_t)0;
@@ -1235,7 +1236,7 @@ ffs_sbupdate(mp, waitfor)
* First write back the summary information.
*/
blks = howmany(fs->fs_cssize, fs->fs_fsize);
- space = (caddr_t)fs->fs_csp[0];
+ space = (caddr_t)fs->fs_csp;
for (i = 0; i < blks; i += fs->fs_frag) {
size = fs->fs_bsize;
if (i + fs->fs_frag > blks)