diff --git a/SOURCES/0028-Add-systemd-socket-activation.patch b/SOURCES/0028-Add-systemd-socket-activation.patch new file mode 100644 index 0000000..35c4484 --- /dev/null +++ b/SOURCES/0028-Add-systemd-socket-activation.patch @@ -0,0 +1,368 @@ +From fa2594ee2f73901b729651f7ed31e37d141a0863 Mon Sep 17 00:00:00 2001 +From: Jonathon Jongsma +Date: Fri, 16 Jun 2017 09:46:56 -0500 +Subject: [PATCH linux vdagent] Add systemd socket activation + +If we are configured to use the systemd init script, also add support +for systemd socket activation. systemd will listen on the socket that is +used to communicate between the session agent and the system daemon. +When the session agent connects, the system daemon will automatically be +started. The socket will be enabled only if the required virtio-port +device exists. The socket is disabled when the device is removed. + +This has a couple minor advantages to the previous approach: + - For VMS that are not running a graphical desktop (and thus no + session agents are running), the system vdagent daemon won't get + started at all even if the spice virtio port is configured. Only the + socket will be enabled. In the previous approach, the system daemon + was started when the virtio device was added regardless of whether + it was needed or not. + - Solves issues related to switching between systemd targets. With the + previous approach, when a user switches to a different target + ("systemctl isolate multi-user.target"), spice-vdagentd.target was + stopped by systemd (since "isolate" by definition stops all targets + except the one specified). This meant that if the user subsequently + switched back to graphical.target, the spice-vdagentd.target would + still be disabled and vdagent functionality would not work. With + this change, the socket will still be listening after switching to a + different target, so as soon as a session agent tries to connect to + the socket, the system daemon will get restarted. + +Fixes: rhbz#1340160 + +Signed-off-by: Jonathon Jongsma +Acked-by: Victor Toso +--- + Makefile.am | 8 +++---- + configure.ac | 8 +++++++ + data/70-spice-vdagentd.rules | 2 +- + data/spice-vdagentd.service | 8 +++---- + data/spice-vdagentd.socket | 10 ++++++++ + data/spice-vdagentd.target | 2 -- + src/udscs.c | 45 ++++++++++++++++++++++++------------ + src/udscs.h | 12 +++++++++- + src/vdagentd.c | 54 +++++++++++++++++++++++++++++++++++--------- + 9 files changed, 110 insertions(+), 39 deletions(-) + create mode 100644 data/spice-vdagentd.socket + delete mode 100644 data/spice-vdagentd.target + +diff --git a/Makefile.am b/Makefile.am +index 2effe4e..3ba7692 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -14,9 +14,9 @@ src_spice_vdagent_SOURCES = src/vdagent.c \ + src/udscs.c + + src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) \ +- $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(PIE_CFLAGS) ++ $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(PIE_CFLAGS) $(LIBSYSTEMD_DAEMON_CFLAGS) + src_spice_vdagentd_LDADD = $(DBUS_LIBS) $(LIBSYSTEMD_LOGIN_LIBS) \ +- $(PCIACCESS_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(PIE_LDFLAGS) ++ $(PCIACCESS_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(PIE_LDFLAGS) $(LIBSYSTEMD_DAEMON_LIBS) + src_spice_vdagentd_SOURCES = src/vdagentd.c \ + src/vdagentd-uinput.c \ + src/vdagentd-xorg-conf.c \ +@@ -66,7 +66,7 @@ if INIT_SCRIPT_SYSTEMD + systemdunitdir = $(SYSTEMDSYSTEMUNITDIR) + systemdunit_DATA = \ + $(top_srcdir)/data/spice-vdagentd.service \ +- $(top_srcdir)/data/spice-vdagentd.target ++ $(top_srcdir)/data/spice-vdagentd.socket + + udevrulesdir = /lib/udev/rules.d + udevrules_DATA = $(top_srcdir)/data/70-spice-vdagentd.rules +@@ -89,7 +89,7 @@ EXTRA_DIST = \ + data/spice-vdagent.desktop \ + data/spice-vdagentd \ + data/spice-vdagentd.service \ +- data/spice-vdagentd.target \ ++ data/spice-vdagentd.socket \ + data/tmpfiles.d/spice-vdagentd.conf \ + data/xorg.conf.RHEL-5 \ + $(NULL) +diff --git a/configure.ac b/configure.ac +index 9903ea9..3ce2208 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -65,6 +65,14 @@ AC_MSG_RESULT($with_init_script) + if test "x$init_systemd" = "xyes"; then + SYSTEMDSYSTEMUNITDIR=`${PKG_CONFIG} systemd --variable=systemdsystemunitdir` + AC_SUBST(SYSTEMDSYSTEMUNITDIR) ++ # earlier versions of systemd require a separate libsystemd-daemon library ++ PKG_CHECK_MODULES([LIBSYSTEMD_DAEMON], ++ [libsystemd >= 209], ++ [have_libsystemd_daemon="yes"], ++ [have_libsystemd_daemon="no"]) ++ if test "$have_libsystemd_daemon" = "yes"; then ++ AC_DEFINE([WITH_SYSTEMD_SOCKET_ACTIVATION], [1], [If defined, vdagentd will support socket activation with systemd] ) ++ fi + fi + + AC_ARG_ENABLE([pciaccess], +diff --git a/data/70-spice-vdagentd.rules b/data/70-spice-vdagentd.rules +index a1785ba..64b4166 100644 +--- a/data/70-spice-vdagentd.rules ++++ b/data/70-spice-vdagentd.rules +@@ -1 +1 @@ +-ACTION=="add", SUBSYSTEM=="virtio-ports", ENV{DEVLINKS}=="/dev/virtio-ports/com.redhat.spice.0", ENV{SYSTEMD_WANTS}="spice-vdagentd.target" ++ACTION=="add", SUBSYSTEM=="virtio-ports", ENV{DEVLINKS}=="/dev/virtio-ports/com.redhat.spice.0", ENV{SYSTEMD_WANTS}="spice-vdagentd.socket" +diff --git a/data/spice-vdagentd.service b/data/spice-vdagentd.service +index 8c5effe..365b2c1 100644 +--- a/data/spice-vdagentd.service ++++ b/data/spice-vdagentd.service +@@ -1,17 +1,15 @@ + [Unit] + Description=Agent daemon for Spice guests + After=dbus.target +- +-# TODO we should use: +-#Requires=spice-vdagentd.socket ++Requires=spice-vdagentd.socket + + [Service] + Type=forking + EnvironmentFile=-/etc/sysconfig/spice-vdagentd +-ExecStartPre=/bin/rm -f /var/run/spice-vdagentd/spice-vdagent-sock + ExecStart=/usr/sbin/spice-vdagentd $SPICE_VDAGENTD_EXTRA_ARGS + PIDFile=/var/run/spice-vdagentd/spice-vdagentd.pid + PrivateTmp=true ++Restart=on-failure + + [Install] +-WantedBy=spice-vdagentd.target ++Also=spice-vdagentd.socket +diff --git a/data/spice-vdagentd.socket b/data/spice-vdagentd.socket +new file mode 100644 +index 0000000..e34a188 +--- /dev/null ++++ b/data/spice-vdagentd.socket +@@ -0,0 +1,10 @@ ++[Unit] ++Description=Activation socket for spice guest agent daemon ++# only start the socket if the virtio port device exists ++Requisite=dev-virtio\x2dports-com.redhat.spice.0.device ++ ++[Socket] ++ListenStream=/var/run/spice-vdagentd/spice-vdagent-sock ++ ++[Install] ++WantedBy=sockets.target +diff --git a/data/spice-vdagentd.target b/data/spice-vdagentd.target +deleted file mode 100644 +index 1f74931..0000000 +--- a/data/spice-vdagentd.target ++++ /dev/null +@@ -1,2 +0,0 @@ +-[Unit] +-Description=Agent daemon for Spice guests +diff --git a/src/udscs.c b/src/udscs.c +index 288aca2..f04a31c 100644 +--- a/src/udscs.c ++++ b/src/udscs.c +@@ -81,52 +81,67 @@ static void udscs_do_write(struct udscs_connection **connp); + static void udscs_do_read(struct udscs_connection **connp); + + +-struct udscs_server *udscs_create_server(const char *socketname, ++struct udscs_server *udscs_create_server_for_fd(int fd, + udscs_connect_callback connect_callback, + udscs_read_callback read_callback, + udscs_disconnect_callback disconnect_callback, + const char * const type_to_string[], int no_types, int debug) + { +- int c; +- struct sockaddr_un address; + struct udscs_server *server; + + server = calloc(1, sizeof(*server)); + if (!server) + return NULL; + ++ if (fd <= 0) { ++ syslog(LOG_ERR, "Invalid file descriptor: %i", fd); ++ return NULL; ++ } ++ + server->type_to_string = type_to_string; + server->no_types = no_types; + server->debug = debug; ++ server->fd = fd; ++ server->connect_callback = connect_callback; ++ server->read_callback = read_callback; ++ server->disconnect_callback = disconnect_callback; ++ ++ return server; ++} ++ ++struct udscs_server *udscs_create_server(const char *socketname, ++ udscs_connect_callback connect_callback, ++ udscs_read_callback read_callback, ++ udscs_disconnect_callback disconnect_callback, ++ const char * const type_to_string[], int no_types, int debug) ++{ ++ int c; ++ int fd; ++ struct sockaddr_un address; + +- server->fd = socket(PF_UNIX, SOCK_STREAM, 0); +- if (server->fd == -1) { ++ fd = socket(PF_UNIX, SOCK_STREAM, 0); ++ if (fd == -1) { + syslog(LOG_ERR, "creating unix domain socket: %m"); +- free(server); + return NULL; + } + + address.sun_family = AF_UNIX; + snprintf(address.sun_path, sizeof(address.sun_path), "%s", socketname); +- c = bind(server->fd, (struct sockaddr *)&address, sizeof(address)); ++ c = bind(fd, (struct sockaddr *)&address, sizeof(address)); + if (c != 0) { + syslog(LOG_ERR, "bind %s: %m", socketname); +- free(server); + return NULL; + } + +- c = listen(server->fd, 5); ++ c = listen(fd, 5); + if (c != 0) { + syslog(LOG_ERR, "listen: %m"); +- free(server); + return NULL; + } + +- server->connect_callback = connect_callback; +- server->read_callback = read_callback; +- server->disconnect_callback = disconnect_callback; +- +- return server; ++ return udscs_create_server_for_fd(fd, connect_callback, read_callback, ++ disconnect_callback, type_to_string, ++ no_types, debug); + } + + void udscs_destroy_server(struct udscs_server *server) +diff --git a/src/udscs.h b/src/udscs.h +index 89ab617..cb67059 100644 +--- a/src/udscs.h ++++ b/src/udscs.h +@@ -57,6 +57,17 @@ typedef int (*udscs_for_all_clients_callback)(struct udscs_connection **connp, + by explictly calling udscs_destroy_connection */ + typedef void (*udscs_disconnect_callback)(struct udscs_connection *conn); + ++/* Create a server for the given file descriptor. This allows us to use ++ * pre-configured sockets for use with systemd socket activation, etc. ++ * ++ * See udscs_create_server() for more information ++ */ ++struct udscs_server *udscs_create_server_for_fd(int fd, ++ udscs_connect_callback connect_callback, ++ udscs_read_callback read_callback, ++ udscs_disconnect_callback disconnect_callback, ++ const char * const type_to_string[], int no_types, int debug); ++ + /* Create a unix domain socket named name and start listening on it. */ + struct udscs_server *udscs_create_server(const char *socketname, + udscs_connect_callback connect_callback, +@@ -98,7 +109,6 @@ void udscs_client_handle_fds(struct udscs_connection **connp, fd_set *readfds, + + + /* Queue a message for delivery to the client connected through conn. +- + Returns 0 on success -1 on error (only happens when malloc fails) */ + int udscs_write(struct udscs_connection *conn, uint32_t type, uint32_t arg1, + uint32_t arg2, const uint8_t *data, uint32_t size); +diff --git a/src/vdagentd.c b/src/vdagentd.c +index 59ea8da..d5cc33b 100644 +--- a/src/vdagentd.c ++++ b/src/vdagentd.c +@@ -36,6 +36,10 @@ + #include + #include + ++#ifdef WITH_SYSTEMD_SOCKET_ACTIVATION ++#include ++#endif /* WITH_SYSTEMD_SOCKET_ACTIVATION */ ++ + #include "udscs.h" + #include "vdagentd-proto.h" + #include "vdagentd-proto-strings.h" +@@ -873,6 +877,7 @@ int main(int argc, char *argv[]) + int do_daemonize = 1; + int want_session_info = 1; + struct sigaction act; ++ gboolean own_socket = TRUE; + + for (;;) { + if (-1 == (c = getopt(argc, argv, "-dhxXs:u:"))) +@@ -914,20 +919,43 @@ int main(int argc, char *argv[]) + openlog("spice-vdagentd", do_daemonize ? 0 : LOG_PERROR, LOG_USER); + + /* Setup communication with vdagent process(es) */ +- server = udscs_create_server(VDAGENTD_SOCKET, agent_connect, +- agent_read_complete, agent_disconnect, +- vdagentd_messages, VDAGENTD_NO_MESSAGES, +- debug); ++#ifdef WITH_SYSTEMD_SOCKET_ACTIVATION ++ int n_fds; ++ /* try to retrieve pre-configured sockets from systemd */ ++ n_fds = sd_listen_fds(0); ++ if (n_fds > 1) { ++ syslog(LOG_CRIT, "Received too many sockets from systemd (%i)", n_fds); ++ return 1; ++ } else if (n_fds == 1) { ++ server = udscs_create_server_for_fd(SD_LISTEN_FDS_START, agent_connect, ++ agent_read_complete, ++ agent_disconnect, ++ vdagentd_messages, ++ VDAGENTD_NO_MESSAGES, debug); ++ own_socket = FALSE; ++ } else ++ /* systemd socket activation not enabled, create our own */ ++#endif /* WITH_SYSTEMD_SOCKET_ACTIVATION */ ++ { ++ server = udscs_create_server(VDAGENTD_SOCKET, agent_connect, ++ agent_read_complete, agent_disconnect, ++ vdagentd_messages, VDAGENTD_NO_MESSAGES, ++ debug); ++ } ++ + if (!server) { + syslog(LOG_CRIT, "Fatal could not create server socket %s", + VDAGENTD_SOCKET); + return 1; + } +- if (chmod(VDAGENTD_SOCKET, 0666)) { +- syslog(LOG_CRIT, "Fatal could not change permissions on %s: %m", +- VDAGENTD_SOCKET); +- udscs_destroy_server(server); +- return 1; ++ /* no need to set permissions on a socket that was provided by systemd */ ++ if (own_socket) { ++ if (chmod(VDAGENTD_SOCKET, 0666)) { ++ syslog(LOG_CRIT, "Fatal could not change permissions on %s: %m", ++ VDAGENTD_SOCKET); ++ udscs_destroy_server(server); ++ return 1; ++ } + } + + if (do_daemonize) +@@ -957,8 +985,12 @@ int main(int argc, char *argv[]) + vdagent_virtio_port_destroy(&virtio_port); + session_info_destroy(session_info); + udscs_destroy_server(server); +- if (unlink(VDAGENTD_SOCKET) != 0) +- syslog(LOG_ERR, "unlink %s: %s", VDAGENTD_SOCKET, strerror(errno)); ++ ++ /* leave the socket around if it was provided by systemd */ ++ if (own_socket) { ++ if (unlink(VDAGENTD_SOCKET) != 0) ++ syslog(LOG_ERR, "unlink %s: %s", VDAGENTD_SOCKET, strerror(errno)); ++ } + syslog(LOG_INFO, "vdagentd quiting, returning status %d", retval); + + if (do_daemonize) +-- +2.13.6 + diff --git a/SPECS/spice-vdagent.spec b/SPECS/spice-vdagent.spec index 576ce71..251106e 100644 --- a/SPECS/spice-vdagent.spec +++ b/SPECS/spice-vdagent.spec @@ -1,6 +1,6 @@ Name: spice-vdagent Version: 0.14.0 -Release: 14%{?dist} +Release: 15%{?dist} Summary: Agent for Spice guests Group: Applications/System License: GPLv3+ @@ -37,6 +37,7 @@ Patch24: 0024-vdagentd-send-file-xfer-status-generic-version.patch Patch25: 0025-session-info-check-for-a-locked-session.patch Patch26: 0026-session-info-check-if-session-belongs-to-user.patch Patch27: 0027-systemd-login-check-for-LockedHint-property.patch +Patch28: 0028-Add-systemd-socket-activation.patch BuildRequires: systemd-devel glib2-devel spice-protocol >= 0.12.6 BuildRequires: libpciaccess-devel libXrandr-devel libXinerama-devel BuildRequires: libXfixes-devel systemd-units desktop-file-utils libtool @@ -87,6 +88,7 @@ Features: %patch25 -p1 %patch26 -p1 %patch27 -p1 +%patch28 -p1 autoreconf -fi @@ -102,20 +104,20 @@ rm $RPM_BUILD_ROOT%{_sysconfdir}/modules-load.d/spice-vdagentd.conf %post -%systemd_post spice-vdagentd.service +%systemd_post spice-vdagentd.service spice-vdagentd.socket %preun -%systemd_preun spice-vdagentd.service +%systemd_preun spice-vdagentd.service spice-vdagentd.socket %postun -%systemd_postun_with_restart spice-vdagentd.service +%systemd_postun_with_restart spice-vdagentd.service spice-vdagentd.socket %files %doc COPYING ChangeLog README TODO /lib/udev/rules.d/70-spice-vdagentd.rules %{_unitdir}/spice-vdagentd.service -%{_unitdir}/spice-vdagentd.target +%{_unitdir}/spice-vdagentd.socket %{_prefix}/lib/tmpfiles.d/spice-vdagentd.conf %{_bindir}/spice-vdagent %{_sbindir}/spice-vdagentd @@ -128,6 +130,10 @@ rm $RPM_BUILD_ROOT%{_sysconfdir}/modules-load.d/spice-vdagentd.conf %changelog +* Fri Nov 17 2017 Jonathon Jongsma - 0.14.0-15 +- Add systemd socket activation + Resolves: rhbz#1340160 + * Fri Jul 8 2016 Victor Toso - 0.14.0-14 - Do not allow drag-and-drop on (gdm) login screen Resolves: rhbz#1328761