[3880] in bugtraq

home help back first fref pref prev next nref lref last post

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

daemon@ATHENA.MIT.EDU (Chet Ramey)
Fri Jan 3 12:37:45 1997

Date: 	Fri, 3 Jan 1997 11:01:11 -0500
Reply-To: chet@po.CWRU.Edu
From: Chet Ramey <chet@odin.INS.CWRU.Edu>
X-To:         hzoli@cs.elte.hu
To: Multiple recipients of list BUGTRAQ <BUGTRAQ@NETSPACE.ORG>
In-Reply-To:  Message from hzoli@cs.elte.hu of Fri, 27 Dec 1996 01:45:29 +0100
              (id <199612270045.BAA07194@hzoli.ppp.cs.elte.hu>)

> 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

home help back first fref pref prev next nref lref last post