From f41447a0f47a4126c8f0c4e28d21e18bf819174c Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 20 Apr 2018 16:52:25 +0200 Subject: [PATCH] Resolves: #1558249 - fix crash caused by mistakenly enabled leaf optimization --- findutils-4.6.0-fts-update.patch | 241 ++++++++++++++++++++++++++++++- findutils.spec | 5 +- 2 files changed, 239 insertions(+), 7 deletions(-) diff --git a/findutils-4.6.0-fts-update.patch b/findutils-4.6.0-fts-update.patch index ad6289b..6025514 100644 --- a/findutils-4.6.0-fts-update.patch +++ b/findutils-4.6.0-fts-update.patch @@ -1,7 +1,7 @@ From f3337786e55909538aacfd7c29b1cf58ff444fbf Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 12 Feb 2018 12:45:36 +0100 -Subject: [PATCH 1/2] import gnulib's FTS module from upstream commit 281b825e +Subject: [PATCH 1/4] import gnulib's FTS module from upstream commit 281b825e --- gl/lib/fts.c | 424 +++++++++++++++++++++++++++++----------------------------- @@ -474,10 +474,11 @@ index c91d7a1..bfa73e3 100644 size_t len, maxlen, new_len; char *cp; int dir_fd; -@@ -1370,24 +1394,6 @@ fts_build (register FTS *sp, int type) +@@ -1369,24 +1393,6 @@ fts_build (register FTS *sp, int type) + sorting, yet not so large that we risk exhausting memory. */ max_entries = sp->fts_compar ? SIZE_MAX : FTS_MAX_READDIR_ENTRIES; - /* +- /* - * Nlinks is the number of possible entries of type directory in the - * directory if we're cheating on stat calls, 0 if we're not doing - * any stat calls at all, (nlink_t) -1 if we're statting everything. @@ -495,10 +496,9 @@ index c91d7a1..bfa73e3 100644 - nostat = false; - } - -- /* + /* * If we're going to need to stat anything or we want to descend * and stay in the directory, chdir. If this fails we keep going, - * but set a flag so we don't chdir after the post-order visit. @@ -1408,15 +1414,22 @@ fts_build (register FTS *sp, int type) the required dirp and dir_fd. */ descend = true; @@ -718,7 +718,7 @@ index b9a3f12..70cc9e3 100644 From ea88dd373c60feab541fe037369805f326dc3494 Mon Sep 17 00:00:00 2001 From: rpm-build Date: Mon, 12 Feb 2018 18:58:30 +0100 -Subject: [PATCH 2/2] fts: remove dependency on gnulib's fleximember.h +Subject: [PATCH 2/4] fts: remove dependency on gnulib's fleximember.h ... by reverting upstream commit edb9d82948cb23f67a19e1b435047a0570225df3 --- @@ -759,3 +759,232 @@ index bfa73e3..c37ebe2 100644 -- 2.13.6 + +From 9c1720c99bbf8998dfdaa5976bca8bdc6d93f8e7 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Thu, 5 Apr 2018 08:48:01 -0700 +Subject: [PATCH 3/4] fts: treat CIFS like NFS + +Problem reported by Kamil Dudka in: +https://lists.gnu.org/r/bug-gnulib/2018-04/msg00015.html +* lib/fts.c (S_MAGIC_CIFS): New macro. +(dirent_inode_sort_may_be_useful, leaf_optimization): +Treat CIFS like NFS. + +Upstream-commit: 2e53df541a30d438859087ed4b5a396e04697b9b +Signed-off-by: Kamil Dudka +--- + gl/lib/fts.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/gl/lib/fts.c b/gl/lib/fts.c +index c37ebe2..508ceac 100644 +--- a/gl/lib/fts.c ++++ b/gl/lib/fts.c +@@ -684,6 +684,7 @@ enum leaf_optimization + + /* Linux-specific constants from coreutils' src/fs.h */ + # define S_MAGIC_AFS 0x5346414F ++# define S_MAGIC_CIFS 0xFF534D42 + # define S_MAGIC_NFS 0x6969 + # define S_MAGIC_PROC 0x9FA0 + # define S_MAGIC_REISERFS 0x52654973 +@@ -791,8 +792,9 @@ dirent_inode_sort_may_be_useful (FTSENT const *p) + + switch (filesystem_type (p)) + { +- case S_MAGIC_TMPFS: ++ case S_MAGIC_CIFS: + case S_MAGIC_NFS: ++ case S_MAGIC_TMPFS: + /* On a file system of any of these types, sorting + is unnecessary, and hence wasteful. */ + return false; +@@ -826,6 +828,10 @@ leaf_optimization (FTSENT const *p) + /* Although AFS mount points are not counted in st_nlink, they + act like directories. See . */ + FALLTHROUGH; ++ case S_MAGIC_CIFS: ++ /* Leaf optimization causes 'find' to abort. See ++ . */ ++ FALLTHROUGH; + case S_MAGIC_NFS: + /* NFS provides usable dirent.d_type but not necessarily for all entries + of large directories, so as per +-- +2.14.3 + + +From ff64329a046e76ba553c15373ed61bbed814d286 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Wed, 11 Apr 2018 12:50:35 -0700 +Subject: [PATCH 4/4] fts: fix bug in find across filesystems + +This fixes a bug I introduced last summer. +Problem reported by Kamil Dudka in: +https://lists.gnu.org/r/bug-gnulib/2018-04/msg00033.html +* lib/fts.c (filesystem_type, dirent_inode_sort_may_be_useful) +(leaf_optimization): +New arg for file descriptor. All callers changed. +(fts_build): Check for whether inodes should be sorted +before closing the directory. + +Upstream-commit: 81b8c0d3be98f5a77403599de3d06329b3e7673e +Signed-off-by: Kamil Dudka +--- + gl/lib/fts.c | 55 +++++++++++++++++++++++++++++++------------------------ + 1 file changed, 31 insertions(+), 24 deletions(-) + +diff --git a/gl/lib/fts.c b/gl/lib/fts.c +index 508ceac..175f12a 100644 +--- a/gl/lib/fts.c ++++ b/gl/lib/fts.c +@@ -725,11 +725,12 @@ dev_type_compare (void const *x, void const *y) + return ax->st_dev == ay->st_dev; + } + +-/* Return the file system type of P, or 0 if not known. ++/* Return the file system type of P with file descriptor FD, or 0 if not known. ++ If FD is negative, P's file descriptor is unavailable. + Try to cache known values. */ + + static fsword +-filesystem_type (FTSENT const *p) ++filesystem_type (FTSENT const *p, int fd) + { + FTS *sp = p->fts_fts; + Hash_table *h = sp->fts_leaf_optimization_works_ht; +@@ -755,7 +756,7 @@ filesystem_type (FTSENT const *p) + } + + /* Look-up failed. Query directly and cache the result. */ +- if (fstatfs (p->fts_fts->fts_cwd_fd, &fs_buf) != 0) ++ if (fd < 0 || fstatfs (fd, &fs_buf) != 0) + return 0; + + if (h) +@@ -777,12 +778,12 @@ filesystem_type (FTSENT const *p) + return fs_buf.f_type; + } + +-/* Return false if it is easy to determine the file system type of the +- directory P, and sorting dirents on inode numbers is known not to +- improve traversal performance with that type of file system. +- Otherwise, return true. */ ++/* Return true if sorting dirents on inode numbers is known to improve ++ traversal performance for the directory P with descriptor DIR_FD. ++ Return false otherwise. When in doubt, return true. ++ DIR_FD is negative if unavailable. */ + static bool +-dirent_inode_sort_may_be_useful (FTSENT const *p) ++dirent_inode_sort_may_be_useful (FTSENT const *p, int dir_fd) + { + /* Skip the sort only if we can determine efficiently + that skipping it is the right thing to do. +@@ -790,7 +791,7 @@ dirent_inode_sort_may_be_useful (FTSENT const *p) + while the cost of *not* performing it can be O(N^2) with + a very large constant. */ + +- switch (filesystem_type (p)) ++ switch (filesystem_type (p, dir_fd)) + { + case S_MAGIC_CIFS: + case S_MAGIC_NFS: +@@ -804,16 +805,17 @@ dirent_inode_sort_may_be_useful (FTSENT const *p) + } + } + +-/* Given an FTS entry P for a directory D, ++/* Given an FTS entry P for a directory with descriptor DIR_FD, + return true if it is both useful and valid to apply leaf optimization. + The optimization is useful only for file systems that lack usable + dirent.d_type info. The optimization is valid if an st_nlink value + of at least MIN_DIR_NLINK is an upper bound on the number of +- subdirectories of D, counting "." and ".." as subdirectories. */ ++ subdirectories of D, counting "." and ".." as subdirectories. ++ DIR_FD is negative if unavailable. */ + static enum leaf_optimization +-leaf_optimization (FTSENT const *p) ++leaf_optimization (FTSENT const *p, int dir_fd) + { +- switch (filesystem_type (p)) ++ switch (filesystem_type (p, dir_fd)) + { + /* List here the file system types that may lack usable dirent.d_type + info, yet for which the optimization does apply. */ +@@ -850,12 +852,13 @@ leaf_optimization (FTSENT const *p) + + #else + static bool +-dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED) ++dirent_inode_sort_may_be_useful (FTSENT const *p _GL_UNUSED, ++ int dir_fd _GL_UNUSED) + { + return true; + } + static enum leaf_optimization +-leaf_optimization (FTSENT const *p _GL_UNUSED) ++leaf_optimization (FTSENT const *p _GL_UNUSED, int dir_fd _GL_UNUSED) + { + return NO_LEAF_OPTIMIZATION; + } +@@ -1049,7 +1052,7 @@ check_for_dir: + if (parent->fts_n_dirs_remaining == 0 + && ISSET(FTS_NOSTAT) + && ISSET(FTS_PHYSICAL) +- && (leaf_optimization (parent) ++ && (leaf_optimization (parent, sp->fts_cwd_fd) + == NOSTAT_LEAF_OPTIMIZATION)) + { + /* nothing more needed */ +@@ -1334,6 +1337,7 @@ fts_build (register FTS *sp, int type) + int dir_fd; + FTSENT *cur = sp->fts_cur; + bool continue_readdir = !!cur->fts_dirp; ++ bool sort_by_inode = false; + size_t max_entries; + + /* When cur->fts_dirp is non-NULL, that means we should +@@ -1427,7 +1431,7 @@ fts_build (register FTS *sp, int type) + && ! (ISSET (FTS_NOSTAT) && ISSET (FTS_PHYSICAL) + && ! ISSET (FTS_SEEDOT) + && cur->fts_statp->st_nlink == MIN_DIR_NLINK +- && (leaf_optimization (cur) ++ && (leaf_optimization (cur, dir_fd) + != NO_LEAF_OPTIMIZATION))); + if (descend || type == BREAD) + { +@@ -1588,6 +1592,15 @@ mem1: saved_errno = errno; + tail->fts_link = p; + tail = p; + } ++ ++ /* If there are many entries, no sorting function has been ++ specified, and this file system is of a type that may be ++ slow with a large number of entries, arrange to sort the ++ directory entries on increasing inode numbers. */ ++ if (nitems == _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD ++ && !sp->fts_compar) ++ sort_by_inode = dirent_inode_sort_may_be_useful (cur, dir_fd); ++ + ++nitems; + if (max_entries <= nitems) { + /* When there are too many dir entries, leave +@@ -1645,13 +1658,7 @@ mem1: saved_errno = errno; + return (NULL); + } + +- /* If there are many entries, no sorting function has been specified, +- and this file system is of a type that may be slow with a large +- number of entries, then sort the directory entries on increasing +- inode numbers. */ +- if (nitems > _FTS_INODE_SORT_DIR_ENTRIES_THRESHOLD +- && !sp->fts_compar +- && dirent_inode_sort_may_be_useful (cur)) { ++ if (sort_by_inode) { + sp->fts_compar = fts_compare_ino; + head = fts_sort (sp, head, nitems); + sp->fts_compar = NULL; +-- +2.14.3 + diff --git a/findutils.spec b/findutils.spec index a2ec894..c0b52fe 100644 --- a/findutils.spec +++ b/findutils.spec @@ -1,7 +1,7 @@ Summary: The GNU versions of find utilities (find and xargs) Name: findutils Version: 4.6.0 -Release: 18%{?dist} +Release: 19%{?dist} Epoch: 1 License: GPLv3+ Group: Applications/File @@ -147,6 +147,9 @@ fi %{_infodir}/find-maint.info.gz %changelog +* Fri Apr 20 2018 Kamil Dudka - 1:4.6.0-19 +- fix crash caused by mistakenly enabled leaf optimization (#1558249) + * Tue Mar 06 2018 Kamil Dudka - 1:4.6.0-18 - fix build failure with glibc-2.28