diff options
author | Bruce Evans <bde@FreeBSD.org> | 2000-11-04 08:10:56 +0000 |
---|---|---|
committer | Bruce Evans <bde@FreeBSD.org> | 2000-11-04 08:10:56 +0000 |
commit | 1c1752872f0b5a55c89a940ccd2c9e0fe7f5cd3a (patch) | |
tree | c87a5d0458befae0650a31b2d233097db8ed3b53 /sys/ufs | |
parent | af6f98bd1073818205d46a3d7587d91a64035a0c (diff) | |
download | src-1c1752872f0b5a55c89a940ccd2c9e0fe7f5cd3a.tar.gz src-1c1752872f0b5a55c89a940ccd2c9e0fe7f5cd3a.zip |
Fixed breakage of mknod() in rev.1.48 of ext2_vnops.c and rev.1.126 of
ufs_vnops.c:
1) i_ino was confused with i_number, so the inode number passed to
VFS_VGET() was usually wrong (usually 0U).
2) ip was dereferenced after vgone() freed it, so the inode number
passed to VFS_VGET() was sometimes not even wrong.
Bug (1) was usually fatal in ext2_mknod(), since ext2fs doesn't have
space for inode 0 on the disk; ino_to_fsba() subtracts 1 from the
inode number, so inode number 0U gives a way out of bounds array
index. Bug(1) was usually harmless in ufs_mknod(); ino_to_fsba()
doesn't subtract 1, and VFS_VGET() reads suitable garbage (all 0's?)
from the disk for the invalid inode number 0U; ufs_mknod() returns
a wrong vnode, but most callers just vput() it; the correct vnode is
eventually obtained by an implicit VFS_VGET() just like it used to be.
Bug (2) usually doesn't happen.
Notes
Notes:
svn path=/head/; revision=68307
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ufs/ufs_vnops.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 127bda26042f..07d0dac0fbb4 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -208,6 +208,7 @@ ufs_mknod(ap) struct vattr *vap = ap->a_vap; struct vnode **vpp = ap->a_vpp; struct inode *ip; + ino_t ino; int error; error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), @@ -231,8 +232,9 @@ ufs_mknod(ap) */ vput(*vpp); (*vpp)->v_type = VNON; + ino = ip->i_number; /* Save this before vgone() invalidates ip. */ vgone(*vpp); - error = VFS_VGET(ap->a_dvp->v_mount, ip->i_ino, vpp); + error = VFS_VGET(ap->a_dvp->v_mount, ino, vpp); if (error) { *vpp = NULL; return (error); |