59 lines
2.2 KiB
Diff
59 lines
2.2 KiB
Diff
From 235f21673cd8e3458795cdadca6e78a3423ab024 Mon Sep 17 00:00:00 2001
|
|
From: Bernhard Voelker <mail@bernhard-voelker.de>
|
|
Date: Sat, 9 Feb 2019 15:57:19 +0100
|
|
Subject: [PATCH 224/224] find: make pred_empty safer and avoid fd leaks
|
|
|
|
There is a small race condition between the previous stat call
|
|
and openat/fdopendir (which cannot be avoided): if the directory
|
|
got replaced by another file type, then openat would succeed but the
|
|
subsequent fdopendir would fail with ENOTDIR. Detect this earlier
|
|
by passing the O_DIRECTORY flag.
|
|
Furthermore, the opened file descriptor was leaked in that case
|
|
(bug introduced in FINDUTILS_4_3_2-1-80-gb46b0d89 in 2007).
|
|
Later on, after a readdir error, also the directory stream was leaked
|
|
(bug introduced by myself in commit 7a6e548690b1).
|
|
|
|
* find/pred.c (pred_empty): Add more flags to the openat call,
|
|
especially O_DIRECTORY; inspired by gnulib's opendirat module.
|
|
Close the file descriptor when fdopendir failed.
|
|
Close the directory stream when readdir failed.
|
|
---
|
|
find/pred.c | 6 ++++--
|
|
1 file changed, 4 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/find/pred.c b/find/pred.c
|
|
index e34a41dc..688103d6 100644
|
|
--- a/find/pred.c
|
|
+++ b/find/pred.c
|
|
@@ -363,9 +363,9 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
|
errno = 0;
|
|
if ((fd = openat (state.cwd_dir_fd, state.rel_pathname, O_RDONLY
|
|
#if defined O_LARGEFILE
|
|
- |O_LARGEFILE
|
|
+ | O_LARGEFILE
|
|
#endif
|
|
- )) < 0)
|
|
+ | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK)) < 0)
|
|
{
|
|
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
|
state.exit_status = 1;
|
|
@@ -376,6 +376,7 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
|
{
|
|
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
|
state.exit_status = 1;
|
|
+ close (fd);
|
|
return false;
|
|
}
|
|
/* errno is not touched in the loop body, so initializing it here
|
|
@@ -396,6 +397,7 @@ pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_
|
|
/* Handle errors from readdir(3). */
|
|
error (0, errno, "%s", safely_quote_err_filename (0, pathname));
|
|
state.exit_status = 1;
|
|
+ CLOSEDIR (d);
|
|
return false;
|
|
}
|
|
if (CLOSEDIR (d))
|
|
--
|
|
2.19.1
|
|
|