Thanks for adding the O_RESOLVE_BENEATH flag [0]. I do have one report of surprising behavior with it. It seems that opening ".." with a base fd referencing "/" succeeds. This is understandable, because ".." in the root directory refers to the root directory, and indeed it's not outside the base fd in that case. However, use cases for O_RESOLVE_BENEATH would be better served by having an open of ".." with a base fd of the root directory fail. If one has path strings coming from an untrusted source, one wouldn't want the source to be able to tell where the base is in the overall filesystem namespace. If opening ".." at the top level succeeds, that reveals that the base directory is in fact the root directory. For comparison, Linux's openat2's RESOLVE_BENEATH flag fails on ".." at the root. [0]: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=248335
What are the consequences of knowing that fd is root? In other words, what could an adversary do knowing that, that she could not do otherwise? I do not want to introduce a special case in lookup() for this situation, unless it is indeed a must.
For example, if I have a network file server using O_RESOLVE_BENEATH to ensure that I'm only serving files within a certain directory, and the directory contains directories like "bin", "etc", and similar, attackers could tell whether I'm serving up my actual root directory or just some other directory that has root-like contents. If it is my actual root directory, that might help them learn about the version or configuration of the system the server is running on. It may also reveal that the server is running FreeBSD, since the Linux with RESOLVE_BENEATH implementation and the portable-but-slow implementation I have both fail in this situation.
The 'attacker' can try to fetch 'bin/ls' regardless of the behavior of /.. .
If I'm not serving up my actual root directory, `bin/ls` might not be from the OS or architecture I'm running the server on.
(In reply to Konstantin Belousov from comment #1) It's not like the consequences are huge, but - right now if there is a requirement to have consistent behavior in this obscure case across platforms, it's annoying to implement (every open call would need to waste a syscall probing whether the fd is the root like this, and falling back to a manual userspace implementation if that's the case) - inside FreeBSD itself we might want the same consistency for implementing RESOLVE_BENEATH in Linuxulator?
https://reviews.freebsd.org/D39773
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=a718431c30a57226bc7c1a9181fc84bab00641a1 commit a718431c30a57226bc7c1a9181fc84bab00641a1 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2023-04-23 23:21:42 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2023-04-24 21:32:10 +0000 lookup(): ensure that openat("/", "..", O_RESOLVE_BENEATH) fails PR: 269780 Reported by: Dan Gohman <dev@sunfishcode.online> Reviewed by: emaste, markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D39773 sys/kern/vfs_lookup.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=16004e477d387d6a075597ec76f0dc82d02b60db commit 16004e477d387d6a075597ec76f0dc82d02b60db Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2023-04-23 23:21:42 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2023-05-01 06:45:28 +0000 lookup(): ensure that openat("/", "..", O_RESOLVE_BENEATH) fails PR: 269780 (cherry picked from commit a718431c30a57226bc7c1a9181fc84bab00641a1) sys/kern/vfs_lookup.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)