Bugtraq mailing list archives

Re: access(2)--a security hole?


From: mouse () Collatz McRCIM McGill EDU (der Mouse)
Date: Sat, 22 Oct 1994 21:40:07 -0400


The security hole in access() is really that it has an implicit race
condition in it.  [...]
The obvious correct coding is to open *first*, then check access, and
close it back up if you shouldn't have opened it.

This opens up other problems - you can't do it at all if you use
O_CREAT, or you can end up creating files where the user can't.  Yes,
you can unlink it afterwards, but damage may have been done already,
and if you didn't use O_EXCL you can't even tell whether you should do
the unlink.  (There's no way to do the equivalent of an atomic
"test-and-set" open, one which indicates somehow whether the file
already existed, but opens/creates it regardless.  O_TAS anyone?)

And you still can't use access() to do the check, because the symlink
may have been switched back.  You have to do a very complicated and
painful directory tree walk, using lstat/fstat all over the place and I
think opening up more races, probably one per directory involved in the
walk.

Thus, this "obvious correct coding" isn't correct at all; the only
correct thing to do is to do the operation under the UID (and GID, for
setgid programs) that must be able to perform the operation.  If there
were some way to perform multiple syscalls atomically with respect to
other processes, this might not be necessary, but there isn't.  (Except
for a few OSes that provide some sort of preemptive high-priority
scheduling, and as far as I know all such restrict access to those
priorities to processes running as root, and even then usually don't
guarantee that nobody else will run while the high-priority process is
blocked in the kernel in a syscall.)

                                        der Mouse

                            mouse () collatz mcrcim mcgill edu



Current thread: