97 lines
3.9 KiB
Diff
97 lines
3.9 KiB
Diff
From 440b528b1d81dd31b2a2e4dde20d5c837c147811 Mon Sep 17 00:00:00 2001
|
|
From: Paul Eggert <eggert@cs.ucla.edu>
|
|
Date: Tue, 6 Dec 2022 10:27:43 -0800
|
|
Subject: [PATCH] fts: fix race + mishandling of fstatat failure
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
I hope this fixes a Luke Dashjr coreutils bug report about ext4
|
|
ramdisks; see “9.1: du Aborted (corrupt filesystem)”
|
|
<https://debbugs.gnu.org/59821>.
|
|
* lib/fts.c (fts_build): Fix two bugs. First, fts_stat was being
|
|
called without checking its return value, causing a later abort.
|
|
Second, there was a race between opening a directory and statting
|
|
it, fixed by using fstat on the file descriptor rather than
|
|
fstatat on the directory name.
|
|
|
|
Reference:https://github.com/coretuils/gnulib/commit/440b528b1d81dd31b2a2e4dde20d5c837c147811
|
|
Conflict:Context adapation
|
|
|
|
---
|
|
ChangeLog | 10 ++++++++++
|
|
lib/fts.c | 32 ++++++++++++++++++++++++--------
|
|
2 files changed, 34 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/ChangeLog b/ChangeLog
|
|
index 44fe270..1785234 100644
|
|
--- a/ChangeLog
|
|
+++ b/ChangeLog
|
|
@@ -1,3 +1,15 @@
|
|
+2022-12-06 Paul Eggert <eggert@cs.ucla.edu>
|
|
+
|
|
+ fts: fix race + mishandling of fstatat failure
|
|
+ I hope this fixes a Luke Dashjr coreutils bug report about ext4
|
|
+ ramdisks; see “9.1: du Aborted (corrupt filesystem)”
|
|
+ <https://debbugs.gnu.org/59821>.
|
|
+ * lib/fts.c (fts_build): Fix two bugs. First, fts_stat was being
|
|
+ called without checking its return value, causing a later abort.
|
|
+ Second, there was a race between opening a directory and statting
|
|
+ it, fixed by using fstat on the file descriptor rather than
|
|
+ fstatat on the directory name.
|
|
+
|
|
2021-09-24 Pádraig Brady <P@draigBrady.com>
|
|
|
|
version 9.0
|
|
diff --git a/lib/fts.c b/lib/fts.c
|
|
index 27354d39c8..74a08f7ec8 100644
|
|
--- a/lib/fts.c
|
|
+++ b/lib/fts.c
|
|
@@ -1316,19 +1316,35 @@ fts_build (register FTS *sp, int type)
|
|
/* Rather than calling fts_stat for each and every entry encountered
|
|
in the readdir loop (below), stat each directory only right after
|
|
opening it. */
|
|
- if (cur->fts_info == FTS_NSOK)
|
|
- cur->fts_info = fts_stat(sp, cur, false);
|
|
- else if (sp->fts_options & FTS_TIGHT_CYCLE_CHECK)
|
|
- {
|
|
- /* Now read the stat info again after opening a directory to
|
|
+ bool stat_optimization = cur->fts_info == FTS_NSOK;
|
|
+
|
|
+ if (stat_optimization
|
|
+ /* Also read the stat info again after opening a directory to
|
|
reveal eventual changes caused by a submount triggered by
|
|
the traversal. But do it only for utilities which use
|
|
FTS_TIGHT_CYCLE_CHECK. Therefore, only find and du
|
|
benefit/suffer from this feature for now. */
|
|
- LEAVE_DIR (sp, cur, "4");
|
|
- fts_stat (sp, cur, false);
|
|
- if (! enter_dir (sp, cur))
|
|
+ || ISSET (FTS_TIGHT_CYCLE_CHECK))
|
|
+ {
|
|
+ if (!stat_optimization)
|
|
+ LEAVE_DIR (sp, cur, "4");
|
|
+ if (fstat (dir_fd, cur->fts_statp) != 0)
|
|
+ {
|
|
+ int fstat_errno = errno;
|
|
+ closedir_and_clear (cur->fts_dirp);
|
|
+ if (type == BREAD)
|
|
+ {
|
|
+ cur->fts_errno = fstat_errno;
|
|
+ cur->fts_info = FTS_NS;
|
|
+ }
|
|
+ __set_errno (fstat_errno);
|
|
+ return NULL;
|
|
+ }
|
|
+ if (stat_optimization)
|
|
+ cur->fts_info = FTS_D;
|
|
+ else if (! enter_dir (sp, cur))
|
|
{
|
|
+ closedir_and_clear (cur->fts_dirp);
|
|
__set_errno (ENOMEM);
|
|
return NULL;
|
|
}
|
|
--
|
|
2.27.0
|
|
|