On 2025-08-07, Josh Triplett <josh@xxxxxxxxxxxxxxxx> wrote: > I just discovered that opening a file with O_PATH gives an fd that works > with > > utimensat(fd, "", times, O_EMPTY_PATH) I guess you mean AT_EMPTY_PATH? We don't have O_EMPTY_PATH on Linux (yet, at least...). > but does *not* work with what futimens calls, which is: > > utimensat(fd, NULL, times, 0) > > The former will go through do_utimes_fd, while the latter goes through > do_utimes_path. I would have expected these two cases to end up in the > same codepath once they'd discovered they were operating on a file > descriptor, and I would have expected both to support O_PATH file > descriptors if either does. > > This is true for both symlinks (with O_NOFOLLOW | O_PATH) and regular > files (with just O_PATH). This is on 6.12, in case it matters. > > Quick and dirty test program (in Rust, using rustix to make syscalls): > > ``` > use rustix::fs::{AtFlags, OFlags, Timespec, Timestamps, UTIME_OMIT}; > > fn main() -> std::io::Result<()> { > let f = rustix::fs::open("oldfile", OFlags::PATH | OFlags::CLOEXEC, 0o666.into())?; > let times = Timestamps { > last_access: Timespec { tv_sec: 0, tv_nsec: UTIME_OMIT }, > last_modification: Timespec { tv_sec: 0, tv_nsec: 0 }, > }; > let ret = rustix::fs::utimensat(&f, "", ×, AtFlags::EMPTY_PATH); > println!("utimensat: {ret:?}"); > let ret = rustix::fs::futimens(&f, ×); > println!("futimens: {ret:?}"); > Ok(()) > } > ``` > > Is this something that would be reasonable to fix? Would a patch be > welcome that makes both cases work identically and support O_PATH file > descriptors? The set of things that are and are not allowed on O_PATH file descriptors is a bit of a hodge-podge these days. Originally the intention was for all of these things to be blocked by O_PATH (kind of like O_SEARCH on other *nix systems) but the existence of AT_EMPTY_PATH (and /proc/self/fd/... hackery) slowly led more and more things to be allowed. The current stalemate is that stuff which operates on the fd directly (fchmod/fchown) tends to not allow operations on O_PATH file descriptors, while stuff that operates on paths with AT_EMPTY_PATH (fchmodat/fchownat) does. Why? My impression is that this is mainly because the man-page (and the original descriptions by Al) says that the former set of functions don't work on O_PATH. (Though Al probably has a different viewpoint.) I was working on an attempted solution for this mess (as part of work to add O_EMPTY_PATH support while also plugging some holes in the re-opening semantics on Linux), but it's on the backburner for now. The core issue is that O_PATH is a very minimalistic capability system, and different users expect different things from O_PATH, and there isn't a nice way to make everyone happy with just one bit. -- Aleksa Sarai Senior Software Engineer (Containers) SUSE Linux GmbH https://www.cyphar.com/
Attachment:
signature.asc
Description: PGP signature