[Spice-devel] [vdagent-linux v2 1/5] session-info: check for a locked session
Victor Toso
victortoso at redhat.com
Thu Apr 28 12:10:32 UTC 2016
On Wed, Apr 27, 2016 at 04:19:34PM -0500, Jonathon Jongsma wrote:
> On Sat, 2016-04-23 at 12:53 +0200, Victor Toso wrote:
> > Each session back-end can return this information to vdagentd when requested.
> >
> > The agent should use this on situations that should not work when session is
> > locked such as file-transfer-start which is fixed by this patch.
> >
> > systemd-login is the only back-end implementing this function at the moment
> > and
> > I'll address console-kit back-end in a later patch.
> >
> > Also, this patch makes spice-vdagent depend on dbus for getting the lock
> > information.
> >
> > Resolve: https://bugzilla.redhat.com/show_bug.cgi?id=1323623
> > ---
> > configure.ac | 1 +
> > src/console-kit.c | 7 +++
> > src/dummy-session-info.c | 5 ++
> > src/session-info.h | 3 ++
> > src/systemd-login.c | 128
> > +++++++++++++++++++++++++++++++++++++++++++++++
> > src/vdagentd.c | 7 +++
> > 6 files changed, 151 insertions(+)
> >
> > diff --git a/configure.ac b/configure.ac
> > index 2fe685b..aa2ef9f 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -81,6 +81,7 @@ PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.28])
> > PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
> > PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.8])
> > PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
> > +PKG_CHECK_MODULES([DBUS], [dbus-1])
>
> If you're adding a hard dbus requirement here, we could remove the conditional
> requirement from the console-kit section of configure.ac.
Squashed the next patch into this one.
> That said, it's kind of a shame to use libdbus for new code. Perhaps
> we could keep using libdbus for the consolekit / rhel6 code and bump
> the glib requirement for the systemd backend and use gdbus there?
I think we would need to have glib mainloop in the agent in order to
rely on gdbus. I'm in favour of it but I think we could do it later on,
after some more clean up in the agent code.
This work/cleanup could be done in order to have gtk integration in the
agent. If that seems reasonable we can discuss the best way to do it.
Marc-André has started a 'vdagent-gtk' branch with a lot of interesting
changes [0] but it's been a while since I've read it.
[0] https://github.com/elmarco/vdagent-gtk
>
> >
> > if test "$with_session_info" = "auto" || test "$with_session_info" =
> > "systemd"; then
> > PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
> > diff --git a/src/console-kit.c b/src/console-kit.c
> > index f3c4aa3..9662d3d 100644
> > --- a/src/console-kit.c
> > +++ b/src/console-kit.c
> > @@ -416,3 +416,10 @@ static char
> > *console_kit_check_active_session_change(struct session_info *si)
> >
> > return si->active_session;
> > }
> > +
> > +gboolean session_info_session_is_locked(struct session_info *si)
> > +{
> > + /* TODO: It could be implemented based on Lock/Unlock signals from
> > Session
> > + * interface. */
> > + return FALSE;
> > +}
> > diff --git a/src/dummy-session-info.c b/src/dummy-session-info.c
> > index 2f0ae65..e7a716f 100644
> > --- a/src/dummy-session-info.c
> > +++ b/src/dummy-session-info.c
> > @@ -44,3 +44,8 @@ char *session_info_session_for_pid(struct session_info *si,
> > uint32_t pid)
> > {
> > return NULL;
> > }
> > +
> > +gboolean session_is_locked(struct session_info *ck)
> > +{
> > + return FALSE;
> > +}
> > diff --git a/src/session-info.h b/src/session-info.h
> > index c4f8187..f395dbf 100644
> > --- a/src/session-info.h
> > +++ b/src/session-info.h
> > @@ -24,6 +24,7 @@
> >
> > #include <stdio.h>
> > #include <stdint.h>
> > +#include <glib.h>
> >
> > struct session_info;
> >
> > @@ -36,4 +37,6 @@ const char *session_info_get_active_session(struct
> > session_info *ck);
> > /* Note result must be free()-ed by caller */
> > char *session_info_session_for_pid(struct session_info *ck, uint32_t pid);
> >
> > +gboolean session_info_session_is_locked(struct session_info *si);
> > +
> > #endif
> > diff --git a/src/systemd-login.c b/src/systemd-login.c
> > index 9ba300a..470a9ff 100644
> > --- a/src/systemd-login.c
> > +++ b/src/systemd-login.c
> > @@ -25,13 +25,121 @@
> > #include <string.h>
> > #include <syslog.h>
> > #include <systemd/sd-login.h>
> > +#include <dbus/dbus.h>
> >
> > struct session_info {
> > int verbose;
> > sd_login_monitor *mon;
> > char *session;
> > + struct {
> > + DBusConnection *system_connection;
> > + char *match_session_signals;
> > + } dbus;
> > + gboolean session_is_locked;
> > };
> >
> > +#define LOGIND_SESSION_INTERFACE "org.freedesktop.login1.Session"
> > +#define LOGIND_SESSION_OBJ_TEMPLATE "'/org/freedesktop/login1/session/_3%s'"
> > +
> > +#define SESSION_SIGNAL_LOCK "Lock"
> > +#define SESSION_SIGNAL_UNLOCK "Unlock"
> > +
> > +/* dbus related */
> > +static DBusConnection *si_dbus_get_system_bus(void)
> > +{
> > + DBusConnection *connection;
> > + DBusError error;
> > +
> > + dbus_error_init(&error);
> > + connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
> > + if (connection == NULL || dbus_error_is_set(&error)) {
> > + if (dbus_error_is_set(&error)) {
> > + syslog(LOG_WARNING, "Unable to connect to system bus: %s",
> > + error.message);
> > + dbus_error_free(&error);
> > + } else {
> > + syslog(LOG_WARNING, "Unable to connect to system bus");
> > + }
> > + return NULL;
> > + }
> > + return connection;
> > +}
> > +
> > +static void si_dbus_match_remove(struct session_info *si)
> > +{
> > + DBusError error;
> > + if (si->dbus.match_session_signals == NULL)
> > + return;
> > +
> > + dbus_error_init(&error);
> > + dbus_bus_remove_match(si->dbus.system_connection,
> > + si->dbus.match_session_signals,
> > + &error);
> > +
> > + g_free(si->dbus.match_session_signals);
> > +}
> > +
> > +static void si_dbus_match_rule_update(struct session_info *si)
> > +{
> > + DBusError error;
> > +
> > + if (si->dbus.system_connection == NULL ||
> > + si->session == NULL)
> > + return;
> > +
> > + si_dbus_match_remove(si);
> > +
> > + si->dbus.match_session_signals =
> > + g_strdup_printf ("type='signal',interface='%s',path="
> > + LOGIND_SESSION_OBJ_TEMPLATE,
> > + LOGIND_SESSION_INTERFACE,
> > + si->session);
> > + if (si->verbose)
> > + syslog(LOG_DEBUG, "logind match: %s", si
> > ->dbus.match_session_signals);
> > +
> > + dbus_error_init(&error);
> > + dbus_bus_add_match(si->dbus.system_connection,
> > + si->dbus.match_session_signals,
> > + &error);
> > + if (dbus_error_is_set(&error)) {
> > + syslog(LOG_WARNING, "Unable to add dbus rule match: %s",
> > + error.message);
> > + dbus_error_free(&error);
> > + g_free(si->dbus.match_session_signals);
> > + }
> > +}
> > +
> > +static void
> > +si_dbus_read_signals(struct session_info *si)
> > +{
> > + DBusMessage *message = NULL;
> > +
> > + dbus_connection_read_write(si->dbus.system_connection, 0);
> > + message = dbus_connection_pop_message(si->dbus.system_connection);
> > + while (message != NULL) {
> > + const char *member;
> > +
> > + if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
> > + syslog(LOG_WARNING, "(systemd-login) received non signal
> > message");
> > + dbus_message_unref(message);
> > + break;
> > + }
> > +
> > + member = dbus_message_get_member (message);
> > + if (g_strcmp0(member, SESSION_SIGNAL_LOCK) == 0) {
> > + si->session_is_locked = TRUE;
> > + } else if (g_strcmp0(member, SESSION_SIGNAL_UNLOCK) == 0) {
> > + si->session_is_locked = FALSE;
> > + } else if (si->verbose) {
> > + syslog(LOG_DEBUG, "(systemd-login) Signal not handled: %s",
> > member);
> > + }
> > +
> > + dbus_message_unref(message);
> > + dbus_connection_read_write(si->dbus.system_connection, 0);
> > + message = dbus_connection_pop_message(si->dbus.system_connection);
> > + }
> > +}
> > +
> > struct session_info *session_info_create(int verbose)
> > {
> > struct session_info *si;
> > @@ -42,6 +150,7 @@ struct session_info *session_info_create(int verbose)
> > return NULL;
> >
> > si->verbose = verbose;
> > + si->session_is_locked = FALSE;
> >
> > r = sd_login_monitor_new("session", &si->mon);
> > if (r < 0) {
> > @@ -50,6 +159,7 @@ struct session_info *session_info_create(int verbose)
> > return NULL;
> > }
> >
> > + si->dbus.system_connection = si_dbus_get_system_bus();
> > return si;
> > }
> >
> > @@ -58,6 +168,8 @@ void session_info_destroy(struct session_info *si)
> > if (!si)
> > return;
> >
> > + si_dbus_match_remove(si);
> > + dbus_connection_close(si->dbus.system_connection);
> > sd_login_monitor_unref(si->mon);
> > free(si->session);
> > free(si);
> > @@ -87,6 +199,7 @@ const char *session_info_get_active_session(struct
> > session_info *si)
> > sd_login_monitor_flush(si->mon);
> > free(old_session);
> >
> > + si_dbus_match_rule_update(si);
> > return si->session;
> > }
> >
> > @@ -104,3 +217,18 @@ char *session_info_session_for_pid(struct session_info
> > *si, uint32_t pid)
> >
> > return session;
> > }
> > +
> > +gboolean session_info_session_is_locked(struct session_info *si)
> > +{
> > + if (si == NULL)
> > + return FALSE;
> > +
> > + /* We could also rely on IdleHint property from Session which seems to
> > work
> > + * well in rhel7 but it wasn't working well in my own system (F23). I'm
> > + * convinced for now that Lock/Unlock signals should be enough but that
> > + * means Lock/Unlock being done by logind. That might take a while.
> > + * Check: https://bugzilla.gnome.org/show_bug.cgi?id=764773 */
> > +
> > + si_dbus_read_signals(si);
> > + return si->session_is_locked;
> > +}
> > diff --git a/src/vdagentd.c b/src/vdagentd.c
> > index 69332ff..efcf951 100644
> > --- a/src/vdagentd.c
> > +++ b/src/vdagentd.c
> > @@ -279,6 +279,13 @@ static void do_client_file_xfer(struct
> > vdagent_virtio_port *vport,
> > "active session, cancelling client file-xfer request %u",
> > s->id);
> > return;
> > + } else if (session_info_session_is_locked(session_info)) {
> > + syslog(LOG_DEBUG, "Session is locked, skipping file-xfer-start");
> > + cancel_file_xfer(vport,
> > + "User's session is locked and cannot start file transfer. "
> > + "Cancelling client file-xfer request %u",
> > + s->id);
> > + return;
> > }
> > udscs_write(active_session_conn, VDAGENTD_FILE_XFER_START, 0, 0,
> > data, message_header->size);
More information about the Spice-devel
mailing list