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>