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