Subject: Re: CRITICAL ** Holes in default cron jobs ** CRITICAL
To: None <tech-kern@NetBSD.ORG>
From: Warner Losh <firstname.lastname@example.org>
Date: 12/31/1996 10:59:14
Maybe I'm missing something here, but it seems to me that there are
times that you don't want to follow symlinks. This is one of those
times. The only secure way to be sure is to have a unlink2() call
that doesn't follow symlinks. There are just too many races in the
name space management of the unix file system.
The idea to only remove files owned by root, et al is flawed for
several reasons. First, /etc/passwd is owned by root, and if you can
trick things into being removed, that would be a target. Second, you
still have the race between when you see an object in the tree and
when you go to stat/unlink it. Unless you can make that operation
atomic (seeing and statting), you won't be able to solve this race.
One idea that I had, and I sent to greywolf, which wouldn't exactly
work is to do the following, where xyzzy is a random string.
while (mkdir /tmp/$xyzzy) do
mv /tmp/* /tmp/.* /tmp/$xyzzy
rm -rf /tmp/$xyzzy
This works great if you want to remove EVERYTHING in /tmp. I don't
see any races in it, if done as root. All of /tmp will be gone (there
will be an expected error on the mv command that can be ignored).
However, most times you want to pick and chose which files you want to
blow away, while leaving the new ones in the same place an
unmolested. This falls down badly in that case, since trying to
rename something is still suseptible to the race. The above code
isn't racible (as far as I can tell) because /tmp can't be swapped out
(unless / is badly permissioned), and because mkdir is atomic. Once
the files land in $xyzzy, no one except root can access them. You
then know that you have a static tree to deal with, I believe.
Since it isn't useful, I'm not going down this path much farther. I
think it is safe, but there is a nagging doubt at the back of my brain
telling me that something is wrong with it and there might be a race
related to pwd of other processes. I can't find it, but that doesn't
mean it isn't there.