Ty Sarna sez:
*
* This illustrates something that's bugged me about Un*x-oid systems for a
* long time: the lack of any way to get a handle on a file (as distinct
* from what open() returns, which is more like a handle on the file's
* contents). That would solve many of these problems, by allowing the
* lookup operation to be separate, and then allowing unlink() et all to be
* used on the handle, with a guarantee that all operations on the handle
* will be done on the same file. It does introduce a few new problems, but
* I think they're solvable.
Once you open a file descriptor, you have a handle, really. A switcheroo
once you have the file open will accomplish nothing, since an open
returns a fd which operates on data associated with a particular inode.
Someone suggested making a directory in /tmp, which was then argued against
because "it could be switched out". Last I looked, /tmp was _supposed_
to be mode 777+sticky so that renames/rmdir-mkdir would fail for anyone
except the owner of the directory, the owner of a file, or the super-user.
It seems we're running into the age-old problem of pitting the better
mousetraps against the better mice.
Perhaps the mk{,s}temp calls should have a final fallback algorithm
which would use a random character pattern in the case that all the
standard paths were used ("Well, hell, I can't make anything of this,
let's try something completely different"). This would certainly thwart
any potential miscreants.
The handle() thing might seem interesting at first, but open() really
seems to manage what is necessary.
The upshot of this whole argument is perhaps the find operation is better
off not using /tmp for storage of "temporary" files at all (maybe run
"rm -fr /tmp/.stmp; umask 77; mkdir /tmp/.stmp" just before you start
inetd...?).
* This guarantees that nobody can switch symlinks on you in the meantime.
How does this help you above a stat() call...?
The mkstemp() call seems to be a good alternative for making temporary
file templates; its only failing is that all it returns is a file
descriptor where it should probably be returning some more information
(like a file name...?).
(Of course, there's always fstat(), which should be called before trusting
the descriptor anyway, if you're sufficiently paranoid.)
* It also logically simplifies the stat() variants (stat() and lstat()
* become handle()/hstat()/unhand() wrappers that do or don't set
* DONT_FOLLOW_SYMLINKS, fstat() becomes a wrapper for
* fh2handle()/hstat()/unhand., etc). It also makes access() (in the form
* of haccess()) more useful as well.
*
It looks like an extra layer of complexity that we really don't need.
Why the dependency on a particular filename anyway? If you really have
a need to do that, just hang on to your descriptor and rewrite it
someplace where you KNOW the name can't be altered, and use that name
for all further references...
*/
--*greywolf;