From 67b24ad9f494256cb580f06d2258ce711ae7b84d Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Oct 16 2012 02:20:04 +0000 Subject: slave: don't fail if user session already active when activating from unlock After GDM successfully reauthenticates a user it runs gdm_slave_switch_to_user_session to jump to the user's VT and unlock it. Of course, if the user is reauthenticating from an unlock screen instead of a user switched login screen, then they'll already be on the right VT. gdm_slave_switch_to_user_session fails if the user is already switched to the session specified. This failing behavior is used at login time to decide start a user's session (versus switching to a user's already running session). This commit changes gdm_slave_switch_to_user_session to take an additional parameter to decide whether or not switching to an already active session should fail, or merely skip to the unlocking step. https://bugzilla.gnome.org/show_bug.cgi?id=685988 (cherry picked from commit 99c4f960c0689d310a799e87f6361fb25a8862f6) --- diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index 2e0b68b..9bc8522 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -311,17 +311,18 @@ gdm_simple_slave_start_session_when_ready (GdmSimpleSlave *slave, } static gboolean -try_migrate_session (GdmSimpleSlave *slave) +switch_to_and_unlock_session (GdmSimpleSlave *slave, + gboolean fail_if_already_switched) { char *username; gboolean res; - g_debug ("GdmSimpleSlave: trying to migrate session"); - username = gdm_session_get_username (slave->priv->session); + g_debug ("GdmSimpleSlave: trying to switch to session for user %s", username); + /* try to switch to an existing session */ - res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username); + res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username, fail_if_already_switched); g_free (username); return res; @@ -392,11 +393,18 @@ static gboolean start_session_timeout (GdmSimpleSlave *slave) { gboolean migrated; - + gboolean fail_if_already_switched = TRUE; g_debug ("GdmSimpleSlave: accredited"); - migrated = try_migrate_session (slave); + /* If there's already a session running, jump to it. + * If the only session running is the one we just opened, + * start a session on it. + * + * We assume we're in the former case if we need to switch + * VTs, and we assume we're in the latter case if we don't. + */ + migrated = switch_to_and_unlock_session (slave, fail_if_already_switched); g_debug ("GdmSimpleSlave: migrated: %d", migrated); if (migrated) { /* We don't stop the slave here because @@ -438,7 +446,14 @@ on_session_reauthenticated (GdmSession *session, const char *service_name, GdmSimpleSlave *slave) { - try_migrate_session (slave); + gboolean fail_if_already_switched = FALSE; + + /* There should already be a session running, so jump to it's + * VT. In the event we're already on the right VT, (i.e. user + * used an unlock screen instead of a user switched login screen), + * then silently succeed and unlock the session. + */ + switch_to_and_unlock_session (slave, fail_if_already_switched); } static void diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c index f011207..287c7d6 100644 --- a/daemon/gdm-slave.c +++ b/daemon/gdm-slave.c @@ -1474,15 +1474,6 @@ activate_session_id_for_systemd (GdmSlave *slave, GError *error = NULL; GVariant *reply; - /* Can't activate what's already active. We want this - * to fail, because we don't want migration to succeed - * if the only active session is the one just created - * at the login screen. - */ - if (sd_session_is_active (session_id) > 0) { - return FALSE; - } - reply = g_dbus_connection_call_sync (slave->priv->connection, "org.freedesktop.login1", "/org/freedesktop/login1", @@ -1559,6 +1550,59 @@ activate_session_id (GdmSlave *slave, #endif } +#ifdef WITH_CONSOLE_KIT +static gboolean +ck_session_is_active (GdmSlave *slave, + const char *seat_id, + const char *session_id) +{ + GError *error = NULL; + GVariant *reply; + gboolean is_active; + + reply = g_dbus_connection_call_sync (slave->priv->connection, + CK_NAME, + session_id, + "org.freedesktop.ConsoleKit.Session", + "IsActive", + NULL, + G_VARIANT_TYPE ("(b)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (reply == NULL) { + g_debug ("GdmSlave: ConsoleKit IsActive %s raised:\n %s\n\n", + g_dbus_error_get_remote_error (error), error->message); + g_error_free (error); + return FALSE; + } + + g_variant_get (reply, "(b)", &is_active); + g_variant_unref (reply); + + return is_active; +} +#endif + +static gboolean +session_is_active (GdmSlave *slave, + const char *seat_id, + const char *session_id) +{ +#ifdef WITH_SYSTEMD + if (sd_booted () > 0) { + return sd_session_is_active (session_id) > 0; + } +#endif + +#ifdef WITH_CONSOLE_KIT + return ck_session_is_active (slave, seat_id, session_id); +#else + return FALSE; +#endif +} + #ifdef WITH_SYSTEMD static gboolean session_unlock_for_systemd (GdmSlave *slave, @@ -1645,10 +1689,12 @@ session_unlock (GdmSlave *slave, gboolean gdm_slave_switch_to_user_session (GdmSlave *slave, - const char *username) + const char *username, + gboolean fail_if_already_switched) { gboolean res; gboolean ret; + gboolean session_already_switched; char *ssid_to_activate; ret = FALSE; @@ -1659,14 +1705,23 @@ gdm_slave_switch_to_user_session (GdmSlave *slave, goto out; } + session_already_switched = session_is_active (slave, slave->priv->display_seat_id, ssid_to_activate); + g_debug ("GdmSlave: Activating session: '%s'", ssid_to_activate); - res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate); - if (! res) { - g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate); + if (session_already_switched && fail_if_already_switched) { + g_debug ("GdmSlave: unable to activate session since it's already active: %s", ssid_to_activate); goto out; } + if (!session_already_switched) { + res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate); + if (! res) { + g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate); + goto out; + } + } + res = session_unlock (slave, ssid_to_activate); if (!res) { /* this isn't fatal */ diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h index 98e25f5..0647618 100644 --- a/daemon/gdm-slave.h +++ b/daemon/gdm-slave.h @@ -99,7 +99,8 @@ gboolean gdm_slave_add_user_authorization (GdmSlave *slave, char **filename); gboolean gdm_slave_switch_to_user_session (GdmSlave *slave, - const char *username); + const char *username, + gboolean fail_if_already_switched); gboolean gdm_slave_connect_to_x11_display (GdmSlave *slave);