[Python-Dev] Set close-on-exec flag by default in SocketServer (original) (raw)

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