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

Charles-François Natali cf.natali at gmail.com
Wed Jan 9 22:15:33 CET 2013


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

Although obvious, the security implications are not restricted to
sockets (yes, it's a contrived example):
"""
# cat test_inherit.py
import fcntl
import os
import pwd
import sys


f = open("/tmp/passwd", 'w+')

#fcntl.fcntl(f.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC)

if os.fork() == 0:
    os.setuid(pwd.getpwnam('nobody').pw_uid)
    os.execv(sys.executable, ['python', '-c', 'import os; os.write(3,
"owned")'])
else:
    os.waitpid(-1, 0)
    f.seek(0)
    print(f.read())
    f.close()
# python test_inherit.py
owned
"""

> 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?

In the listening socket is inherited, it can lead to EADDRINUSE, or
the child process "hijacking" new connections (by accept()ing on the
same socket).
As for the client sockets, there's at least one reason to set them
close-on-exec: if a second forked process inherits the first process'
client socket, even when the first client closes its file descriptor
(and exits), the socket won't be closed until the the second process
exits too: so one long-running child process can delay other child
processes connection shutdown for arbitrarily long.


More information about the Python-Dev mailing list