>> to that end, i propose that we treat any open descriptor N>2 at the >> time of an exec() to be a bug, which is to be fixed by setting >> O_CLOEXEC at time of creation. > >What impact will such a decision have on tools like setlock which open a >filedescriptor, obtain an exclusive lock, and then exec a process? For >example, I may use something like the following in a script to prevent >multiple processes from incorporating email: > >setlock /tmp/mit.lock inc +MyIncTmp ...
Well, my reading of the setlock man page (assuming this is the FreeBSD one) is that it is not depending on a _descriptor_ to be passed down (I don't even know how that would work), but in fact it is opening a particular _file_ and locking it. But let's pretend that it actually did need to have a descriptor passed down to nmh programs, and the locking needed to extend to any children that inc forked (that's the critical case here). Today, depending on which code path was executed, that would either a) work fine (because we don't close any descriptors) or b) fail miserably (because we close all descriptors above 2, but sometimes maybe 3). My change makes it so we no longer close all descriptors when creating a child process (in the majority of cases we didn't). The particular change I have started implementing is that any descriptors _created by nmh_ will be marked as close-on-exec, so they will no longer be available to child processes (well, technically, child processes that have called exec(), but you know what I mean). For example, let's say inc(1) is talking to a POP server. Before, the network connection to the POP server was available to programs that inc(1) happened to fork off. One possible example would be the add-hook program if you happened to define one (the hook code never closed extra file descriptors). I think most people would agree that this is probably not desirable. Now that the network descriptors are marked as close-on-exec, child processes (like the hooks code) never see them. Even if the hooks are not doing anything malicious, it's easy to imagine possible problems with a network socket ending up in their address space. If the hooks code forks off a long-running process, for example, that could leave a network socket open that nmh had considered closed and could potentially cause problems if (for example) the POP server expected you to close the connection before it allowed another one. There are tons of examples like this in nmh; plenty of child processes are created with descriptors open. Most of these are for files, but clearly at best that's sloppy and at worst is dangerous. I can see this only getting worse if we get IMAP support or additional plugin interfaces. My eventual goal is to make it so every new descriptor created _by nmh_ has close-on-exec set by default. This wouldn't affect descriptors inherited by nmh programs (because they wouldn't know about them) or descriptors created by library functions (nmh wouldn't know about them either); hopefully any descriptors created internally by a library function would be marked properly (a quick check shows that this is not an unfounded assumption; at least on MacOS X the descriptor created by getutxent() is marked as close-on-exec). As a side note, I see that documentation for the hooks interface has never made it into a man page; anyone willing to rectify that? --Ken -- nmh-workers https://lists.nongnu.org/mailman/listinfo/nmh-workers
