Bugtraq mailing list archives

Re: Temporary Files (was Re: mktemp() and friends)


From: chet () odin INS CWRU Edu (Chet Ramey)
Date: Fri, 3 Jan 1997 11:01:11 -0500


Under bash this can be avoided theoretically:

set -C
exec > /tmp/foo
if ! test -f /dev/fd/1; then
        error...
fi

There are two bugs in bash which makes this unsafe.  The bash manual tells
you that tests to /dev/fd/n apply to the file descriptor n but in fact they
apply to the real /dev/fd/n if the OS supports the /dev/fd filesystem.  On
Solaris /dev/fd/n is always a device special file which makes the above
test fail in all cases.

I'm still thinking about this one, so the `bug' still exists.

The other bug is that noclobber is not implemented atomically.  Here is the
code.  Redirect->flags contains O_TRUNC | O_WRONLY | O_CREAT here:

          r = stat (redirectee_word, &finfo);

          if (r == 0 && (S_ISREG (finfo.st_mode)))
            {
              free (redirectee_word);
              return (NOCLOBBER_REDIRECT);
            }

          /* If the file was not present, make sure we open it exclusively
             so that if it is created before we open it, our open will fail. */
          if (r != 0)
            redirect->flags |= O_EXCL;

          fd = open (redirectee_word, redirect->flags, 0666);

As you can see bash will happily truncate any symlink created between the
stat and open.  I have already mailed the bash maintainer about these bugs.

The current (unreleased post bash-2.0) bash code adds a couple of
checks to this.  The O_EXCL is still in there only if the file does
not exist at stat(2) time.  If the file exists and is not a regular
file, O_EXCL is not used.  O_TRUNC is turned off.  This preserves
POSIX.2 compatibility.  If the open succeeds, a check is done using
fstat(2) to ensure that it still points to the same non-regular file
that stat(2) checked.  If the file opened is suddenly a regular file
or a different special file, bash assumes that the file has changed
underneath it and returns an error.

Of course the right way to do that is to never use O_TRUNC with noclobber,
try O_WRONLY | O_CREAT | O_EXCL first, and if that fails, open it with
O_WRONLY, fstat the returned file descriptor and close it and fail if it is
a regular file.

The current bash approach is very similar, with additional checks.



--
``The lyf so short, the craft so long to lerne.'' - Chaucer

Chet Ramey, Case Western Reserve University     Internet: chet () po CWRU Edu



Current thread: