I thought this only allowed open(..., ... | O_TRUNC) on directories, allowing attackers to
truncate directories. If it allows writing to directories too (I'm behind a harsh firewall and
can't check right now), then I suspect this could be an exploitable hole as well as 'mere'
Consider: this code amounts to allowing hostile attackers to call link() on arbitrary files,
even in subdirectories they cannot read, by editing the directory to include a reference to
whatever-it-is. But more than that, it allows them to call link() *without adjusting the link
So, imagine a system which had /tmp or /var/tmp or something user-writable on the same
directory as /. The hostile attacker creates a directory, opens it for writing, and attaches a
link to /etc/passwd (without readdir()ing it, so IIRC the directory won't be cached yet so the
changes will be picked up: if not, allocate a lot of memory to push the cached copy out).
Then unlink() that copy, and the link count will fall to zero, leading to /etc/passwd being
unlinked. It's not open all the time, so this now leads to /etc/passwd's blocks being freed.
So far, so corruption: but now the attacker fills up his/her quota with minimum-size files
containing the /etc/passwd contents he wants (up to the length of /etc/passwd beforehand, or
one block, whichever is smaller), then unlinks them again, repeatedly. Because /etc/passwd is
now a view onto free space, I suspect that if you do this for long enough, it would let the
attacker replace /etc/passwd's contents, with, say, a single root account without password :)
unsubtle, but still an attack.
(Again, I haven't been able to check the code from here, and I can't recall whether files
whose link count falls to zero get their size reset to zero as well. If so, this particular
attack is prevented, and 'all' the attacker would be able to do would be to in effect truncate
any file on a filesystem he could write to, rather than being able to write arbitrary content