Writing to A NON-Existing File in \"C\"

der Mouse mouse at larry.mcrcim.mcgill.edu
Tue Apr 26 20:08:24 AEST 1988


>> [access is ...] the wrong way to [determine whether the real user
>> can access a file], because of the resulting window, but that's
>> another can of worms.

> OK, now to address that window issue.  As I understand it, the basic
> objection to access is a window of vulnerability between deciding if
> access to a file is okay, and actually doing something to that file.

Precisely.  At least, that's the one I meant.

> I propose enclosing the whole mess between two stat's, and testing
> whether the vital statistics match.  Then, you can assume it's the
> same file you asks about via access.

Well, you have to be very careful, and even then, I don't think it's
possible to get it right.  You can make the window much harder to hit,
but I don't think it's possible to get rid of it entirely.  After much
arguing with myself, the closest I've come up with is

fd = open(path) <--- this must succeed, of course
access(path)    <--- this must show "access permitted"
stat(path)      <--\ These two must produce
fstat(fd)       <--/  matching stat structures

but this is vulnerable to a quick switch immediately before and after
the access() call.  Sprinkling extra calls (stat(), access(), etc)
around doesn't help, because if the switches occur exactly before and
after the access(), it is impossible to detect them.

None of this helps any when you want to find out whether it is safe to
create or remove a file.  For any sequence of operations, switching
symlinks immediately before (and after) an unlink() or
open(...,O_CREAT,...) can beat it.  Therefore, if a setuid program is
to create or remove a file, it must be very sure that the real user
cannot pull a switch on any directory on the path used to reach the
file in question.  Chdir() first (or create all your files in / :-)

What's more, when creating, O_EXCL must be used.  I shan't describe the
problem in detail, because I'm sure far too few setuid programs
actually do bother to use O_EXCL, and I don't want to be too blatant
about giving directions on how to break into a system.

What we need, it seems, is a way to say "I wish to restrict myself to
the real user's access privileges" for a time, with the potential to
revert back to the previous state.  4.3's setreuid() appears to be
exactly this, though I seem to recall that if the real uid is 0, the
process has superuser access even if the effective uid is not 0, which
would mean that this technique is useless for setuid-root programs.

It might be worth putting a flag into open() (O_REALUID maybe) to have
it use the real UID when it does permission checks, just as a case of
"make the common case easy".  Open already takes flags, so it would be
totally compatible.

Security is such a mess.  Why don't we all run GNU and leave this sort
of security to the security freaks?  Oh yes, that's right, GNU doesn't
exist yet.  Bother.

					der Mouse

			uucp: mouse at mcgill-vision.uucp
			arpa: mouse at larry.mcrcim.mcgill.edu



More information about the Comp.unix.wizards mailing list