![]() |
|
Message-ID: <20250913124834.GS1827@brightrain.aerifal.cx> Date: Sat, 13 Sep 2025 08:48:34 -0400 From: Rich Felker <dalias@...c.org> To: Demi Marie Obenour <demiobenour@...il.com> Cc: musl@...ts.openwall.com Subject: Re: closefrom and close_range wrappers On Fri, Sep 12, 2025 at 09:40:22PM -0400, Demi Marie Obenour wrote: > Would it make sense for musl to provide close_range and > closefrom? The main uses of them are to close unwanted > FDs after a fork and before exec. close_range() can also > be used to mark them close-on-exec instead. > > The main advantage of closefrom() is that it is portable > to more systems. Closing file descriptors one doesn't own > is not an issue because the code that does own these FDs > will never get a chance to run. In particular, calling any > stdio functions that use anything but stdin, stdout, and > stderr would be UB. stdin, stdout, and stderr use FD 0, 1, > and 2, respectively, and those are almost always left open. > > Yes, this is all a consequence of fork()/exec() being an > extremely poor API, but I don't know of a better solution. > There are third-party libraries (including glib and wlroots) > that expect one to either use an API like this or emulate it > by scanning /proc/self/fd (yuck). Yes, these libraries should > be atomically setting O_CLOEXEC, but their authors disagree > and maintaining downstream forks is not practical. I need to look back at where we left this last time it was discussed. As Laurent replied, per the standard (POSIX) these operations are fundamentally programming errors. Closing a fd that "doesn't belong to you" (that may be some implementation detail of the POSIX implementation or some part of the execution environment hosting your application) produces undefined behavior. Nonetheless, people do want to do it for various reasons and the existing ways of doing it without the syscall are "worse". One question that naturally arises whenever adding an interface like this is what we do on kernel versions that lack it. Do we fail it and leave the application to figure out what to do when it fails, or emulate it? If taking the failing option, there's not a whole lot of value over the caller just using syscall() directly, but maybe it makes sense. I think there are some macro constants needed to use the syscall that potentially make it difficult to do without libc exposing anything (possible conflicts pulling in kernel headers). I'll try to find past discussion of this. If anyone else has it handy to cite, go ahead. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.