diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2017-03-16 16:29:45 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-03-19 11:12:12 +0100 |
commit | 53fabd4b86e15869e13fb762686d674c64294385 (patch) | |
tree | 8ffb29b28fd121ab3d695e6e89cdd3bef9a6df4b /qemu-nbd.c | |
parent | ebedf0f9cd46b617df331eecc857c379d574ac62 (diff) |
qemu-ga: obey LISTEN_PID when using systemd socket activation
qemu-ga's socket activation support was not obeying the LISTEN_PID
environment variable, which avoids that a process uses a socket-activation
file descriptor meant for its parent.
Mess can for example ensue if a process forks a children before consuming
the socket-activation file descriptor and therefore setting O_CLOEXEC
on it.
Luckily, qemu-nbd also got socket activation code, and its copy does
support LISTEN_PID. Some extra fixups are needed to ensure that the
code can be used for both, but that's what this patch does. The
main change is to replace get_listen_fds's "consume" argument with
the FIRST_SOCKET_ACTIVATION_FD macro from the qemu-nbd code.
Cc: "Richard W.M. Jones" <rjones@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'qemu-nbd.c')
-rw-r--r-- | qemu-nbd.c | 100 |
1 files changed, 8 insertions, 92 deletions
diff --git a/qemu-nbd.c b/qemu-nbd.c index e4fede641e..e080fb7c75 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -28,6 +28,7 @@ #include "qemu/config-file.h" #include "qemu/bswap.h" #include "qemu/log.h" +#include "qemu/systemd.h" #include "block/snapshot.h" #include "qapi/util.h" #include "qapi/qmp/qstring.h" @@ -474,98 +475,6 @@ static void setup_address_and_port(const char **address, const char **port) } } -#define FIRST_SOCKET_ACTIVATION_FD 3 /* defined by systemd ABI */ - -#ifndef _WIN32 -/* - * Check if socket activation was requested via use of the - * LISTEN_FDS and LISTEN_PID environment variables. - * - * Returns 0 if no socket activation, or the number of FDs. - */ -static unsigned int check_socket_activation(void) -{ - const char *s; - unsigned long pid; - unsigned long nr_fds; - unsigned int i; - int fd; - int err; - - s = getenv("LISTEN_PID"); - if (s == NULL) { - return 0; - } - err = qemu_strtoul(s, NULL, 10, &pid); - if (err) { - if (verbose) { - fprintf(stderr, "malformed %s environment variable (ignored)\n", - "LISTEN_PID"); - } - return 0; - } - if (pid != getpid()) { - if (verbose) { - fprintf(stderr, "%s was not for us (ignored)\n", - "LISTEN_PID"); - } - return 0; - } - - s = getenv("LISTEN_FDS"); - if (s == NULL) { - return 0; - } - err = qemu_strtoul(s, NULL, 10, &nr_fds); - if (err) { - if (verbose) { - fprintf(stderr, "malformed %s environment variable (ignored)\n", - "LISTEN_FDS"); - } - return 0; - } - assert(nr_fds <= UINT_MAX); - - /* A limitation of current qemu-nbd is that it can only listen on - * a single socket. When that limitation is lifted, we can change - * this function to allow LISTEN_FDS > 1, and remove the assertion - * in the main function below. - */ - if (nr_fds > 1) { - error_report("qemu-nbd does not support socket activation with %s > 1", - "LISTEN_FDS"); - exit(EXIT_FAILURE); - } - - /* So these are not passed to any child processes we might start. */ - unsetenv("LISTEN_FDS"); - unsetenv("LISTEN_PID"); - - /* So the file descriptors don't leak into child processes. */ - for (i = 0; i < nr_fds; ++i) { - fd = FIRST_SOCKET_ACTIVATION_FD + i; - if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { - /* If we cannot set FD_CLOEXEC then it probably means the file - * descriptor is invalid, so socket activation has gone wrong - * and we should exit. - */ - error_report("Socket activation failed: " - "invalid file descriptor fd = %d: %m", - fd); - exit(EXIT_FAILURE); - } - } - - return (unsigned int) nr_fds; -} - -#else /* !_WIN32 */ -static unsigned int check_socket_activation(void) -{ - return 0; -} -#endif - /* * Check socket parameters compatibility when socket activation is used. */ @@ -892,6 +801,13 @@ int main(int argc, char **argv) error_report("%s", err_msg); exit(EXIT_FAILURE); } + + /* qemu-nbd can only listen on a single socket. */ + if (socket_activation > 1) { + error_report("qemu-nbd does not support socket activation with %s > 1", + "LISTEN_FDS"); + exit(EXIT_FAILURE); + } } if (tlscredsid) { |