]> granicus.if.org Git - sudo/commitdiff
Use /proc/self/fd instead of /proc/$$/fd
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 9 Jun 2007 11:26:43 +0000 (11:26 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sat, 9 Jun 2007 11:26:43 +0000 (11:26 +0000)
Move old-style fd closing into closefrom_fallback() and call
that if /proc/self/fd doesn't exist or the F_CLOSEM fcntl() fails

closefrom.c

index 03ee1b2c637b40f27cffe2922e4c0789135d9f2d..a6118b83b569fb3e2e55091c11b5b7ed7996badc 100644 (file)
 __unused static const char rcsid[] = "$Sudo$";
 #endif /* lint */
 
+#ifndef HAVE_FCNTL_CLOSEM
+# ifndef HAVE_DIRFD
+#   define closefrom_fallback  closefrom
+# endif
+#endif
+
 /*
  * Close all file descriptors greater than or equal to lowfd.
+ * This is the expensive (ballback) method.
+ */
+void
+closefrom_fallback(lowfd)
+    int lowfd;
+{
+    long fd, maxfd;
+
+    /*
+     * Fall back on sysconf() or getdtablesize().  We avoid checking
+     * resource limits since it is possible to open a file descriptor
+     * and then drop the rlimit such that it is below the open fd.
+     */
+#ifdef HAVE_SYSCONF
+    maxfd = sysconf(_SC_OPEN_MAX);
+#else
+    maxfd = getdtablesize();
+#endif /* HAVE_SYSCONF */
+    if (maxfd < 0)
+       maxfd = OPEN_MAX;
+
+    for (fd = lowfd; fd < maxfd; fd++)
+       (void) close((int) fd);
+}
+
+/*
+ * Close all file descriptors greater than or equal to lowfd.
+ * We try the fast way first, falling back on the slow method.
  */
 #ifdef HAVE_FCNTL_CLOSEM
 void
 closefrom(lowfd)
     int lowfd;
 {
-    (void) fcntl(lowfd, F_CLOSEM, 0);
+    if (fcntl(lowfd, F_CLOSEM, 0) == -1)
+       closefrom_fallback(lowfd);
 }
 #else
+# ifdef HAVE_DIRFD
 void
 closefrom(lowfd)
     int lowfd;
 {
-    long fd, maxfd;
-#ifdef HAVE_DIRFD
-    char fdpath[PATH_MAX], *endp;
     struct dirent *dent;
     DIR *dirp;
-    int len;
+    char *endp;
+    long fd;
 
-    /* Check for a /proc/$$/fd directory. */
-    len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
-    if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
+    /* Use /proc/self/fd directory if it exists. */
+    if ((dirp = opendir("/proc/self/fd")) != NULL) {
        while ((dent = readdir(dirp)) != NULL) {
            fd = strtol(dent->d_name, &endp, 10);
            if (dent->d_name != endp && *endp == '\0' &&
@@ -84,23 +117,7 @@ closefrom(lowfd)
        }
        (void) closedir(dirp);
     } else
-#endif
-    {
-       /*
-        * Fall back on sysconf() or getdtablesize().  We avoid checking
-        * resource limits since it is possible to open a file descriptor
-        * and then drop the rlimit such that it is below the open fd.
-        */
-#ifdef HAVE_SYSCONF
-       maxfd = sysconf(_SC_OPEN_MAX);
-#else
-       maxfd = getdtablesize();
-#endif /* HAVE_SYSCONF */
-       if (maxfd < 0)
-           maxfd = OPEN_MAX;
-
-       for (fd = lowfd; fd < maxfd; fd++)
-           (void) close((int) fd);
-    }
+       closefrom_fallback(lowfd);
 }
-#endif /* !HAVE_FCNTL_CLOSEM */
+#endif /* HAVE_DIRFD */
+#endif /* HAVE_FCNTL_CLOSEM */