diff options
author | dg <dg@FreeBSD.org> | 1996-06-12 03:37:57 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1996-06-12 03:37:57 +0000 |
commit | 5026fc1c3662189cacaad4f0eb1fc0222ec8def1 (patch) | |
tree | 0244ce546b0fc6e415af50b64cc8c473ae6be049 /sys/ufs | |
parent | 6e349b6b4756260c2efd6d1e925c366e50db77d0 (diff) | |
download | FreeBSD-src-5026fc1c3662189cacaad4f0eb1fc0222ec8def1.zip FreeBSD-src-5026fc1c3662189cacaad4f0eb1fc0222ec8def1.tar.gz |
Moved the fsnode MALLOC to before the call to getnewvnode() so that the
process won't possibly block before filling in the fsnode pointer (v_data)
which might be dereferenced during a sync since the vnode is put on the
mnt_vnodelist by getnewvnode.
Pointed out by Matt Day <mday@artisoft.com>
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 15 | ||||
-rw-r--r-- | sys/ufs/lfs/lfs_alloc.c | 11 | ||||
-rw-r--r-- | sys/ufs/mfs/mfs_vfsops.c | 18 |
3 files changed, 34 insertions, 10 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 44ae0d6..200b006 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94 - * $Id: ffs_vfsops.c,v 1.37 1996/03/02 03:45:12 dyson Exp $ + * $Id: ffs_vfsops.c,v 1.38 1996/03/02 22:18:34 dyson Exp $ */ #include "opt_quota.h" @@ -866,6 +866,16 @@ restart: } ffs_inode_hash_lock = 1; + /* + * If this MALLOC() is performed after the getnewvnode() + * it might block, leaving a vnode with a NULL v_data to be + * found by ffs_sync() if a sync happens to fire right then, + * which will cause a panic because ffs_sync() blindly + * dereferences vp->v_data (as well it should). + */ + type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */ + MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK); + /* Allocate a new vnode/inode. */ error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, &vp); if (error) { @@ -873,10 +883,9 @@ restart: wakeup(&ffs_inode_hash_lock); ffs_inode_hash_lock = 0; *vpp = NULL; + FREE(ip, type); return (error); } - type = ump->um_devvp->v_tag == VT_MFS ? M_MFSNODE : M_FFSNODE; /* XXX */ - MALLOC(ip, struct inode *, sizeof(struct inode), type, M_WAITOK); bzero((caddr_t)ip, sizeof(struct inode)); vp->v_data = ip; ip->i_vnode = vp; diff --git a/sys/ufs/lfs/lfs_alloc.c b/sys/ufs/lfs/lfs_alloc.c index 8d4e044..43b99f7 100644 --- a/sys/ufs/lfs/lfs_alloc.c +++ b/sys/ufs/lfs/lfs_alloc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)lfs_alloc.c 8.4 (Berkeley) 1/4/94 - * $Id: lfs_alloc.c,v 1.9 1995/12/07 12:47:55 davidg Exp $ + * $Id: lfs_alloc.c,v 1.10 1996/01/05 18:31:51 wollman Exp $ */ #include "opt_quota.h" @@ -166,9 +166,17 @@ lfs_vcreate(mp, ino, vpp) struct ufsmount *ump; int error, i; + /* + * Do the MALLOC before the getnewvnode since doing so afterward + * might cause a bogus v_data pointer to get dereferenced + * elsewhere if MALLOC should block. + */ + MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK); + /* Create the vnode. */ if (error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, vpp)) { *vpp = NULL; + FREE(ip, M_LFSNODE); return (error); } @@ -176,7 +184,6 @@ lfs_vcreate(mp, ino, vpp) ump = VFSTOUFS(mp); /* Initialize the inode. */ - MALLOC(ip, struct inode *, sizeof(struct inode), M_LFSNODE, M_WAITOK); (*vpp)->v_data = ip; ip->i_vnode = *vpp; ip->i_devvp = ump->um_devvp; diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c index 39a1822..628c6b3 100644 --- a/sys/ufs/mfs/mfs_vfsops.c +++ b/sys/ufs/mfs/mfs_vfsops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)mfs_vfsops.c 8.4 (Berkeley) 4/16/94 - * $Id: mfs_vfsops.c,v 1.20 1995/12/17 21:09:59 phk Exp $ + * $Id: mfs_vfsops.c,v 1.21 1996/04/08 07:54:49 phk Exp $ */ #include <sys/param.h> @@ -288,7 +288,7 @@ mfs_mount(mp, path, data, ndp, p) /* * FS specific handling */ - mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); + MALLOC(mfsp, struct mfsnode *, sizeof *mfsp, M_MFSNODE, M_WAITOK); rootvp->v_data = mfsp; rootvp->v_op = mfs_vnodeop_p; rootvp->v_tag = VT_MFS; @@ -305,7 +305,7 @@ mfs_mount(mp, path, data, ndp, p) if( (err = ffs_mountfs(rootvp, mp, p)) != 0 ) { /* fs specific cleanup (if any)*/ rootvp->v_data = NULL; - free(mfsp, M_MFSNODE); + FREE(mfsp, M_MFSNODE); goto error_1; } @@ -368,13 +368,21 @@ mfs_mount(mp, path, data, ndp, p) /* XXX MFS does not support name updating*/ goto success; } + /* + * Do the MALLOC before the getnewvnode since doing so afterward + * might cause a bogus v_data pointer to get dereferenced + * elsewhere if MALLOC should block. + */ + MALLOC(mfsp, struct mfsnode *, sizeof *mfsp, M_MFSNODE, M_WAITOK); + err = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp); - if (err) + if (err) { + FREE(mfsp, M_MFSNODE); goto error_1; + } devvp->v_type = VBLK; if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0)) panic("mfs_mount: dup dev"); - mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK); devvp->v_data = mfsp; mfsp->mfs_baseoff = args.base; mfsp->mfs_size = args.size; |