Subject: Re: funlink() for fun!
To: NetBSD Kernel Technical Discussion List <tech-kern@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-kern
Date: 07/11/2003 16:48:54
>>> If all one is trying to do is flesh out the set of f*() system
>>> calls which have file descriptor parameters to make it orthogonal
>>> to the set which have pathname parameters then
>> ...you shouldn't do funlink() in this form in the first place, as
>> unlink() is not an operation on a file but an operation on a link to
>> a file.
> But that's the whole point of funlink() (and perhaps even some of the
> other f*() calls, such as fchdir()) -- turn an operation on a file
> into an operation on a filename (i.e. a link to a file).
Not quite. chdir() operates on a process and a directory; the pathname
is necessary only to identify the directory. It could equally well
identify the directory by a file descriptor open on it, and that's
exactly what fchdir() does. truncate() operates on a file; the
pathname is used merely to find the desired file. It too could equally
well identify the file by a file descriptor open on it, and that's
exactly what ftruncate() does.
However, unlink() does not operate on a file, except as a side effect;
it operates on a link to a file. The file is affected, sometimes very
mildly, sometimes severely, but the critical point is that the pathname
is not serving just to locate the file, but rather to locate a
particular link to the file. Since file descriptors are on files, not
on links to files, funlink() doesn't really make sense.
>> Now, an funlink() that takes an fd on a directory and a (slashless)
>> component name, that would be a sensible way to add an fd-based
>> variant of unlink().
> If the process has an FD open on the parent directory then it should
> be able to much more easily just fchdir() there first, obtaining and
> keeping an open FD for its PWD for those cases where it has to go
> right back to where it started.
Yes, it should be able to. But since you can't open "." if your
current directory is execute-only, it can't. (It'd also be nice to be
able to do one syscall (funlink of this flavor) instead of three
(fchdir, unlink, fchdir).)
> For other uses (such as unlinking stdin) such a form would be
> unusable, and after all the goal is to define a system call that
> accepts a file descriptor and acts upon the file that was opened in
> the same way as the s/^f// system call would act when passed a
> filename referring to the same file that was opened.
Which is why you can't do funlink(), because unlink doesn't operate on
files; it operates on links to files. The file is operated on only in
that it's garbage-collected once it's no longer referenceable. (Which
may be when its refcount goes to zero, or it may be an indeterminate
time later.)
> I've always though the only extremely serious omission in the f*()
> function call set has been faccess()
It doesn't really make sense, unless you also add fopen() (which name
has unfortunately already been preempted by stdio), to re-open a file
with potentially different access rights. Otherwise, faccess() doesn't
tell you anything of use.
> (and of course there should not have ever been an access() call since
> it is inherently insecure);
How so? Provided you realize what it does, and more importantly what
it doesn't do, there's nothing wrong with it. (In particular, access()
with F_OK is useful to non-setid programs.)
> It could also be very useful for secure programming if we had an
> O_MKDIR flag for open() that would [combine mkdir() and open()].
> O_MKDIR may even eliminate enough of the cases where you'd use your
> O_NOACCESS to make O_NOACCESS strictly unnecessary.
No, it wouldn't. You still couldn't save and restore your current
directory by opening "." and fchdir()ing back there if your current
directory is execute-only, even with O_MKDIR, without O_NOACCESS.
/~\ The ASCII der Mouse
\ / Ribbon Campaign
X Against HTML mouse@rodents.montreal.qc.ca
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B