On 2025-09-26 10:55, Paul Eggert wrote:
I'm planning a future patch to use AT_RESOLVE_BENEATH if available, and this won't be an issue on FreeBSD once that happens.
I did this by installing the attached patches. Comments welcome. In doing it I noticed one tiny glitch in the FreeBSD implementation: it opens /usr/share/zoneinfo with O_RDONLY. Surely that should be O_SEARCH. This makes no practical difference since the directory is always both readable and searchable, but I thought I'd mention it.
Second, even platforms lacking AT_RESOLVE_BENEATH get equivalent security guarantees, because we can trust the contents of /usr/share/ zoneinfo (if we can't trust that directory, we have bigger problems than those fixable by AT_RESOLVE_BENEATH!) and tzcode's localtime checks for ".." in relative pathnames (I'll arrange for this check to be optimized away on platforms with AT_RESOLVE_BENEATH).
On thinking about it more, I still don't see how bleeding-edge FreeBSD's recently-added openat+open approach is a win for localtime.c. That approach slows things down (because we now have two extra syscalls: openat and close); it introduces new failure modes (e.g., EMFILE); and it provides no extra security because it does not fix any TOCTTOU races in practice. Although the attached patches implement the approach anyway (as an option), I'm hoping that upon further reflection the FreeBSD maintainers agree that it's unnecessary; if so, we can remove the option from tzcode. If I'm not mistaken, the two remaining features in FreeBSD but not tzcode are support for intermittent polling for TZif file changes, and support for poorly written multithreaded programs that use localtime/gmtime/offtime instead of localtime_r/gmtime_r/offtime_r. I plan to look at these two features in that order.