svn commit: r247211 - stable/9/sys/ufs/ffs

Konstantin Belousov kib at FreeBSD.org
Sun Feb 24 05:49:00 UTC 2013


Author: kib
Date: Sun Feb 24 05:48:59 2013
New Revision: 247211
URL: http://svnweb.freebsd.org/changeset/base/247211

Log:
  MFC r246612:
  Fix several unsafe pointer dereferences in the buffered_write() function.

Modified:
  stable/9/sys/ufs/ffs/ffs_alloc.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- stable/9/sys/ufs/ffs/ffs_alloc.c	Sun Feb 24 03:15:43 2013	(r247210)
+++ stable/9/sys/ufs/ffs/ffs_alloc.c	Sun Feb 24 05:48:59 2013	(r247211)
@@ -2853,10 +2853,11 @@ buffered_write(fp, uio, active_cred, fla
 	int flags;
 	struct thread *td;
 {
-	struct vnode *devvp;
+	struct vnode *devvp, *vp;
 	struct inode *ip;
 	struct buf *bp;
 	struct fs *fs;
+	struct filedesc *fdp;
 	int error, vfslocked;
 	daddr_t lbn;
 
@@ -2867,12 +2868,34 @@ buffered_write(fp, uio, active_cred, fla
 	 * within the filesystem being written. Yes, this is an ugly hack.
 	 */
 	devvp = fp->f_vnode;
-	ip = VTOI(td->td_proc->p_fd->fd_cdir);
-	if (ip->i_devvp != devvp)
+	if (!vn_isdisk(devvp, NULL))
 		return (EINVAL);
+	fdp = td->td_proc->p_fd;
+	FILEDESC_SLOCK(fdp);
+	vp = fdp->fd_cdir;
+	vref(vp);
+	FILEDESC_SUNLOCK(fdp);
+	vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+	vn_lock(vp, LK_SHARED | LK_RETRY);
+	/*
+	 * Check that the current directory vnode indeed belongs to
+	 * UFS before trying to dereference UFS-specific v_data fields.
+	 */
+	if (vp->v_op != &ffs_vnodeops1 && vp->v_op != &ffs_vnodeops2) {
+		vput(vp);
+		VFS_UNLOCK_GIANT(vfslocked);
+		return (EINVAL);
+	}
+	ip = VTOI(vp);
+	if (ip->i_devvp != devvp) {
+		vput(vp);
+		VFS_UNLOCK_GIANT(vfslocked);
+		return (EINVAL);
+	}
 	fs = ip->i_fs;
+	vput(vp);
+	VFS_UNLOCK_GIANT(vfslocked);
 	foffset_lock_uio(fp, uio, flags);
-	vfslocked = VFS_LOCK_GIANT(ip->i_vnode->v_mount);
 	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
 #ifdef DEBUG
 	if (fsckcmds) {
@@ -2900,7 +2923,6 @@ buffered_write(fp, uio, active_cred, fla
 	error = bwrite(bp);
 out:
 	VOP_UNLOCK(devvp, 0);
-	VFS_UNLOCK_GIANT(vfslocked);
 	foffset_unlock_uio(fp, uio, flags | FOF_NEXTOFF);
 	return (error);
 }


More information about the svn-src-all mailing list