Bugtraq mailing list archives

Re: Race conditions


From: rwing!pat () ole cdac com (Pat Myrto)
Date: Fri, 9 Dec 94 23:32:20 PST


"In the previous message, Fred Blonder said..."

      From: rwing!pat () ole cdac com (Pat Myrto)

      And if a temp file MUST be made, use the mkstemp()
      call to generate the name and open it.  Mkstemp()
      atomically generates the tempname from the template,
      opens the file and returns a handle.  As the manpage
      says, mkstemp() eliminates the race condition between
      testing if a file exists, and the opening of the tmp file.

But 'mkstemp()' is in section 3 of the manual; it's a subroutine,
not a system call, so how can it be 'atomic'?


I err'd, I was told by another it was atomic.  After a bit more research
stimulated by your response, I found out that what it does is something
like mktemp() to generate an INITIAL tempname, and then tries an open(foo,
O_EXCL|O_CREAT|O_RDWR, 0600) on the name (which will fail if a symlink
or another file is there). If the open fails, the 'a' preceeding the
pid in the tempname that was generated to replace the 6 'X's, gets
incremented, and it tries again (with a 'b', 'c', ...  prefix) until it
succeeds or until the letter prefix has passed 'z'.  There is no stat(),
lstat(), or fstat() used -- the tempname is created (assuming pid ==
12345) with the leading letter 'a' as in a12345, and repeated open()s
will try b12345, c12345, etc.  If it cannot find a name to use, it will
finally return with a value of -1 instead of a file handle.

In other words, apparantly the 'atomicity' I was advised about is in
the open() call with those options, and used in that way, in its behavior
if a file exists, and then changing the name and re-trying again atomically
if a file or symlink is seen.  Sort of a trial-and-error scheme to find
an unused name, selecting a different filename if anything exists by
that name.

Mkstemp tries to find the name, finding one that is unique at the time
it creates it, hands it to the caller, then the caller calls open() on
the not-necessarily-unique name some time later.  In other words, the
test for uniquness on the name actually used is NOT done in the open call.
Mktemp() says the name is unique as of some nonzero time previously...

In other words, mkstemp() is useful IFF open(x,O_CREAT|O_EXCL|O_whatever,mode)
works properly.  So, if the OS does NOT support O_EXCL or if it does NOT
fail on an open O_RDRW call on a symlink pointing to nothing, one is back
to square one.
-- 
pat@rwing  [If all fails, try:  rwing!pat () eskimo com]  Pat Myrto - Seattle WA
"No one has the right to destroy another person's belief by demanding
empirical evidence."  --   Ann Landers, nationally syndicated advice columnist
and Director at Handgun Control Inc.



Current thread: