xref: /qemu/util/systemd.c (revision ab930e80)
1 /*
2  * systemd socket activation support
3  *
4  * Copyright 2017 Red Hat, Inc. and/or its affiliates
5  *
6  * Authors:
7  *  Richard W.M. Jones <rjones@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "qemu/systemd.h"
15 #include "qemu/cutils.h"
16 #include "qemu/error-report.h"
17 
18 #ifndef _WIN32
19 unsigned int check_socket_activation(void)
20 {
21     const char *s;
22     unsigned long pid;
23     unsigned long nr_fds;
24     unsigned int i;
25     int fd;
26     int f;
27     int err;
28 
29     s = getenv("LISTEN_PID");
30     if (s == NULL) {
31         return 0;
32     }
33     err = qemu_strtoul(s, NULL, 10, &pid);
34     if (err) {
35         return 0;
36     }
37     if (pid != getpid()) {
38         return 0;
39     }
40 
41     s = getenv("LISTEN_FDS");
42     if (s == NULL) {
43         return 0;
44     }
45     err = qemu_strtoul(s, NULL, 10, &nr_fds);
46     if (err) {
47         return 0;
48     }
49     assert(nr_fds <= UINT_MAX);
50 
51     /* So these are not passed to any child processes we might start. */
52     unsetenv("LISTEN_FDS");
53     unsetenv("LISTEN_PID");
54     unsetenv("LISTEN_FDNAMES");
55 
56     /* So the file descriptors don't leak into child processes. */
57     for (i = 0; i < nr_fds; ++i) {
58         fd = FIRST_SOCKET_ACTIVATION_FD + i;
59         f = fcntl(fd, F_GETFD);
60         if (f == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) {
61             /* If we cannot set FD_CLOEXEC then it probably means the file
62              * descriptor is invalid, so socket activation has gone wrong
63              * and we should exit.
64              */
65             error_report("Socket activation failed: "
66                          "invalid file descriptor fd = %d: %s",
67                          fd, g_strerror(errno));
68             exit(EXIT_FAILURE);
69         }
70     }
71 
72     return (unsigned int) nr_fds;
73 }
74 
75 #else /* !_WIN32 */
76 unsigned int check_socket_activation(void)
77 {
78     return 0;
79 }
80 #endif
81