Subject: Re: funlink() for fun!
To: NetBSD Kernel Technical Discussion List <tech-kern@NetBSD.ORG>
From: Bill Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 07/15/2003 11:47:20
On Mon, 14 Jul 2003, Greg A. Woods wrote:

> [ On Monday, July 14, 2003 at 16:19:21 (+0200), Matthias Buelow wrote: ]
> I really don't want to sound condescending, but I do get the distinct
> feeling that you don't really understand the underlying reason why
> funlink() is desirable in the first place.

As an observer of this whole exchange, I'd have to say that a lot of us
don't have the "understanding" of why funlink() is desirable, because no
one who's championing "it" has really defined it nor explained what it's
to do. As best I can tell, you and greywolf has had different things in
mind and have been arguing about different shadows.

> The underlying goal of having a system call that can unlink a file when
> given a file descriptor open on that file is to avoid an unfortunately
> common insecure programming technique commonly called a "Time-Of-Check,
> Time-Of-Use (TOCTOU) race condition".  Calls to unlink() are vulnerable
> if they are passed the fully qualified pathname of a file that was
> created in or under an insecure (i.e. world-writable) directory, even if
> that path is checked for vulnerabilities and the file's metadata is
> compared to that of the originally created file before the unlink() call
> is made.  Implementing funlink() in userland would simply move the race
> condition to a new place and thus be no fix at all.  However a
> system-call implementation of funlink() could ensure the new race
> condition is impossible, thus ensuring the functionality fulfils the
> underlying requirements.

Then my suggestion is funlink(fd, path). The call does a nami lookup on
path, and if it gets the same thing as fd, removes it. And it can return
different errors depending on: unable to lookup path (permissions along
the way), unable to unlink (write permissions on parent dir), no such
file, file and fd differ, multiple links(*), or file already unlinked (0
links).

(*) Some flag may be in order to indicate if the unlink should proceed if
there are multiple links yet the one we're asked to remove exists; an
unlink in this case should get a different error code. While this is an
error in the "I've made a temp file and tried to unlink it" case, there
are other cases where I can see it may be useful.

Since the program should (or can) know the path the file should have, let
it take care of remembering it. That way only the cases that need this
bother with it.

Take care,

Bill