From owner-svn-src-head@FreeBSD.ORG Sun Feb 10 10:17:34 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 850A4A6C; Sun, 10 Feb 2013 10:17:34 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 6051A293; Sun, 10 Feb 2013 10:17:34 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r1AAHY8Z016390; Sun, 10 Feb 2013 10:17:34 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r1AAHY7F016389; Sun, 10 Feb 2013 10:17:34 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201302101017.r1AAHY7F016389@svn.freebsd.org> From: Konstantin Belousov Date: Sun, 10 Feb 2013 10:17:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r246612 - head/sys/ufs/ffs X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 10 Feb 2013 10:17:34 -0000 Author: kib Date: Sun Feb 10 10:17:33 2013 New Revision: 246612 URL: http://svnweb.freebsd.org/changeset/base/246612 Log: Fix several unsafe pointer dereferences in the buffered_write() function, implementing the sysctl vfs.ffs.set_bufoutput (not used in the tree yet). - The current directory vnode dereference is unsafe since fd_cdir could be changed and unreferenced, lock the filedesc around and vref the fd_cdir. - The VTOI() conversion of the fd_cdir is unsafe without first checking that the vnode is indeed from an FFS mount, otherwise the code dereferences a random memory. - The cdir could be reclaimed from under us, lock it around the checks. - The type of the fp vnode might be not a disk, or it might have changed while the thread was in flight, check the type. Reviewed and tested by: mckusick MFC after: 2 weeks Modified: head/sys/ufs/ffs/ffs_alloc.c Modified: head/sys/ufs/ffs/ffs_alloc.c ============================================================================== --- head/sys/ufs/ffs/ffs_alloc.c Sun Feb 10 10:00:35 2013 (r246611) +++ head/sys/ufs/ffs/ffs_alloc.c Sun Feb 10 10:17:33 2013 (r246612) @@ -2906,10 +2906,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; daddr_t lbn; @@ -2920,10 +2921,29 @@ 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); + 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); + return (EINVAL); + } + ip = VTOI(vp); + if (ip->i_devvp != devvp) { + vput(vp); + return (EINVAL); + } fs = ip->i_fs; + vput(vp); foffset_lock_uio(fp, uio, flags); vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); #ifdef DEBUG