153fabd4bSPaolo Bonzini /*
253fabd4bSPaolo Bonzini * systemd socket activation support
353fabd4bSPaolo Bonzini *
453fabd4bSPaolo Bonzini * Copyright 2017 Red Hat, Inc. and/or its affiliates
553fabd4bSPaolo Bonzini *
653fabd4bSPaolo Bonzini * Authors:
753fabd4bSPaolo Bonzini * Richard W.M. Jones <rjones@redhat.com>
853fabd4bSPaolo Bonzini *
953fabd4bSPaolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2 or later.
1053fabd4bSPaolo Bonzini * See the COPYING file in the top-level directory.
1153fabd4bSPaolo Bonzini */
1253fabd4bSPaolo Bonzini
1353fabd4bSPaolo Bonzini #include "qemu/osdep.h"
1453fabd4bSPaolo Bonzini #include "qemu/systemd.h"
1553fabd4bSPaolo Bonzini #include "qemu/cutils.h"
1653fabd4bSPaolo Bonzini #include "qemu/error-report.h"
1753fabd4bSPaolo Bonzini
1853fabd4bSPaolo Bonzini #ifndef _WIN32
check_socket_activation(void)1953fabd4bSPaolo Bonzini unsigned int check_socket_activation(void)
2053fabd4bSPaolo Bonzini {
2153fabd4bSPaolo Bonzini const char *s;
2253fabd4bSPaolo Bonzini unsigned long pid;
2353fabd4bSPaolo Bonzini unsigned long nr_fds;
2453fabd4bSPaolo Bonzini unsigned int i;
2553fabd4bSPaolo Bonzini int fd;
26474a6e64SEric Blake int f;
2753fabd4bSPaolo Bonzini int err;
2853fabd4bSPaolo Bonzini
2953fabd4bSPaolo Bonzini s = getenv("LISTEN_PID");
3053fabd4bSPaolo Bonzini if (s == NULL) {
3153fabd4bSPaolo Bonzini return 0;
3253fabd4bSPaolo Bonzini }
3353fabd4bSPaolo Bonzini err = qemu_strtoul(s, NULL, 10, &pid);
3453fabd4bSPaolo Bonzini if (err) {
3553fabd4bSPaolo Bonzini return 0;
3653fabd4bSPaolo Bonzini }
3753fabd4bSPaolo Bonzini if (pid != getpid()) {
3853fabd4bSPaolo Bonzini return 0;
3953fabd4bSPaolo Bonzini }
4053fabd4bSPaolo Bonzini
4153fabd4bSPaolo Bonzini s = getenv("LISTEN_FDS");
4253fabd4bSPaolo Bonzini if (s == NULL) {
4353fabd4bSPaolo Bonzini return 0;
4453fabd4bSPaolo Bonzini }
4553fabd4bSPaolo Bonzini err = qemu_strtoul(s, NULL, 10, &nr_fds);
4653fabd4bSPaolo Bonzini if (err) {
4753fabd4bSPaolo Bonzini return 0;
4853fabd4bSPaolo Bonzini }
4953fabd4bSPaolo Bonzini assert(nr_fds <= UINT_MAX);
5053fabd4bSPaolo Bonzini
5153fabd4bSPaolo Bonzini /* So these are not passed to any child processes we might start. */
5253fabd4bSPaolo Bonzini unsetenv("LISTEN_FDS");
5353fabd4bSPaolo Bonzini unsetenv("LISTEN_PID");
54*7ade2b18SEric Blake unsetenv("LISTEN_FDNAMES");
5553fabd4bSPaolo Bonzini
5653fabd4bSPaolo Bonzini /* So the file descriptors don't leak into child processes. */
5753fabd4bSPaolo Bonzini for (i = 0; i < nr_fds; ++i) {
5853fabd4bSPaolo Bonzini fd = FIRST_SOCKET_ACTIVATION_FD + i;
59474a6e64SEric Blake f = fcntl(fd, F_GETFD);
60474a6e64SEric Blake if (f == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) {
6153fabd4bSPaolo Bonzini /* If we cannot set FD_CLOEXEC then it probably means the file
6253fabd4bSPaolo Bonzini * descriptor is invalid, so socket activation has gone wrong
6353fabd4bSPaolo Bonzini * and we should exit.
6453fabd4bSPaolo Bonzini */
6553fabd4bSPaolo Bonzini error_report("Socket activation failed: "
66372a87a1SThomas Huth "invalid file descriptor fd = %d: %s",
67372a87a1SThomas Huth fd, g_strerror(errno));
6853fabd4bSPaolo Bonzini exit(EXIT_FAILURE);
6953fabd4bSPaolo Bonzini }
7053fabd4bSPaolo Bonzini }
7153fabd4bSPaolo Bonzini
7253fabd4bSPaolo Bonzini return (unsigned int) nr_fds;
7353fabd4bSPaolo Bonzini }
7453fabd4bSPaolo Bonzini
7553fabd4bSPaolo Bonzini #else /* !_WIN32 */
check_socket_activation(void)7653fabd4bSPaolo Bonzini unsigned int check_socket_activation(void)
7753fabd4bSPaolo Bonzini {
7853fabd4bSPaolo Bonzini return 0;
7953fabd4bSPaolo Bonzini }
8053fabd4bSPaolo Bonzini #endif
81