Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Mar 2014 16:43:09 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r262892 - stable/10/lib/libc/gen
Message-ID:  <201403071643.s27Gh9Px037411@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Fri Mar  7 16:43:08 2014
New Revision: 262892
URL: http://svnweb.freebsd.org/changeset/base/262892

Log:
  MFC r261859: fts: Fix double-free with conflicting concurrent modifications.
  
  If rare conditions such as concurrent conflicting manipulation of the
  filesystem occur, fts_read() frees the current FTSENT without adjusting
  the pointers in the FTS accordingly. A later fts_close() then frees the
  same FTSENT again.

Modified:
  stable/10/lib/libc/gen/fts.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/lib/libc/gen/fts.c
==============================================================================
--- stable/10/lib/libc/gen/fts.c	Fri Mar  7 16:14:51 2014	(r262891)
+++ stable/10/lib/libc/gen/fts.c	Fri Mar  7 16:43:08 2014	(r262892)
@@ -406,8 +406,6 @@ fts_read(FTS *sp)
 	/* Move to the next node on this level. */
 next:	tmp = p;
 	if ((p = p->fts_link) != NULL) {
-		free(tmp);
-
 		/*
 		 * If reached the top, return to the original directory (or
 		 * the root of the tree), and load the paths for the next root.
@@ -417,6 +415,7 @@ next:	tmp = p;
 				SET(FTS_STOP);
 				return (NULL);
 			}
+			free(tmp);
 			fts_load(sp, p);
 			return (sp->fts_cur = p);
 		}
@@ -426,8 +425,10 @@ next:	tmp = p;
 		 * ignore.  If followed, get a file descriptor so we can
 		 * get back if necessary.
 		 */
-		if (p->fts_instr == FTS_SKIP)
+		if (p->fts_instr == FTS_SKIP) {
+			free(tmp);
 			goto next;
+		}
 		if (p->fts_instr == FTS_FOLLOW) {
 			p->fts_info = fts_stat(sp, p, 1);
 			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
@@ -441,6 +442,8 @@ next:	tmp = p;
 			p->fts_instr = FTS_NOINSTR;
 		}
 
+		free(tmp);
+
 name:		t = sp->fts_path + NAPPEND(p->fts_parent);
 		*t++ = '/';
 		memmove(t, p->fts_name, p->fts_namelen + 1);
@@ -449,13 +452,13 @@ name:		t = sp->fts_path + NAPPEND(p->fts
 
 	/* Move up to the parent node. */
 	p = tmp->fts_parent;
-	free(tmp);
 
 	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
 		/*
 		 * Done; free everything up and set errno to 0 so the user
 		 * can distinguish between error and EOF.
 		 */
+		free(tmp);
 		free(p);
 		errno = 0;
 		return (sp->fts_cur = NULL);
@@ -488,6 +491,7 @@ name:		t = sp->fts_path + NAPPEND(p->fts
 		SET(FTS_STOP);
 		return (NULL);
 	}
+	free(tmp);
 	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
 	return (sp->fts_cur = p);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403071643.s27Gh9Px037411>