xref: /openbmc/qemu/util/systemd.c (revision 4b9fa0b4)
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 err;
27 
28     s = getenv("LISTEN_PID");
29     if (s == NULL) {
30         return 0;
31     }
32     err = qemu_strtoul(s, NULL, 10, &pid);
33     if (err) {
34         return 0;
35     }
36     if (pid != getpid()) {
37         return 0;
38     }
39 
40     s = getenv("LISTEN_FDS");
41     if (s == NULL) {
42         return 0;
43     }
44     err = qemu_strtoul(s, NULL, 10, &nr_fds);
45     if (err) {
46         return 0;
47     }
48     assert(nr_fds <= UINT_MAX);
49 
50     /* So these are not passed to any child processes we might start. */
51     unsetenv("LISTEN_FDS");
52     unsetenv("LISTEN_PID");
53 
54     /* So the file descriptors don't leak into child processes. */
55     for (i = 0; i < nr_fds; ++i) {
56         fd = FIRST_SOCKET_ACTIVATION_FD + i;
57         if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
58             /* If we cannot set FD_CLOEXEC then it probably means the file
59              * descriptor is invalid, so socket activation has gone wrong
60              * and we should exit.
61              */
62             error_report("Socket activation failed: "
63                          "invalid file descriptor fd = %d: %s",
64                          fd, g_strerror(errno));
65             exit(EXIT_FAILURE);
66         }
67     }
68 
69     return (unsigned int) nr_fds;
70 }
71 
72 #else /* !_WIN32 */
73 unsigned int check_socket_activation(void)
74 {
75     return 0;
76 }
77 #endif
78