]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp,mv,install: avoid EACCES with non directory destination
authorPádraig Brady <P@draigBrady.com>
Sun, 10 Apr 2022 15:59:40 +0000 (16:59 +0100)
committerPádraig Brady <P@draigBrady.com>
Tue, 12 Apr 2022 23:37:12 +0000 (00:37 +0100)
* src/system.h (target_directory_operand): Also check with stat()
on systems with O_SEARCH, to avoid open("file", O_SEARCH|O_DIRECTORY)
returning EACCES rather than ENOTDIR, which was seen on Solaris 11.4
when operating on non dirs without execute bit set.
* NEWS: Remove related bug entry, as that issue was only introduced
after coreutils v9.0 was released.
Reported by Bruno Haible.

NEWS
src/system.h

diff --git a/NEWS b/NEWS
index 69feffcbc13727ec2820669cec0c220768f12a63..85fd5be122f9678b9937c633077848dcbc529319 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -21,11 +21,6 @@ GNU coreutils NEWS                                    -*- outline -*-
   and B is in some other file system.
   [bug introduced in coreutils-9.0]
 
-  cp, mv, and install, on older systems like Solaris 10 without O_DIRECTORY
-  support, avoid opening non directory destination operands.  Opening such
-  files can have side effects, like hanging with a fifo for example.
-  [bug introduced in coreutils-9.0]
-
   On macOS, fmt no longer corrupts multi-byte characters
   by misdetecting their component bytes as spaces.
   [This bug was present in "the beginning".]
index c24cb4dc393031b820611f2c1b19b083e0eb939f..768c3a1f2a45fdff3d6ace3aa87ad35a7fccc3b7 100644 (file)
@@ -137,19 +137,23 @@ target_directory_operand (char const *file)
     return AT_FDCWD;
 
   int fd = -1;
-  bool is_a_dir = false;
+  int maybe_dir = -1;
   struct stat st;
 
-  /* On old systems like Solaris 10, check with stat first
-     lest we try to open a fifo for example and hang.  */
-  if (!O_DIRECTORY && stat (file, &st) == 0)
+  /* On old systems without O_DIRECTORY, like Solaris 10,
+     check with stat first lest we try to open a fifo for example and hang.
+     Also check on systems with O_PATHSEARCH == O_SEARCH, like Solaris 11,
+     where open() was seen to return EACCES for non executable non dirs.
+     */
+  if ((!O_DIRECTORY || (O_PATHSEARCH == O_SEARCH))
+      && stat (file, &st) == 0)
     {
-      is_a_dir = !!S_ISDIR (st.st_mode);
-      if (! is_a_dir)
+      maybe_dir = S_ISDIR (st.st_mode);
+      if (! maybe_dir)
         errno = ENOTDIR;
     }
 
-  if (O_DIRECTORY || is_a_dir)
+  if (maybe_dir)
     fd = open (file, O_PATHSEARCH | O_DIRECTORY);
 
   if (!O_DIRECTORY && 0 <= fd)