예제 #1
0
FILE *
fopen_safer (char const *file, char const *mode)
{
  FILE *fp = fopen (file, mode);

  if (fp)
    {
      int fd = fileno (fp);

      if (0 <= fd && fd <= STDERR_FILENO)
	{
	  int f = dup_safer (fd);

	  if (f < 0)
	    {
	      int e = errno;
	      fclose (fp);
	      errno = e;
	      return NULL;
	    }

	  if (fclose (fp) != 0
	      || ! (fp = fdopen (f, mode)))
	    {
	      int e = errno;
	      close (f);
	      errno = e;
	      return NULL;
	    }
	}
    }

  return fp;
}
예제 #2
0
int
main ()
{
  int i;
  DIR *dp;
  /* The dirent-safer module works without the use of fdopendir (which
     would also pull in fchdir and openat); but if those modules were
     also used, we ensure that they are safe.  In particular, the
     gnulib version of fdopendir is unable to guarantee that
     dirfd(fdopendir(fd))==fd, but we can at least guarantee that if
     they are not equal, the fd returned by dirfd is safe.  */
#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR
  int dfd;
#endif

  /* We close fd 2 later, so save it in fd 10.  */
  if (dup2 (STDERR_FILENO, BACKUP_STDERR_FILENO) != BACKUP_STDERR_FILENO
      || (myerr = fdopen (BACKUP_STDERR_FILENO, "w")) == NULL)
    return 2;

#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR
  dfd = open (".", O_RDONLY);
  ASSERT (STDERR_FILENO < dfd);
#endif

  /* Four iterations, with progressively more standard descriptors
     closed.  */
  for (i = -1; i <= STDERR_FILENO; i++)
    {
      if (0 <= i)
        ASSERT (close (i) == 0);
      dp = opendir (".");
      ASSERT (dp);
      ASSERT (dirfd (dp) == -1 || STDERR_FILENO < dirfd (dp));
      ASSERT (closedir (dp) == 0);

#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR
      {
        int fd = dup_safer (dfd);
        ASSERT (STDERR_FILENO < fd);
        dp = fdopendir (fd);
        ASSERT (dp);
        ASSERT (dirfd (dp) == -1 || STDERR_FILENO < dirfd (dp));
        ASSERT (closedir (dp) == 0);
        errno = 0;
        ASSERT (close (fd) == -1);
        ASSERT (errno == EBADF);
      }
#endif
    }

#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR
  ASSERT (close (dfd) == 0);
#endif

  return 0;
}
예제 #3
0
int
fd_safer (int fd)
{
  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
    {
      int f = dup_safer (fd);
      int e = errno;
      close (fd);
      errno = e;
      fd = f;
    }

  return fd;
}
예제 #4
0
DIR *
opendir_safer (char const *name)
{
  DIR *dp = opendir (name);

  if (dp)
    {
      int fd = dirfd (dp);

      if (0 <= fd && fd <= STDERR_FILENO)
        {
          /* If fdopendir is native (as on Linux), then it is safe to
             assume dirfd(fdopendir(n))==n.  If we are using the
             gnulib module fdopendir, then this guarantee is not met,
             but fdopendir recursively calls opendir_safer up to 3
             times to at least get a safe fd.  If fdopendir is not
             present but dirfd is accurate (as on cygwin 1.5.x), then
             we recurse up to 3 times ourselves.  Finally, if dirfd
             always fails (as on mingw), then we are already safe.  */
          DIR *newdp;
          int e;
#if HAVE_FDOPENDIR || GNULIB_FDOPENDIR
          int f = dup_safer (fd);
          if (f < 0)
            {
              e = errno;
              newdp = NULL;
            }
          else
            {
              newdp = fdopendir (f);
              e = errno;
              if (! newdp)
                close (f);
            }
#else /* !FDOPENDIR */
          newdp = opendir_safer (name);
          e = errno;
#endif
          closedir (dp);
          errno = e;
          dp = newdp;
        }
    }

  return dp;
}
FILE *
tmpfile_safer (void)
{
  FILE *fp = tmpfile ();

  if (fp)
    {
      int fd = fileno (fp);

      if (0 <= fd && fd <= STDERR_FILENO)
        {
          int f = dup_safer (fd);

          if (f < 0)
            {
              int e = errno;
              fclose (fp);
              errno = e;
              return NULL;
            }

          /* Keep the temporary file in binary mode, on platforms
             where that matters.  */
          if (fclose (fp) != 0
              || ! (fp = fdopen (f, O_BINARY ? "wb+" : "w+")))
            {
              int e = errno;
              close (f);
              errno = e;
              return NULL;
            }
        }
    }

  return fp;
}