xref: /openbmc/qemu/util/systemd.c (revision 7ade2b18)
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