findutils-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Findutils-patches] [PATCH] find: make pred_empty safer and avoid fd lea


From: Bernhard Voelker
Subject: [Findutils-patches] [PATCH] find: make pred_empty safer and avoid fd leaks
Date: Sat, 9 Feb 2019 15:57:19 +0100

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.20.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]