openat: avoid using wrong fd
authorEric Blake <ebb9@byu.net>
Wed, 7 Oct 2009 12:56:52 +0000 (06:56 -0600)
committerEric Blake <ebb9@byu.net>
Wed, 7 Oct 2009 13:15:08 +0000 (07:15 -0600)
Detected by a Solaris failure on:
int fd = dup (0);
close (fd);
mkdirat (fd, "dir", 0700);
which created "./dir" instead of failing with EBADF.

* lib/openat.c (openat_permissive): Reject user's fd if saving the
working directory chooses same fd.
* lib/at-func.c (AT_FUNC_NAME): Likewise.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
lib/at-func.c
lib/openat.c

index 96296ef..c120c09 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2009-10-07  Eric Blake  <ebb9@byu.net>
 
+       openat: avoid using wrong fd
+       * lib/openat.c (openat_permissive): Reject user's fd if saving the
+       working directory chooses same fd.
+       * lib/at-func.c (AT_FUNC_NAME): Likewise.
+
        mkdir, mkdirat: fix cygwin 1.5.x bug
        * lib/mkdir.c (rpl_mkdir) [FUNC_MKDIR_DOT_BUG]: Work around bug.
        * m4/mkdir-slash.m4 (gl_FUNC_MKDIR_TRAILING_SLASH): Move...
index 75c80d3..4e5ba2f 100644 (file)
@@ -89,6 +89,15 @@ AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS)
 
   if (save_cwd (&saved_cwd) != 0)
     openat_save_fail (errno);
+  if (0 <= fd && fd == saved_cwd.desc)
+    {
+      /* If saving the working directory collides with the user's
+         requested fd, then the user's fd must have been closed to
+         begin with.  */
+      free_cwd (&saved_cwd);
+      errno = EBADF;
+      return -1;
+    }
 
   if (fchdir (fd) != 0)
     {
index 079039f..aae7782 100644 (file)
@@ -202,6 +202,15 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode,
        openat_save_fail (errno);
       *cwd_errno = errno;
     }
+  if (0 <= fd && fd == saved_cwd.desc)
+    {
+      /* If saving the working directory collides with the user's
+         requested fd, then the user's fd must have been closed to
+         begin with.  */
+      free_cwd (&saved_cwd);
+      errno = EBADF;
+      return -1;
+    }
 
   err = fchdir (fd);
   saved_errno = errno;