summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2016-05-10 10:37:58 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2016-05-10 10:37:58 +0000
commit8a7a6ec44db0e2899202b5035db61e25d40a5be8 (patch)
treed076d247002a438687fd177213fdd4db5e465b52 /sys
parentf79d510cb2f7ecec4ee9d4b4f8d2e0ed79e181d0 (diff)
FFS2 does lazy inode initialization, so try harder to avoid using
random data on the disk as an inode. Thus avoiding crashes when translating a bogus filehandle to a vnode. Yes, I'm looking at you, NFS! Adapted from a diff by Christos Zoulas via NetBSD, pointed out by kurt@. ok beck@
Diffstat (limited to 'sys')
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 4fa6553689c..6c14e51f593 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.155 2016/03/27 11:39:37 bluhm Exp $ */
+/* $OpenBSD: ffs_vfsops.c,v 1.156 2016/05/10 10:37:57 krw Exp $ */
/* $NetBSD: ffs_vfsops.c,v 1.19 1996/02/09 22:22:26 christos Exp $ */
/*
@@ -97,6 +97,47 @@ struct inode_vtbl ffs_vtbl = {
ffs_bufatoff
};
+int
+ffs_checkrange(struct mount *mp, uint32_t ino)
+{
+ struct buf *bp;
+ struct cg *cgp;
+ struct fs *fs;
+ struct ufsmount *ump;
+ int cg, error;
+
+ fs = VFSTOUFS(mp)->um_fs;
+ if (ino < ROOTINO || ino >= fs->fs_ncg * fs->fs_ipg)
+ return ESTALE;
+
+ /*
+ * Need to check if inode is initialized because ffsv2 does
+ * lazy initialization and we can get here from nfs_fhtovp
+ */
+ if (fs->fs_magic != FS_UFS2_MAGIC)
+ return 0;
+
+ cg = ino_to_cg(fs, ino);
+ ump = VFSTOUFS(mp);
+
+ error = bread(ump->um_devvp, fsbtodb(fs, cgtod(fs, cg)),
+ (int)fs->fs_cgsize, &bp);
+ if (error)
+ return error;
+
+ cgp = (struct cg *)bp->b_data;
+ if (!cg_chkmagic(cgp)) {
+ brelse(bp);
+ return ESTALE;
+ }
+
+ brelse(bp);
+
+ if (cg * fs->fs_ipg + cgp->cg_initediblk < ino)
+ return ESTALE;
+
+ return 0;
+}
/*
* Called by main() when ufs is going to be mounted as root.
@@ -1361,23 +1402,21 @@ retry:
/*
* File handle to vnode
*
- * Have to be really careful about stale file handles:
- * - check that the inode number is valid
- * - call ffs_vget() to get the locked inode
- * - check for an unallocated inode (i_mode == 0)
+ * Have to be really careful about stale file handles.
*/
int
ffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
{
struct ufid *ufhp;
- struct fs *fs;
+ int error;
ufhp = (struct ufid *)fhp;
- fs = VFSTOUFS(mp)->um_fs;
- if (ufhp->ufid_len != sizeof(*ufhp) ||
- ufhp->ufid_ino < ROOTINO ||
- ufhp->ufid_ino >= fs->fs_ncg * fs->fs_ipg)
- return (ESTALE);
+ if (ufhp->ufid_len != sizeof(*ufhp))
+ return EINVAL;
+
+ if ((error = ffs_checkrange(mp, ufhp->ufid_ino)) != 0)
+ return error;
+
return (ufs_fhtovp(mp, ufhp, vpp));
}