[net.bugs.v7] dup/dup2 vs close-on-exec

henry (11/25/82)

Dup() and dup2() are unaware of the u_pofile array, which contains
(at the moment) the close-on-exec flags for the file descriptors.
Dup() always returns a stays-open-on-exec descriptor, since ufalloc()
zeros out the u_pofile slot for the descriptor it returns.  Now comes
the fun part!  Dup2() does not use ufalloc(), so the descriptor it
gives back simply inherits the previous value of the u_pofile entry.
This is lots of fun, because close() does not zero out u_pofile!
Nor does exec()!  Even the code for exec() that does handle u_pofile --
the close-on-exec handling -- gets it wrong:  it clears only the
close-on-exec bit, not the whole word.

All of this would be much more serious if there were more useful bits
in u_pofile.  As it is, it's not surprising that nobody noticed.

The fix should be fairly straightforward, although I have *not*
tested it.  The code in sys3.c that implements dup() and dup2()
should carry the u_pofile contents along with the descriptor when
duplicating it.  I think I would also be inclined to zero out the
u_pofile entry when the descriptor is closed, just in case.