Paul Eggert <[email protected]> writes:

> Nowadays on GNU/Linux there's a better way: open the file with O_PATH,
> use fstat to check its type, then use openat2 (fd, "", ...) with
> O_RDONLY to get the file descriptor you really want. No races
> involving file types are possible, though unfortunately this behavior
> is undocumented (!) and the Gnulib openat2 emulation doesn't support
> this behavior (and it wouldn't be easy to add, for non-directories
> anyway). FreeBSD 13+ has a similar feature with openat (fd, "",
> O_RDONLY | O_EMPTY_PATH). It's too bad that GNU/Linux didn't follow
> FreeBSD's lead here, as the FreeBSD approach is simpler and
> better-documented, but the Linux kernel developers felt that they had
> run out of flags.
>
> I suppose copy_internal should use the O_PATH approach if on a
> new-enough GNU/Linux or FreeBSD system. Admittedly doing it this way
> would be nontrivial. And it wouldn't fix the problems on macOS. And
> openat2 will almost surely change in Linux 7.2 so this stuff is a bit
> bleeding-edge anyway.

Yes, all of that portability stuff does not sound fun...

Could you not just open everything with O_RDONLY and then use fstat
before calling read? You wouldn't get the protection from O_PATH, but
that seems mostly okay with me. Of course, it can always be added later
once those features stabilize and/or hacks are introduced into Gnulib.

>> The issue is that we get a bogus dev/ino from path based stat operations
>> when invoking 'install' with standard input as the source, for example.
>
> Yes, but let's go back to the original question: why is that dev+ino
> check there at all? What would go wrong if we removed it? Or, can we
> remove the check only in the cases where it's misguided, as is the
> case here?

It looks like the check is there to catch if the file is removed and
recreated between the stat and fstat. In theory that is inadequate since
the new file could have the same inode, but in practice it is fine as
far as I am aware.

Collin

Reply via email to