changeset 17914:644307da6af9

fts: avoid crash when a cycle is added while traversing This could be triggered by auto-mounting a recursive bind mount. Reported by Michael Chapman in: https://bugzilla.redhat.com/1188498 * lib/fts.c (fts_read): Avoid removing the original hash table item when leaving a directory that caused a cycle, and preserve the FTS_DC flag.
author Kamil Dudka <kdudka@redhat.com>
date Wed, 11 Feb 2015 18:41:43 +0100
parents b527a7928c9f
children ee9d88df0605
files ChangeLog lib/fts.c
diffstat 2 files changed, 18 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2015-02-16  Kamil Dudka  <kdudka@redhat.com>
+
+	fts: avoid crash when a cycle is added while traversing
+	This could be triggered by auto-mounting a recursive bind mount.
+	Reported by Michael Chapman in: https://bugzilla.redhat.com/1188498
+	* lib/fts.c (fts_read): Avoid removing the original hash table item
+	when leaving a directory that caused a cycle, and preserve the FTS_DC
+	flag.
+
 2015-02-16  Daiki Ueno  <ueno@gnu.org>
 
 	uniname/uniname: support character alias
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -1091,9 +1091,15 @@
                 p->fts_errno = errno;
                 SET(FTS_STOP);
         }
-        p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
-        if (p->fts_errno == 0)
-                LEAVE_DIR (sp, p, "3");
+
+        /* If the directory causes a cycle, preserve the FTS_DC flag and keep
+           the corresponding dev/ino pair in the hash table.  It is going to be
+           removed when leaving the original directory.  */
+        if (p->fts_info != FTS_DC) {
+                p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+                if (p->fts_errno == 0)
+                        LEAVE_DIR (sp, p, "3");
+        }
         return ISSET(FTS_STOP) ? NULL : p;
 }