Commit 6e06de4e authored by Apollon Oikonomopoulos's avatar Apollon Oikonomopoulos Committed by Helga Velroyen

ganeti.daemon: fix daemon mode with GnuTLS >= 3.3

Newer GnuTLS versions (>= 3.3.0) use a library constructor for
initialization and open /dev/urandom on library load, way before we
fork(). Closing /dev/urandom on fork causes a failure to re-seed GnuTLS's
random number generator during the first ganeti.http.client request, which
in turn causes the process to silently abort(3).

For more background on this behavior, see this thread at the GnuTLS
mailing list:

http://lists.gnupg.org/pipermail/gnutls-help/2014-April/003429.html

Note that calling pycurl.global_init() at the correct place (as we do) is not
enough, as it does not cause a re-initialization of the GnuTLS library.

As we cannot reliably detect neither the GnuTLS version, nor the socket, we
work our way around this by keeping all fds referring to /dev/urandom open
after fork. We do so using the /proc/self/fd interface.

This fixes issues #961 and #964.

Note that this would not affect the Haskell daemons using cURL + GnuTLS,
because we don't close all file descriptors on fork there.
Signed-off-by: default avatarApollon Oikonomopoulos <apoikos@gmail.com>
Reviewed-by: default avatarHelga Velroyen <helgav@google.com>
parent a8f2733b
......@@ -810,7 +810,23 @@ def GenericMain(daemon_name, optionparser,
log_filename = constants.DAEMONS_LOGFILES[daemon_name]
if options.fork:
utils.CloseFDs()
# Newer GnuTLS versions (>= 3.3.0) use a library constructor for
# initialization and open /dev/urandom on library load time, way before we
# fork(). Closing /dev/urandom causes subsequent ganeti.http.client
# requests to fail and the process to receive a SIGABRT. As we cannot
# reliably detect GnuTLS's socket, we work our way around this by keeping
# all fds referring to /dev/urandom open.
noclose_fds = []
for fd in os.listdir("/proc/self/fd"):
try:
if os.readlink(os.path.join("/proc/self/fd", fd)) == "/dev/urandom":
noclose_fds.append(int(fd))
except EnvironmentError:
# The fd might have disappeared (although it shouldn't as we're running
# single-threaded).
continue
utils.CloseFDs(noclose_fds=noclose_fds)
(wpipe, stdio_reopen_fn) = utils.Daemonize(logfile=log_filename)
else:
(wpipe, stdio_reopen_fn) = (None, None)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment