xref: /qemu/util/systemd.c (revision a81df1b6)
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 
55     /* So the file descriptors don't leak into child processes. */
56     for (i = 0; i < nr_fds; ++i) {
57         fd = FIRST_SOCKET_ACTIVATION_FD + i;
58         f = fcntl(fd, F_GETFD);
59         if (f == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) {
60             /* If we cannot set FD_CLOEXEC then it probably means the file
61              * descriptor is invalid, so socket activation has gone wrong
62              * and we should exit.
63              */
64             error_report("Socket activation failed: "
65                          "invalid file descriptor fd = %d: %s",
66                          fd, g_strerror(errno));
67             exit(EXIT_FAILURE);
68         }
69     }
70 
71     return (unsigned int) nr_fds;
72 }
73 
74 #else /* !_WIN32 */
75 unsigned int check_socket_activation(void)
76 {
77     return 0;
78 }
79 #endif
80