[Python-Dev] Set close-on-exec flag by default in SocketServer

Victor Stinner victor.stinner at gmail.com
Wed Jan 9 13:48:49 CET 2013


Hi,

The SocketServer class creates a socket to listen on clients, and a
new socket per client (only for stream server like TCPServer, not for
UDPServer).

Until recently (2011-05-24, issue #5715), the listening socket was not
closed after fork for the ForkingMixIn flavor. This caused two issues:
it's a security leak, and it causes "address already in use" error if
the server is restarted (see the first message of #12107 for an
example with Django).

Our implementation of the XMLRPC server uses fcntl() + FD_CLOEXEC to
fix this issue since long time ago (2005-12-04, #1222790).

IMO it would be safer to always enable close-on-exec flag on all
sockets (listening+clients) *by default*. According to
Charles-François Natali, it will break applications. Ruby made a
similar brave choice one year ago (2011-10-22), not only on sockets
but on all file descriptors:
http://bugs.ruby-lang.org/issues/5041

Developers of Ruby servers relying on inheriting sockets in child
processes have to explicitly disable close-on-exec flag in their
server. Unicorn has been fixed for example.

My question is: would you accept to break backward compatibility (in
Python 3.4) to fix a potential security vulnerability?

If not, an alternative is to add an option, disabled by default, to
enable (or disable) explicitly close-on-exec in Python 3.4, and wait
for 3.5 to enable the option by default. So applications might disable
the flag explicitly in Python 3.4.

I wrote a patch attached to the issue #12107 which adds a flag to
enable or disable close-on-exec, I chose to enable the flag by
default:
http://bugs.python.org/issue12107

--

I'm not sure that close-on-exec flag must be set on the listening
socket *and* on the client sockets. What do you think?

--

It would be nice to be able to set close-on-exec flag directly using
socket.socket() constructor. For example, an optional cloexec
keyword-only argument can be added to socket.socket(family, type, *,
cloexec=False).

Victor


More information about the Python-Dev mailing list