|
|
ad7ee3 |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
ad7ee3 |
From: Victor Toso <victortoso@redhat.com>
|
|
|
ad7ee3 |
Date: Sat, 9 Apr 2016 12:00:08 +0200
|
|
|
ad7ee3 |
Subject: [PATCH] session-info: check for a locked session
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
Each session back-end can return this information to vdagentd when
|
|
|
ad7ee3 |
requested.
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
The agent should use this on situations that should not work when
|
|
|
ad7ee3 |
session is locked such as file-transfer-start which is fixed by this
|
|
|
ad7ee3 |
patch.
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
systemd-login is the only back-end implementing this function at the
|
|
|
ad7ee3 |
moment and I'll address console-kit back-end in a later patch.
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
Also, this patch makes spice-vdagent depend on dbus for getting the
|
|
|
ad7ee3 |
lock information.
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
Resolve: https://bugzilla.redhat.com/show_bug.cgi?id=1323623
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
|
|
|
ad7ee3 |
(cherry picked from commit 364b6bba068bd694d7c4355b6275f88482d9f3f8)
|
|
|
ad7ee3 |
---
|
|
|
ad7ee3 |
configure.ac | 17 ++-----
|
|
|
ad7ee3 |
src/console-kit.c | 7 +++
|
|
|
ad7ee3 |
src/dummy-session-info.c | 5 ++
|
|
|
ad7ee3 |
src/session-info.h | 3 ++
|
|
|
ad7ee3 |
src/systemd-login.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
ad7ee3 |
src/vdagentd.c | 7 +++
|
|
|
ad7ee3 |
6 files changed, 153 insertions(+), 13 deletions(-)
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
diff --git a/configure.ac b/configure.ac
|
|
|
ad7ee3 |
index 9f9d34c..9903ea9 100644
|
|
|
ad7ee3 |
--- a/configure.ac
|
|
|
ad7ee3 |
+++ b/configure.ac
|
|
|
ad7ee3 |
@@ -81,6 +81,7 @@ PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.12])
|
|
|
ad7ee3 |
PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
|
|
|
ad7ee3 |
PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.5])
|
|
|
ad7ee3 |
PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
|
|
|
ad7ee3 |
+PKG_CHECK_MODULES([DBUS], [dbus-1])
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
if test "$with_session_info" = "auto" || test "$with_session_info" = "systemd"; then
|
|
|
ad7ee3 |
PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
|
|
|
ad7ee3 |
@@ -100,19 +101,9 @@ fi
|
|
|
ad7ee3 |
AM_CONDITIONAL(HAVE_LIBSYSTEMD_LOGIN, test x"$have_libsystemd_login" = "xyes")
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
if test "$with_session_info" = "auto" || test "$with_session_info" = "console-kit"; then
|
|
|
ad7ee3 |
- PKG_CHECK_MODULES([DBUS],
|
|
|
ad7ee3 |
- [dbus-1],
|
|
|
ad7ee3 |
- [have_console_kit="yes"],
|
|
|
ad7ee3 |
- [have_console_kit="no"])
|
|
|
ad7ee3 |
- if test x"$have_console_kit" = "xno" && test "$with_session_info" = "console-kit"; then
|
|
|
ad7ee3 |
- AC_MSG_ERROR([console-kit support explicitly requested, but some required packages are not available])
|
|
|
ad7ee3 |
- fi
|
|
|
ad7ee3 |
- if test x"$have_console_kit" = "xyes"; then
|
|
|
ad7ee3 |
- AC_DEFINE([HAVE_CONSOLE_KIT], [1], [If defined, vdagentd will be compiled with ConsoleKit support])
|
|
|
ad7ee3 |
- with_session_info="console-kit"
|
|
|
ad7ee3 |
- else
|
|
|
ad7ee3 |
- with_session_info="none"
|
|
|
ad7ee3 |
- fi
|
|
|
ad7ee3 |
+ AC_DEFINE([HAVE_CONSOLE_KIT], [1], [If defined, vdagentd will be compiled with ConsoleKit support])
|
|
|
ad7ee3 |
+ have_console_kit="yes"
|
|
|
ad7ee3 |
+ with_session_info="console-kit"
|
|
|
ad7ee3 |
else
|
|
|
ad7ee3 |
have_console_kit="no"
|
|
|
ad7ee3 |
fi
|
|
|
ad7ee3 |
diff --git a/src/console-kit.c b/src/console-kit.c
|
|
|
ad7ee3 |
index 759a81e..260fcc7 100644
|
|
|
ad7ee3 |
--- a/src/console-kit.c
|
|
|
ad7ee3 |
+++ b/src/console-kit.c
|
|
|
ad7ee3 |
@@ -352,3 +352,10 @@ static char *console_kit_check_active_session_change(struct session_info *ck)
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
return ck->active_session;
|
|
|
ad7ee3 |
}
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+gboolean session_info_session_is_locked(struct session_info *info)
|
|
|
ad7ee3 |
+{
|
|
|
ad7ee3 |
+ /* TODO: It could be implemented based on Lock/Unlock signals from Session
|
|
|
ad7ee3 |
+ * interface. */
|
|
|
ad7ee3 |
+ return FALSE;
|
|
|
ad7ee3 |
+}
|
|
|
ad7ee3 |
diff --git a/src/dummy-session-info.c b/src/dummy-session-info.c
|
|
|
ad7ee3 |
index e188ddc..c09643b 100644
|
|
|
ad7ee3 |
--- a/src/dummy-session-info.c
|
|
|
ad7ee3 |
+++ b/src/dummy-session-info.c
|
|
|
ad7ee3 |
@@ -44,3 +44,8 @@ char *session_info_session_for_pid(struct session_info *si, uint32_t pid)
|
|
|
ad7ee3 |
{
|
|
|
ad7ee3 |
return NULL;
|
|
|
ad7ee3 |
}
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+gboolean session_is_locked(struct session_info *ck)
|
|
|
ad7ee3 |
+{
|
|
|
ad7ee3 |
+ return FALSE;
|
|
|
ad7ee3 |
+}
|
|
|
ad7ee3 |
diff --git a/src/session-info.h b/src/session-info.h
|
|
|
ad7ee3 |
index 67099de..d660fcf 100644
|
|
|
ad7ee3 |
--- a/src/session-info.h
|
|
|
ad7ee3 |
+++ b/src/session-info.h
|
|
|
ad7ee3 |
@@ -24,6 +24,7 @@
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
#include <stdio.h>
|
|
|
ad7ee3 |
#include <stdint.h>
|
|
|
ad7ee3 |
+#include <glib.h>
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
struct session_info;
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
@@ -36,4 +37,6 @@ const char *session_info_get_active_session(struct session_info *ck);
|
|
|
ad7ee3 |
/* Note result must be free()-ed by caller */
|
|
|
ad7ee3 |
char *session_info_session_for_pid(struct session_info *ck, uint32_t pid);
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
+gboolean session_info_session_is_locked(struct session_info *si);
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
#endif
|
|
|
ad7ee3 |
diff --git a/src/systemd-login.c b/src/systemd-login.c
|
|
|
ad7ee3 |
index 73db37f..4a365c0 100644
|
|
|
ad7ee3 |
--- a/src/systemd-login.c
|
|
|
ad7ee3 |
+++ b/src/systemd-login.c
|
|
|
ad7ee3 |
@@ -25,13 +25,121 @@
|
|
|
ad7ee3 |
#include <string.h>
|
|
|
ad7ee3 |
#include <syslog.h>
|
|
|
ad7ee3 |
#include <systemd/sd-login.h>
|
|
|
ad7ee3 |
+#include <dbus/dbus.h>
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
struct session_info {
|
|
|
ad7ee3 |
int verbose;
|
|
|
ad7ee3 |
sd_login_monitor *mon;
|
|
|
ad7ee3 |
char *session;
|
|
|
ad7ee3 |
+ struct {
|
|
|
ad7ee3 |
+ DBusConnection *system_connection;
|
|
|
ad7ee3 |
+ char *match_session_signals;
|
|
|
ad7ee3 |
+ } dbus;
|
|
|
ad7ee3 |
+ gboolean session_is_locked;
|
|
|
ad7ee3 |
};
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
+#define LOGIND_SESSION_INTERFACE "org.freedesktop.login1.Session"
|
|
|
ad7ee3 |
+#define LOGIND_SESSION_OBJ_TEMPLATE "'/org/freedesktop/login1/session/_3%s'"
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+#define SESSION_SIGNAL_LOCK "Lock"
|
|
|
ad7ee3 |
+#define SESSION_SIGNAL_UNLOCK "Unlock"
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+/* dbus related */
|
|
|
ad7ee3 |
+static DBusConnection *si_dbus_get_system_bus(void)
|
|
|
ad7ee3 |
+{
|
|
|
ad7ee3 |
+ DBusConnection *connection;
|
|
|
ad7ee3 |
+ DBusError error;
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ dbus_error_init(&error);
|
|
|
ad7ee3 |
+ connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
|
|
|
ad7ee3 |
+ if (connection == NULL || dbus_error_is_set(&error)) {
|
|
|
ad7ee3 |
+ if (dbus_error_is_set(&error)) {
|
|
|
ad7ee3 |
+ syslog(LOG_WARNING, "Unable to connect to system bus: %s",
|
|
|
ad7ee3 |
+ error.message);
|
|
|
ad7ee3 |
+ dbus_error_free(&error);
|
|
|
ad7ee3 |
+ } else {
|
|
|
ad7ee3 |
+ syslog(LOG_WARNING, "Unable to connect to system bus");
|
|
|
ad7ee3 |
+ }
|
|
|
ad7ee3 |
+ return NULL;
|
|
|
ad7ee3 |
+ }
|
|
|
ad7ee3 |
+ return connection;
|
|
|
ad7ee3 |
+}
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+static void si_dbus_match_remove(struct session_info *si)
|
|
|
ad7ee3 |
+{
|
|
|
ad7ee3 |
+ DBusError error;
|
|
|
ad7ee3 |
+ if (si->dbus.match_session_signals == NULL)
|
|
|
ad7ee3 |
+ return;
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ dbus_error_init(&error);
|
|
|
ad7ee3 |
+ dbus_bus_remove_match(si->dbus.system_connection,
|
|
|
ad7ee3 |
+ si->dbus.match_session_signals,
|
|
|
ad7ee3 |
+ &error);
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ g_free(si->dbus.match_session_signals);
|
|
|
ad7ee3 |
+ si->dbus.match_session_signals = NULL;
|
|
|
ad7ee3 |
+}
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+static void si_dbus_match_rule_update(struct session_info *si)
|
|
|
ad7ee3 |
+{
|
|
|
ad7ee3 |
+ DBusError error;
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ if (si->dbus.system_connection == NULL ||
|
|
|
ad7ee3 |
+ si->session == NULL)
|
|
|
ad7ee3 |
+ return;
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ si_dbus_match_remove(si);
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ si->dbus.match_session_signals =
|
|
|
ad7ee3 |
+ g_strdup_printf ("type='signal',interface='%s',path="
|
|
|
ad7ee3 |
+ LOGIND_SESSION_OBJ_TEMPLATE,
|
|
|
ad7ee3 |
+ LOGIND_SESSION_INTERFACE,
|
|
|
ad7ee3 |
+ si->session);
|
|
|
ad7ee3 |
+ if (si->verbose)
|
|
|
ad7ee3 |
+ syslog(LOG_DEBUG, "logind match: %s", si->dbus.match_session_signals);
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ dbus_error_init(&error);
|
|
|
ad7ee3 |
+ dbus_bus_add_match(si->dbus.system_connection,
|
|
|
ad7ee3 |
+ si->dbus.match_session_signals,
|
|
|
ad7ee3 |
+ &error);
|
|
|
ad7ee3 |
+ if (dbus_error_is_set(&error)) {
|
|
|
ad7ee3 |
+ syslog(LOG_WARNING, "Unable to add dbus rule match: %s",
|
|
|
ad7ee3 |
+ error.message);
|
|
|
ad7ee3 |
+ dbus_error_free(&error);
|
|
|
ad7ee3 |
+ g_free(si->dbus.match_session_signals);
|
|
|
ad7ee3 |
+ si->dbus.match_session_signals = NULL;
|
|
|
ad7ee3 |
+ }
|
|
|
ad7ee3 |
+}
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+static void
|
|
|
ad7ee3 |
+si_dbus_read_signals(struct session_info *si)
|
|
|
ad7ee3 |
+{
|
|
|
ad7ee3 |
+ DBusMessage *message = NULL;
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ dbus_connection_read_write(si->dbus.system_connection, 0);
|
|
|
ad7ee3 |
+ message = dbus_connection_pop_message(si->dbus.system_connection);
|
|
|
ad7ee3 |
+ while (message != NULL) {
|
|
|
ad7ee3 |
+ const char *member;
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ member = dbus_message_get_member (message);
|
|
|
ad7ee3 |
+ if (g_strcmp0(member, SESSION_SIGNAL_LOCK) == 0) {
|
|
|
ad7ee3 |
+ si->session_is_locked = TRUE;
|
|
|
ad7ee3 |
+ } else if (g_strcmp0(member, SESSION_SIGNAL_UNLOCK) == 0) {
|
|
|
ad7ee3 |
+ si->session_is_locked = FALSE;
|
|
|
ad7ee3 |
+ } else {
|
|
|
ad7ee3 |
+ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
|
|
|
ad7ee3 |
+ syslog(LOG_WARNING, "(systemd-login) received non signal message");
|
|
|
ad7ee3 |
+ } else if (si->verbose) {
|
|
|
ad7ee3 |
+ syslog(LOG_DEBUG, "(systemd-login) Signal not handled: %s", member);
|
|
|
ad7ee3 |
+ }
|
|
|
ad7ee3 |
+ }
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ dbus_message_unref(message);
|
|
|
ad7ee3 |
+ dbus_connection_read_write(si->dbus.system_connection, 0);
|
|
|
ad7ee3 |
+ message = dbus_connection_pop_message(si->dbus.system_connection);
|
|
|
ad7ee3 |
+ }
|
|
|
ad7ee3 |
+}
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
struct session_info *session_info_create(int verbose)
|
|
|
ad7ee3 |
{
|
|
|
ad7ee3 |
struct session_info *si;
|
|
|
ad7ee3 |
@@ -42,6 +150,7 @@ struct session_info *session_info_create(int verbose)
|
|
|
ad7ee3 |
return NULL;
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
si->verbose = verbose;
|
|
|
ad7ee3 |
+ si->session_is_locked = FALSE;
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
r = sd_login_monitor_new("session", &si->mon);
|
|
|
ad7ee3 |
if (r < 0) {
|
|
|
ad7ee3 |
@@ -50,6 +159,7 @@ struct session_info *session_info_create(int verbose)
|
|
|
ad7ee3 |
return NULL;
|
|
|
ad7ee3 |
}
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
+ si->dbus.system_connection = si_dbus_get_system_bus();
|
|
|
ad7ee3 |
return si;
|
|
|
ad7ee3 |
}
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
@@ -58,6 +168,8 @@ void session_info_destroy(struct session_info *si)
|
|
|
ad7ee3 |
if (!si)
|
|
|
ad7ee3 |
return;
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
+ si_dbus_match_remove(si);
|
|
|
ad7ee3 |
+ dbus_connection_close(si->dbus.system_connection);
|
|
|
ad7ee3 |
sd_login_monitor_unref(si->mon);
|
|
|
ad7ee3 |
free(si->session);
|
|
|
ad7ee3 |
free(si);
|
|
|
ad7ee3 |
@@ -87,6 +199,7 @@ const char *session_info_get_active_session(struct session_info *si)
|
|
|
ad7ee3 |
sd_login_monitor_flush(si->mon);
|
|
|
ad7ee3 |
free(old_session);
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
+ si_dbus_match_rule_update(si);
|
|
|
ad7ee3 |
return si->session;
|
|
|
ad7ee3 |
}
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
@@ -104,3 +217,17 @@ char *session_info_session_for_pid(struct session_info *si, uint32_t pid)
|
|
|
ad7ee3 |
|
|
|
ad7ee3 |
return session;
|
|
|
ad7ee3 |
}
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+gboolean session_info_session_is_locked(struct session_info *si)
|
|
|
ad7ee3 |
+{
|
|
|
ad7ee3 |
+ g_return_val_if_fail (si != NULL, FALSE);
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ /* We could also rely on IdleHint property from Session which seems to work
|
|
|
ad7ee3 |
+ * well in rhel7 but it wasn't working well in my own system (F23). I'm
|
|
|
ad7ee3 |
+ * convinced for now that Lock/Unlock signals should be enough but that
|
|
|
ad7ee3 |
+ * means Lock/Unlock being done by logind. That might take a while.
|
|
|
ad7ee3 |
+ * Check: https://bugzilla.gnome.org/show_bug.cgi?id=764773 */
|
|
|
ad7ee3 |
+
|
|
|
ad7ee3 |
+ si_dbus_read_signals(si);
|
|
|
ad7ee3 |
+ return si->session_is_locked;
|
|
|
ad7ee3 |
+}
|
|
|
ad7ee3 |
diff --git a/src/vdagentd.c b/src/vdagentd.c
|
|
|
ad7ee3 |
index 2c8e973..2f77773 100644
|
|
|
ad7ee3 |
--- a/src/vdagentd.c
|
|
|
ad7ee3 |
+++ b/src/vdagentd.c
|
|
|
ad7ee3 |
@@ -276,6 +276,13 @@ static void do_client_file_xfer(struct vdagent_virtio_port *vport,
|
|
|
ad7ee3 |
"active session, cancelling client file-xfer request %u",
|
|
|
ad7ee3 |
s->id, VD_AGENT_FILE_XFER_STATUS_CANCELLED);
|
|
|
ad7ee3 |
return;
|
|
|
ad7ee3 |
+ } else if (session_info_session_is_locked(session_info)) {
|
|
|
ad7ee3 |
+ syslog(LOG_DEBUG, "Session is locked, skipping file-xfer-start");
|
|
|
ad7ee3 |
+ send_file_xfer_status(vport,
|
|
|
ad7ee3 |
+ "User's session is locked and cannot start file transfer. "
|
|
|
ad7ee3 |
+ "Cancelling client file-xfer request %u",
|
|
|
ad7ee3 |
+ s->id, VD_AGENT_FILE_XFER_STATUS_ERROR);
|
|
|
ad7ee3 |
+ return;
|
|
|
ad7ee3 |
}
|
|
|
ad7ee3 |
udscs_write(active_session_conn, VDAGENTD_FILE_XFER_START, 0, 0,
|
|
|
ad7ee3 |
data, message_header->size);
|