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);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to