svn commit: r285319 - head/sys/kern

Mateusz Guzik mjg at FreeBSD.org
Thu Jul 9 15:06:25 UTC 2015


Author: mjg
Date: Thu Jul  9 15:06:24 2015
New Revision: 285319
URL: https://svnweb.freebsd.org/changeset/base/285319

Log:
  vfs: plug a use-after-free of fd_rdir in namei
  
  fd_rdir vnode was stored in ni_rootdir without refing it in any way,
  after which the filedsc lock was being dropped.
  
  The vnode could have been freed by mountcheckdirs or another thread doing
  chroot.
  
  VREF the vnode while the lock is held.
  
  Reviewed by:	kib
  MFC after:	1 week

Modified:
  head/sys/kern/vfs_lookup.c

Modified: head/sys/kern/vfs_lookup.c
==============================================================================
--- head/sys/kern/vfs_lookup.c	Thu Jul  9 14:14:44 2015	(r285318)
+++ head/sys/kern/vfs_lookup.c	Thu Jul  9 15:06:24 2015	(r285319)
@@ -210,6 +210,7 @@ namei(struct nameidata *ndp)
 	 */
 	FILEDESC_SLOCK(fdp);
 	ndp->ni_rootdir = fdp->fd_rdir;
+	VREF(ndp->ni_rootdir);
 	ndp->ni_topdir = fdp->fd_jdir;
 
 	/*
@@ -260,6 +261,7 @@ namei(struct nameidata *ndp)
 			}
 		}
 		if (error) {
+			vrele(ndp->ni_rootdir);
 			namei_cleanup_cnp(cnp);
 			return (error);
 		}
@@ -286,6 +288,7 @@ namei(struct nameidata *ndp)
 				if (KTRPOINT(curthread, KTR_CAPFAIL))
 					ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
 #endif
+				vrele(ndp->ni_rootdir);
 				namei_cleanup_cnp(cnp);
 				return (ENOTCAPABLE);
 			}
@@ -299,6 +302,7 @@ namei(struct nameidata *ndp)
 		ndp->ni_startdir = dp;
 		error = lookup(ndp);
 		if (error) {
+			vrele(ndp->ni_rootdir);
 			namei_cleanup_cnp(cnp);
 			SDT_PROBE(vfs, namei, lookup, return, error, NULL, 0,
 			    0, 0);
@@ -308,6 +312,7 @@ namei(struct nameidata *ndp)
 		 * If not a symbolic link, we're done.
 		 */
 		if ((cnp->cn_flags & ISSYMLINK) == 0) {
+			vrele(ndp->ni_rootdir);
 			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) {
 				namei_cleanup_cnp(cnp);
 			} else
@@ -371,6 +376,7 @@ namei(struct nameidata *ndp)
 		vput(ndp->ni_vp);
 		dp = ndp->ni_dvp;
 	}
+	vrele(ndp->ni_rootdir);
 	namei_cleanup_cnp(cnp);
 	vput(ndp->ni_vp);
 	ndp->ni_vp = NULL;


More information about the svn-src-all mailing list