Bugtraq mailing list archives

Re: Race conditions


From: mouse () Collatz McRCIM McGill EDU (der Mouse)
Date: Wed, 7 Dec 1994 20:41:25 -0500


How does one code a suid program so that it evades these problems
with symlink race conditions?

"Vewy, vewy cawefuwwy."

Setuid programs should always be coded very carefully.  Programs that
have to be race-immune _must_ be coded very carefully.  Programs that
are both (which includes many/most setuid programs) require even more
extreme care.  It helps if you've done parallel code, because it helps
develop the necessary discipline of thinking of worst-case races.

Is there a way to atomically check if a file is a symlink and open
it, or is there another stratedgy?

Sort of.  The following might be sufficiently paranoid to be generally
safe.  (Note: I said "might be", not "is".)

To open a file, which should already exist:

        - lstat() the path, check that lstat succeeded
        - check that it's acceptable (eg, not a symlink :-)
        - open() (without O_CREAT), check that the open succeeded
        - fstat() the fd returned by open
        - if the lstat and fstat st_ino and st_dev fields match,
          accept.

To create a new file, which doesn't already exist:

        - lstat() the path, check that you got ENOENT
        - open(...,...|O_CREAT|O_EXCL,...), check that it succeeded
If you're really paranoid, then:
        - fstat() the fd returned by open
        - lstat() the path again, check that (a) it exists and (b)
          isn't a symlink
        - check that the fstat and the last lstat returned matching
          st_dev and st_ino fields

Note that the latter depends on the O_CREAT|O_EXCL semantics of not
following a trailing symlink.  I would have preferred an O_NOSYMLINK
bit, myself, but oh well.

                                        der Mouse

                            mouse () collatz mcrcim mcgill edu



Current thread: