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

Victor Stinner victor.stinner at gmail.com
Thu Jan 10 01:13:05 CET 2013


2013/1/9 Charles-François Natali <cf.natali at gmail.com>:
>> 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):
> ...
> f = open("/tmp/passwd", 'w+')
> if os.fork() == 0:
>     ...

Do you mean that we should provide a way to enable close-on-exec flag
by default on all file descriptors? Adding an "e" flag to open() mode
is not compatible with this requirement: we would need the opposite
flag to disable explicitly close-on-exec.

A better API is maybe to add a "cloexec" argument to open(),
socket.socket(), pipe(), etc. It's easier to choose the default value
of this argument:
 * False: backward compatible
 * True: backward incompatible
 * value retrieved from a global option, ex: sys.getdefaultcloexec()

So a simple call to "sys.setdefaultcloexec(True)" would make your
program make secure and less error-prone, globally, without having to
break backward compatibility.

Example without setting cloexec globally:
f = open("/tmp/passwd", "w+", cloexec=True)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, cloexec=True)
rfd, wfd = os.pipe(cloexec=True)

--

"os.pipe(cloexec=True)" doesn't respect 1-to-1 "rule" of OS functions
exposed in the Python module "os", because it it may use pipe2() with
O_CLOEXEC internally, whereas os.pipe2() does exist...

... But other Python functions of the os module use a different C
function depending on the option. Examples:
- os.open() uses open(), or openat() if dir_fd is set.
- os.utime() uses utimensat(), utime(), utimes(), futimens(),
futimes(), futimesat(), ...

Victor


More information about the Python-Dev mailing list