From ef3d3d8de8040be76c4dd59dad8960d6ac776670 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mar 05 2015 13:31:00 +0000 Subject: import gdm-3.8.4-32.el7 --- diff --git a/SOURCES/fix-session-chooser-for-smartcards.patch b/SOURCES/fix-session-chooser-for-smartcards.patch new file mode 100644 index 0000000..cb520d0 --- /dev/null +++ b/SOURCES/fix-session-chooser-for-smartcards.patch @@ -0,0 +1,237 @@ +From 8ce3d6268c5ff8f38062c62b487362ac728afa97 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 13 Nov 2014 10:57:05 -0500 +Subject: [PATCH] worker: make sure SavedSessionNameRead is emitted for + conversations without initial username + +We emit SavedSessionNameRead when we know the session associated with a +user account. Unfortunately, we don't emit the signal in the case we +don't know the username up front (such as with a smartcard). + +This commit fixes it to be emitted in that case. +--- + daemon/gdm-session-worker.c | 33 +++++++++++++++++++++------------ + 1 file changed, 21 insertions(+), 12 deletions(-) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index eb81450..731fcf5 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -2131,72 +2131,60 @@ on_saved_session_name_read (GdmSessionWorker *worker) + g_debug ("GdmSessionWorker: Saved session is %s", session_name); + gdm_dbus_worker_emit_saved_session_name_read (GDM_DBUS_WORKER (worker), + session_name); + g_free (session_name); + } + + static void + do_setup (GdmSessionWorker *worker) + { + GError *error; + gboolean res; + + error = NULL; + res = gdm_session_worker_initialize_pam (worker, + worker->priv->service, + worker->priv->username, + worker->priv->hostname, + worker->priv->display_is_local, + worker->priv->x11_display_name, + worker->priv->x11_authority_file, + worker->priv->display_device, + worker->priv->display_seat_id, + &error); + + if (res) { + g_dbus_method_invocation_return_value (worker->priv->pending_invocation, NULL); + } else { + g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error); + } + worker->priv->pending_invocation = NULL; +- +- /* These singal handlers should be disconnected after the loading, +- * so that gdm_session_settings_set_* APIs don't cause the emitting +- * of Saved*NameRead D-Bus signals any more. +- */ +- g_signal_handlers_disconnect_by_func (worker->priv->user_settings, +- G_CALLBACK (on_saved_session_name_read), +- worker); +- +- g_signal_handlers_disconnect_by_func (worker->priv->user_settings, +- G_CALLBACK (on_saved_language_name_read), +- worker); + } + + static void + do_authenticate (GdmSessionWorker *worker) + { + GError *error; + gboolean res; + + /* find out who the user is and ensure they are who they say they are + */ + error = NULL; + res = gdm_session_worker_authenticate_user (worker, + worker->priv->password_is_required, + &error); + if (res) { + /* we're authenticated. Let's make sure we've been given + * a valid username for the system + */ + if (!worker->priv->is_program_session) { + g_debug ("GdmSessionWorker: trying to get updated username"); + gdm_session_worker_update_username (worker); + } + + gdm_dbus_worker_complete_authenticate (GDM_DBUS_WORKER (worker), worker->priv->pending_invocation); + } else { + g_debug ("GdmSessionWorker: Unable to verify user"); + g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error); + } + worker->priv->pending_invocation = NULL; + } +@@ -2236,60 +2224,72 @@ do_accredit (GdmSessionWorker *worker) + gdm_dbus_worker_complete_establish_credentials (GDM_DBUS_WORKER (worker), worker->priv->pending_invocation); + } else { + g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error); + } + worker->priv->pending_invocation = NULL; + } + + static void + save_account_details_now (GdmSessionWorker *worker) + { + g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCREDITED); + + g_debug ("GdmSessionWorker: saving account details for user %s", worker->priv->username); + worker->priv->state = GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED; + if (!gdm_session_settings_save (worker->priv->user_settings, + worker->priv->username)) { + g_warning ("could not save session and language settings"); + } + queue_state_change (worker); + } + + static void + on_settings_is_loaded_changed (GdmSessionSettings *user_settings, + GParamSpec *pspec, + GdmSessionWorker *worker) + { + if (!gdm_session_settings_is_loaded (worker->priv->user_settings)) { + return; + } + ++ /* These singal handlers should be disconnected after the loading, ++ * so that gdm_session_settings_set_* APIs don't cause the emitting ++ * of Saved*NameRead D-Bus signals any more. ++ */ ++ g_signal_handlers_disconnect_by_func (worker->priv->user_settings, ++ G_CALLBACK (on_saved_session_name_read), ++ worker); ++ ++ g_signal_handlers_disconnect_by_func (worker->priv->user_settings, ++ G_CALLBACK (on_saved_language_name_read), ++ worker); ++ + if (worker->priv->state == GDM_SESSION_WORKER_STATE_NONE) { + g_debug ("GdmSessionWorker: queuing setup for user: %s %s", + worker->priv->username, worker->priv->display_device); + queue_state_change (worker); + } else if (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCREDITED) { + save_account_details_now (worker); + } else { + return; + } + + g_signal_handlers_disconnect_by_func (G_OBJECT (worker->priv->user_settings), + G_CALLBACK (on_settings_is_loaded_changed), + worker); + } + + static void + do_save_account_details_when_ready (GdmSessionWorker *worker) + { + g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCREDITED); + + if (!gdm_session_settings_is_loaded (worker->priv->user_settings)) { + g_signal_connect (G_OBJECT (worker->priv->user_settings), + "notify::is-loaded", + G_CALLBACK (on_settings_is_loaded_changed), + worker); + g_debug ("GdmSessionWorker: user %s, not fully loaded yet, will save account details later", + worker->priv->username); + gdm_session_settings_load (worker->priv->user_settings, + worker->priv->username); + return; +@@ -2505,60 +2505,69 @@ gdm_session_worker_handle_open (GdmDBusWorker *object, + GDBusMethodInvocation *invocation) + { + GdmSessionWorker *worker = GDM_SESSION_WORKER (object); + validate_and_queue_state_change (worker, invocation, GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED); + return TRUE; + } + + static gboolean + gdm_session_worker_handle_setup (GdmDBusWorker *object, + GDBusMethodInvocation *invocation, + const char *service, + const char *x11_display_name, + const char *x11_authority_file, + const char *console, + const char *seat_id, + const char *hostname, + gboolean display_is_local) + { + GdmSessionWorker *worker = GDM_SESSION_WORKER (object); + validate_and_queue_state_change (worker, invocation, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE); + + worker->priv->service = g_strdup (service); + worker->priv->x11_display_name = g_strdup (x11_display_name); + worker->priv->x11_authority_file = g_strdup (x11_authority_file); + worker->priv->display_device = g_strdup (console); + worker->priv->display_seat_id = g_strdup (seat_id); + worker->priv->hostname = g_strdup (hostname); + worker->priv->display_is_local = display_is_local; + worker->priv->username = NULL; + ++ g_signal_connect_swapped (worker->priv->user_settings, ++ "notify::language-name", ++ G_CALLBACK (on_saved_language_name_read), ++ worker); ++ ++ g_signal_connect_swapped (worker->priv->user_settings, ++ "notify::session-name", ++ G_CALLBACK (on_saved_session_name_read), ++ worker); + return TRUE; + } + + static gboolean + gdm_session_worker_handle_setup_for_user (GdmDBusWorker *object, + GDBusMethodInvocation *invocation, + const char *service, + const char *username, + const char *x11_display_name, + const char *x11_authority_file, + const char *console, + const char *seat_id, + const char *hostname, + gboolean display_is_local) + { + GdmSessionWorker *worker = GDM_SESSION_WORKER (object); + + if (!validate_state_change (worker, invocation, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE)) + return TRUE; + + worker->priv->service = g_strdup (service); + worker->priv->x11_display_name = g_strdup (x11_display_name); + worker->priv->x11_authority_file = g_strdup (x11_authority_file); + worker->priv->display_device = g_strdup (console); + worker->priv->display_seat_id = g_strdup (seat_id); + worker->priv->hostname = g_strdup (hostname); + worker->priv->display_is_local = display_is_local; + worker->priv->username = g_strdup (username); + + g_signal_connect_swapped (worker->priv->user_settings, +-- +2.1.0 diff --git a/SOURCES/fix-shutdown.patch b/SOURCES/fix-shutdown.patch new file mode 100644 index 0000000..a642fff --- /dev/null +++ b/SOURCES/fix-shutdown.patch @@ -0,0 +1,400 @@ +From 48bf40b905d534ab003722778e0ad16b489e24a5 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 6 Oct 2014 10:58:48 -0400 +Subject: [PATCH 1/4] display: don't leak a reference to the display object + from the display object + +It means display objects never get finalized, and so the slave doesn't +get killed in an orderly way at shutdown. +--- + daemon/gdm-display.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c +index 5d06036..d16c094 100644 +--- a/daemon/gdm-display.c ++++ b/daemon/gdm-display.c +@@ -286,61 +286,61 @@ gdm_display_add_user_authorization (GdmDisplay *display, + g_object_unref (display); + + return ret; + } + + static void + on_name_vanished (GDBusConnection *connection, + const char *name, + gpointer user_data) + { + queue_finish (GDM_DISPLAY (user_data)); + } + + static gboolean + gdm_display_real_set_slave_bus_name (GdmDisplay *display, + const char *name, + GError **error) + { + g_free (display->priv->slave_bus_name); + display->priv->slave_bus_name = g_strdup (name); + + if (display->priv->slave_name_id > 0) { + g_bus_unwatch_name (display->priv->slave_name_id); + } + + display->priv->slave_name_id = g_bus_watch_name_on_connection (display->priv->connection, + name, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, /* name appeared */ + on_name_vanished, +- g_object_ref (display), ++ display, + NULL); + + g_clear_object (&display->priv->slave_bus_proxy); + display->priv->slave_bus_proxy = GDM_DBUS_SLAVE (gdm_dbus_slave_proxy_new_sync (display->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + name, + GDM_SLAVE_PATH, + NULL, NULL)); + g_object_bind_property (G_OBJECT (display->priv->slave_bus_proxy), + "session-id", + G_OBJECT (display), + "session-id", + G_BINDING_DEFAULT); + + return TRUE; + } + + gboolean + gdm_display_set_slave_bus_name (GdmDisplay *display, + const char *name, + GError **error) + { + gboolean ret; + + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + + g_debug ("GdmDisplay: Setting slave bus name:%s on display %s", name, display->priv->x11_display_name); + + g_object_ref (display); + ret = GDM_DISPLAY_GET_CLASS (display)->set_slave_bus_name (display, name, error); +-- +1.8.3.1 + + +From 3cacba38e16686aa93ef47c6e0201938863aa6fb Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 6 Oct 2014 11:00:00 -0400 +Subject: [PATCH 2/4] launch-environment: shutdown worker process as well as + environment pgrp + +The worker isn't part of the environment process group, so it needs to +be kill explicitly even if the environment group is already getting +killed. +--- + daemon/gdm-launch-environment.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c +index 932cc06..551dc96 100644 +--- a/daemon/gdm-launch-environment.c ++++ b/daemon/gdm-launch-environment.c +@@ -502,68 +502,67 @@ gdm_launch_environment_start (GdmLaunchEnvironment *launch_environment) + "session-died", + G_CALLBACK (on_session_died), + launch_environment); + + gdm_session_start_conversation (launch_environment->priv->session, "gdm-launch-environment"); + + if (launch_environment->priv->dbus_session_bus_address) { + gdm_session_select_program (launch_environment->priv->session, launch_environment->priv->command); + } else { + /* wrap it in dbus-launch */ + char *command = g_strdup_printf ("%s %s", DBUS_LAUNCH_COMMAND, launch_environment->priv->command); + + gdm_session_select_program (launch_environment->priv->session, command); + g_free (command); + } + + res = TRUE; + out: + if (local_error) { + g_critical ("GdmLaunchEnvironment: %s", local_error->message); + g_clear_error (&local_error); + } + return res; + } + + gboolean + gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment) + { + if (launch_environment->priv->pid > 1) { + gdm_signal_pid (-launch_environment->priv->pid, SIGTERM); +- } else { +- if (launch_environment->priv->session != NULL) { +- gdm_session_stop_conversation (launch_environment->priv->session, "gdm-launch-environment"); +- gdm_session_close (launch_environment->priv->session); ++ } + +- g_clear_object (&launch_environment->priv->session); +- } ++ if (launch_environment->priv->session != NULL) { ++ gdm_session_stop_conversation (launch_environment->priv->session, "gdm-launch-environment"); ++ gdm_session_close (launch_environment->priv->session); + ++ g_clear_object (&launch_environment->priv->session); + g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0); + } + + return TRUE; + } + + GdmSession * + gdm_launch_environment_get_session (GdmLaunchEnvironment *launch_environment) + { + return launch_environment->priv->session; + } + + char * + gdm_launch_environment_get_session_id (GdmLaunchEnvironment *launch_environment) + { + return g_strdup (launch_environment->priv->session_id); + } + + static void + _gdm_launch_environment_set_verification_mode (GdmLaunchEnvironment *launch_environment, + GdmSessionVerificationMode verification_mode) + { + launch_environment->priv->verification_mode = verification_mode; + } + + static void + _gdm_launch_environment_set_x11_display_name (GdmLaunchEnvironment *launch_environment, + const char *name) + { + g_free (launch_environment->priv->x11_display_name); +-- +1.8.3.1 + + +From 4703ecbca68b4798e95630fced0274e17ee0d5f4 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 6 Oct 2014 11:01:10 -0400 +Subject: [PATCH 3/4] slave: stop from dispose not finalize + +gdm_slave_stop will reference the passed in object, +so doing it after the object is finalized, is wrong. + +This commit moves the stopping to dispose. +--- + daemon/gdm-simple-slave.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index 5057eb4..1ce0284 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -86,61 +86,61 @@ struct GdmSimpleSlavePrivate + GdmSession *session; + + /* this spawns and controls the greeter session */ + GdmLaunchEnvironment *greeter_environment; + + GHashTable *open_reauthentication_requests; + + GDBusProxy *accountsservice_proxy; + guint have_existing_user_accounts : 1; + guint accountsservice_ready : 1; + guint waiting_to_connect_to_display : 1; + + guint start_session_when_ready : 1; + guint waiting_to_start_session : 1; + guint session_is_running : 1; + #ifdef HAVE_LOGINDEVPERM + gboolean use_logindevperm; + #endif + #ifdef WITH_PLYMOUTH + guint plymouth_is_running : 1; + #endif + guint doing_initial_setup : 1; + }; + + enum { + PROP_0, + }; + + static void gdm_simple_slave_class_init (GdmSimpleSlaveClass *klass); + static void gdm_simple_slave_init (GdmSimpleSlave *simple_slave); +-static void gdm_simple_slave_finalize (GObject *object); ++static void gdm_simple_slave_dispose (GObject *object); + static void gdm_simple_slave_open_reauthentication_channel (GdmSlave *slave, + const char *username, + GPid pid_of_caller, + uid_t uid_of_caller, + GAsyncReadyCallback callback, + gpointer user_data, + GCancellable *cancellable); + + static gboolean wants_initial_setup (GdmSimpleSlave *slave); + G_DEFINE_TYPE (GdmSimpleSlave, gdm_simple_slave, GDM_TYPE_SLAVE) + + static void create_new_session (GdmSimpleSlave *slave); + static void start_session (GdmSimpleSlave *slave); + static void queue_start_session (GdmSimpleSlave *slave, + const char *service_name); + + static gboolean + chown_file (GFile *file, + uid_t uid, + gid_t gid, + GError **error) + { + if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, error)) { + return FALSE; + } + if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, error)) { +@@ -1621,92 +1621,91 @@ gdm_simple_slave_stop (GdmSlave *slave) + g_free (username); + + #ifdef HAVE_LOGINDEVPERM + gdm_simple_slave_revoke_console_permissions (self); + #endif + + self->priv->session_is_running = FALSE; + } + + if (self->priv->session != NULL) { + gdm_session_close (self->priv->session); + g_clear_object (&self->priv->session); + } + + if (self->priv->server != NULL) { + gdm_server_stop (self->priv->server); + g_clear_object (&self->priv->server); + } + + g_clear_object (&self->priv->accountsservice_proxy); + + return TRUE; + } + + static void + gdm_simple_slave_class_init (GdmSimpleSlaveClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GdmSlaveClass *slave_class = GDM_SLAVE_CLASS (klass); + +- object_class->finalize = gdm_simple_slave_finalize; ++ object_class->dispose = gdm_simple_slave_dispose; + + slave_class->start = gdm_simple_slave_start; + slave_class->stop = gdm_simple_slave_stop; + slave_class->open_session = gdm_simple_slave_open_session; + slave_class->open_reauthentication_channel = gdm_simple_slave_open_reauthentication_channel; + slave_class->open_reauthentication_channel_finish = gdm_simple_slave_open_reauthentication_channel_finish; + + g_type_class_add_private (klass, sizeof (GdmSimpleSlavePrivate)); + } + + static void + gdm_simple_slave_init (GdmSimpleSlave *slave) + { + slave->priv = GDM_SIMPLE_SLAVE_GET_PRIVATE (slave); + #ifdef HAVE_LOGINDEVPERM + slave->priv->use_logindevperm = FALSE; + #endif + + slave->priv->open_reauthentication_requests = g_hash_table_new_full (NULL, + NULL, + (GDestroyNotify) + NULL, + (GDestroyNotify) + g_object_unref); + } + + static void +-gdm_simple_slave_finalize (GObject *object) ++gdm_simple_slave_dispose (GObject *object) + { + GdmSimpleSlave *slave; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_SIMPLE_SLAVE (object)); + + slave = GDM_SIMPLE_SLAVE (object); + + g_return_if_fail (slave->priv != NULL); + + gdm_slave_stop (GDM_SLAVE (slave)); + +- g_hash_table_unref (slave->priv->open_reauthentication_requests); ++ g_clear_pointer (&slave->priv->open_reauthentication_requests, ++ g_hash_table_unref); + + if (slave->priv->greeter_reset_id > 0) { + g_source_remove (slave->priv->greeter_reset_id); + slave->priv->greeter_reset_id = 0; + } +- +- G_OBJECT_CLASS (gdm_simple_slave_parent_class)->finalize (object); + } + + GdmSlave * + gdm_simple_slave_new (const char *id) + { + GObject *object; + + object = g_object_new (GDM_TYPE_SIMPLE_SLAVE, + "display-id", id, + NULL); + + return GDM_SLAVE (object); + } +-- +1.8.3.1 + + +From dc48d7c3fd45f0c8d623f7766438a5f86e212125 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 6 Oct 2014 11:02:50 -0400 +Subject: [PATCH 4/4] systemd: change to KillMode=process + +By default systemd will kill the entire control-group in one fell +swoop. The problem is, things don't get shutdown in the right +order then, and there's a race where GDM will being restarting +X servers and slaves as soon as they're killed. + +This mucks with shutdown. +--- + data/gdm.service.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/data/gdm.service.in b/data/gdm.service.in +index 29eea4f..a92c745 100644 +--- a/data/gdm.service.in ++++ b/data/gdm.service.in +@@ -1,17 +1,18 @@ + [Unit] + Description=GNOME Display Manager + Conflicts=getty@tty@GDM_INITIAL_VT@.service plymouth-quit.service + After=systemd-user-sessions.service getty@tty@GDM_INITIAL_VT@.service plymouth-quit.service + + [Service] + ExecStart=@sbindir@/gdm + ExecStartPost=-/bin/bash -c "TERM=linux /usr/bin/clear > /dev/tty1" + ExecStop=-/bin/bash -c "TERM=linux /usr/bin/clear > /dev/tty1" ++KillMode=process + Restart=always + IgnoreSIGPIPE=no + BusName=org.gnome.DisplayManager + StandardOutput=syslog + StandardError=inherit + + [Install] + Alias=display-manager.service +-- +1.8.3.1 + diff --git a/SOURCES/fix-timed-login.patch b/SOURCES/fix-timed-login.patch new file mode 100644 index 0000000..fc30971 --- /dev/null +++ b/SOURCES/fix-timed-login.patch @@ -0,0 +1,447 @@ +From a45940c9eb4ac9874e4bd2d6374b0d855d8954fe Mon Sep 17 00:00:00 2001 +From: "Jasper St. Pierre" +Date: Thu, 13 Feb 2014 14:52:49 -0500 +Subject: [PATCH 1/4] display: Clean up get_timed_login_details + +Make it properly log itself as a GdmDisplay method, and use +local variables to ensure that callers can pass NULL. +--- + daemon/gdm-display.c | 34 ++++++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 8 deletions(-) + +diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c +index 352dd92..5d06036 100644 +--- a/daemon/gdm-display.c ++++ b/daemon/gdm-display.c +@@ -426,20 +426,38 @@ gdm_display_real_get_timed_login_details (GdmDisplay *display, + + gboolean + gdm_display_get_timed_login_details (GdmDisplay *display, +- gboolean *enabled, +- char **username, +- int *delay, ++ gboolean *out_enabled, ++ char **out_username, ++ int *out_delay, + GError **error) + { ++ gboolean enabled; ++ char *username; ++ int delay; ++ + g_return_val_if_fail (GDM_IS_DISPLAY (display), FALSE); + +- GDM_DISPLAY_GET_CLASS (display)->get_timed_login_details (display, enabled, username, delay); ++ GDM_DISPLAY_GET_CLASS (display)->get_timed_login_details (display, &enabled, &username, &delay); + +- g_debug ("GdmSlave: Got timed login details for display %s: %d '%s' %d", ++ g_debug ("GdmDisplay: Got timed login details for display %s: %d '%s' %d", + display->priv->x11_display_name, +- *enabled, +- *username ? *username : "(null)", +- *delay); ++ enabled, ++ username, ++ delay); ++ ++ if (out_enabled) { ++ *out_enabled = enabled; ++ } ++ ++ if (out_username) { ++ *out_username = username; ++ } else { ++ g_free (username); ++ } ++ ++ if (out_delay) { ++ *out_delay = delay; ++ } + + return TRUE; + } +-- +1.8.3.1 + + +From ab639086db4f694722fa1c83046bfc503e790894 Mon Sep 17 00:00:00 2001 +From: Vadim Rutkovsky +Date: Fri, 30 May 2014 20:33:49 +0200 +Subject: [PATCH 2/4] Add debug messages for timed login + +--- + daemon/gdm-session.c | 1 + + daemon/gdm-simple-slave.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 4a749d3..6a7d570 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -2604,6 +2604,7 @@ gdm_session_request_timed_login (GdmSession *self, + const char *username, + int delay) + { ++ g_debug ("GdmSession: requesting timed login"); + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface, + username, +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index d83216b..f08f7ad 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -721,6 +721,7 @@ on_ready_to_request_timed_login (GdmSession *session, + GSimpleAsyncResult *result, + gpointer *user_data) + { ++ g_debug ("GdmSimpleSlave: ready to request timed login"); + int delay = GPOINTER_TO_INT (user_data); + GCancellable *cancellable; + char *username; +@@ -754,6 +755,7 @@ on_ready_to_request_timed_login (GdmSession *session, + static gboolean + on_wait_for_greeter_timeout (GSimpleAsyncResult *result) + { ++ g_debug ("GdmSimpleSlave: wait for greeter timeout"); + g_simple_async_result_complete (result); + + return FALSE; +-- +1.8.3.1 + + +From ad879ccbfb4bfc0908b0ca3d256c42d034ae16c7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 5 Jun 2014 17:01:48 -0400 +Subject: [PATCH 3/4] manager: close up timed login race + +Previously we would emit the timed-login-requested signal after the +client connects, which might be before it was listening for the +signal. + +Now we only emit the signal in direct response to a GetTimedLoginDetails +call, which we make implicitly when the appropiate proxy interface is +set up. + +https://bugzilla.gnome.org/show_bug.cgi?id=680348 +--- + daemon/gdm-session.c | 44 ++++++++++++++++++----- + daemon/gdm-session.h | 2 +- + daemon/gdm-session.xml | 5 +++ + daemon/gdm-simple-slave.c | 92 +---------------------------------------------- + gui/libgdm/gdm-client.c | 23 ++++++++++++ + 5 files changed, 65 insertions(+), 101 deletions(-) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 6a7d570..e2e357f 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -89,6 +89,10 @@ struct _GdmSessionPrivate + char *selected_user; + char *user_x11_authority_file; + ++ char *timed_login_username; ++ int timed_login_delay; ++ GList *pending_timed_login_invocations; ++ + GHashTable *conversations; + + GdmSessionConversation *session_conversation; +@@ -1319,6 +1323,27 @@ gdm_session_handle_client_start_session_when_ready (GdmDBusGreeter *greet + } + + static gboolean ++gdm_session_handle_get_timed_login_details (GdmDBusGreeter *greeter_interface, ++ GDBusMethodInvocation *invocation, ++ GdmSession *self) ++{ ++ ++ if (self->priv->greeter_interface != NULL) { ++ gdm_dbus_greeter_complete_get_timed_login_details (greeter_interface, ++ invocation, ++ self->priv->timed_login_username != NULL, ++ self->priv->timed_login_username != NULL? self->priv->timed_login_username : "", ++ self->priv->timed_login_delay); ++ if (self->priv->timed_login_username != NULL) { ++ gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface, ++ self->priv->timed_login_username, ++ self->priv->timed_login_delay); ++ } ++ } ++ return TRUE; ++} ++ ++static gboolean + gdm_session_handle_client_begin_auto_login (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *username, +@@ -1395,6 +1420,10 @@ export_greeter_interface (GdmSession *self, + "handle-start-session-when-ready", + G_CALLBACK (gdm_session_handle_client_start_session_when_ready), + self); ++ g_signal_connect (greeter_interface, ++ "handle-get-timed-login-details", ++ G_CALLBACK (gdm_session_handle_get_timed_login_details), ++ self); + + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (greeter_interface), + connection, +@@ -2600,16 +2629,13 @@ gdm_session_reset (GdmSession *self) + } + + void +-gdm_session_request_timed_login (GdmSession *self, +- const char *username, +- int delay) ++gdm_session_set_timed_login_details (GdmSession *self, ++ const char *username, ++ int delay) + { +- g_debug ("GdmSession: requesting timed login"); +- if (self->priv->greeter_interface != NULL) { +- gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface, +- username, +- delay); +- } ++ g_debug ("GdmSession: timed login details %s %d", username, delay); ++ self->priv->timed_login_username = g_strdup (username); ++ self->priv->timed_login_delay = delay; + } + + gboolean +diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h +index 8b93e2c..14a1721 100644 +--- a/daemon/gdm-session.h ++++ b/daemon/gdm-session.h +@@ -158,7 +158,7 @@ void gdm_session_select_user (GdmSession *session, + const char *username); + void gdm_session_cancel (GdmSession *session); + void gdm_session_reset (GdmSession *session); +-void gdm_session_request_timed_login (GdmSession *session, ++void gdm_session_set_timed_login_details (GdmSession *session, + const char *username, + int delay); + gboolean gdm_session_client_is_connected (GdmSession *session); +diff --git a/daemon/gdm-session.xml b/daemon/gdm-session.xml +index cf3103a..756346d 100644 +--- a/daemon/gdm-session.xml ++++ b/daemon/gdm-session.xml +@@ -88,6 +88,11 @@ + + + ++ ++ ++ ++ ++ + + + +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index f08f7ad..e0e82c7 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -717,51 +717,6 @@ on_session_client_ready_for_session_to_start (GdmSession *session, + } + + static void +-on_ready_to_request_timed_login (GdmSession *session, +- GSimpleAsyncResult *result, +- gpointer *user_data) +-{ +- g_debug ("GdmSimpleSlave: ready to request timed login"); +- int delay = GPOINTER_TO_INT (user_data); +- GCancellable *cancellable; +- char *username; +- +- cancellable = g_object_get_data (G_OBJECT (result), +- "cancellable"); +- if (g_cancellable_is_cancelled (cancellable)) { +- return; +- } +- +- username = g_simple_async_result_get_source_tag (result); +- +- gdm_session_request_timed_login (session, username, delay); +- +- g_object_weak_unref (G_OBJECT (session), +- (GWeakNotify) +- g_cancellable_cancel, +- cancellable); +- g_object_weak_unref (G_OBJECT (session), +- (GWeakNotify) +- g_object_unref, +- cancellable); +- g_object_weak_unref (G_OBJECT (session), +- (GWeakNotify) +- g_free, +- username); +- +- g_free (username); +-} +- +-static gboolean +-on_wait_for_greeter_timeout (GSimpleAsyncResult *result) +-{ +- g_debug ("GdmSimpleSlave: wait for greeter timeout"); +- g_simple_async_result_complete (result); +- +- return FALSE; +-} +- +-static void + on_session_client_connected (GdmSession *session, + GCredentials *credentials, + GPid pid_of_client, +@@ -790,53 +745,8 @@ on_session_client_connected (GdmSession *session, + return; + } + +- /* temporary hack to fix timed login +- * http://bugzilla.gnome.org/680348 +- */ + if (delay > 0) { +- GSimpleAsyncResult *result; +- GCancellable *cancellable; +- guint timeout_id; +- gpointer source_tag; +- +- delay = MAX (delay, 4); +- +- cancellable = g_cancellable_new (); +- source_tag = g_strdup (username); +- result = g_simple_async_result_new (G_OBJECT (session), +- (GAsyncReadyCallback) +- on_ready_to_request_timed_login, +- GINT_TO_POINTER (delay), +- source_tag); +- g_simple_async_result_set_check_cancellable (result, cancellable); +- g_object_set_data (G_OBJECT (result), +- "cancellable", +- cancellable); +- +- timeout_id = g_timeout_add_seconds_full (delay - 2, +- G_PRIORITY_DEFAULT, +- (GSourceFunc) +- on_wait_for_greeter_timeout, +- g_object_ref (result), +- (GDestroyNotify) +- g_object_unref); +- g_cancellable_connect (cancellable, +- G_CALLBACK (g_source_remove), +- GINT_TO_POINTER (timeout_id), +- NULL); +- +- g_object_weak_ref (G_OBJECT (session), +- (GWeakNotify) +- g_cancellable_cancel, +- cancellable); +- g_object_weak_ref (G_OBJECT (session), +- (GWeakNotify) +- g_object_unref, +- cancellable); +- g_object_weak_ref (G_OBJECT (session), +- (GWeakNotify) +- g_free, +- source_tag); ++ gdm_session_set_timed_login_details (session, username, delay); + } + + g_free (username); +diff --git a/gui/libgdm/gdm-client.c b/gui/libgdm/gdm-client.c +index 4542c3e..e1188e5 100644 +--- a/gui/libgdm/gdm-client.c ++++ b/gui/libgdm/gdm-client.c +@@ -794,6 +794,26 @@ gdm_client_get_user_verifier_finish (GdmClient *client, + } + + static void ++on_timed_login_details_got (GdmGreeter *greeter, ++ GAsyncResult *result) ++{ ++ gdm_greeter_call_get_timed_login_details_finish (greeter, NULL, NULL, NULL, result, NULL); ++} ++ ++static void ++query_for_timed_login_requested_signal (GdmGreeter *greeter) ++{ ++ /* This just makes sure a timed-login-requested signal gets fired ++ * off if appropriate. ++ */ ++ gdm_greeter_call_get_timed_login_details (greeter, ++ NULL, ++ (GAsyncReadyCallback) ++ on_timed_login_details_got, ++ NULL); ++} ++ ++static void + on_greeter_proxy_created (GObject *source, + GAsyncResult *result, + GSimpleAsyncResult *operation_result) +@@ -813,6 +833,8 @@ on_greeter_proxy_created (GObject *source, + (GDestroyNotify) + g_object_unref); + g_simple_async_result_complete_in_idle (operation_result); ++ ++ query_for_timed_login_requested_signal (greeter); + } + + static void +@@ -980,6 +1002,7 @@ gdm_client_get_greeter_sync (GdmClient *client, + (GWeakNotify) + g_clear_object, + &client->priv->connection); ++ query_for_timed_login_requested_signal (client->priv->greeter); + } + + return client->priv->greeter; +-- +1.8.3.1 + + +From 35d66c9d4cf54d3e480c399b045468547a0818a8 Mon Sep 17 00:00:00 2001 +From: Philippe Troin +Date: Tue, 2 Sep 2014 15:28:17 -0400 +Subject: [PATCH 4/4] daemon: allow multiple time logins to work + +GDM currently lumps timed login with autologin when deciding whether or +not to skip it, if it's already happened once this boot. + +That's the wrong behavior, and indeed will create a confused experience, +because it's not what the login screen provided by gnome-shell +expects. + +This commit allows timed login to work after the user logs out. + +https://bugzilla.gnome.org/show_bug.cgi?id=732774 +--- + daemon/gdm-simple-slave.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c +index e0e82c7..5057eb4 100644 +--- a/daemon/gdm-simple-slave.c ++++ b/daemon/gdm-simple-slave.c +@@ -650,13 +650,14 @@ static void + start_autologin_conversation_if_necessary (GdmSimpleSlave *slave) + { + gboolean enabled; ++ int delay = 0; + +- if (g_file_test (GDM_RAN_ONCE_MARKER_FILE, G_FILE_TEST_EXISTS)) { ++ gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, NULL, &delay); ++ ++ if (delay == 0 && g_file_test (GDM_RAN_ONCE_MARKER_FILE, G_FILE_TEST_EXISTS)) { + return; + } + +- gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, NULL, NULL); +- + if (!enabled) { + return; + } +-- +1.8.3.1 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index b09e3d7..741b769 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -12,7 +12,7 @@ Summary: The GNOME Display Manager Name: gdm Version: 3.8.4 -Release: 28%{?dist}.1 +Release: 32%{?dist} Epoch: 1 License: GPLv2+ Group: User Interface/X @@ -31,6 +31,9 @@ Patch7: fail-gracefully.patch Patch8: just-in-time-reauthentication.patch Patch9: pam-gnome-keyring.patch Patch10: clear-screen.patch +Patch11: fix-timed-login.patch +Patch12: fix-shutdown.patch +Patch13: fix-session-chooser-for-smartcards.patch Patch98: system-dconf.patch Patch99: classic-session.patch @@ -146,6 +149,9 @@ Development files and headers for writing GDM greeters. %patch8 -p1 -b .just-in-time-reauthetication %patch9 -p1 -b .pam-gnome-kerying %patch10 -p1 -b .clear-screen +%patch11 -p1 -b .fix-timed-login +%patch12 -p1 -b .fix-shutdown +%patch13 -p1 -b .fix-session-chooser-for-smartcards %patch98 -p1 -b .system-dconf %patch99 -p1 -b .classic-session @@ -364,11 +370,23 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || : %{_libdir}/girepository-1.0/Gdm-1.0.typelib %changelog -* Fri May 23 2014 Ray Strode 3.8.4-28.1 -- rebuild because of dist confusion +* Thu Nov 13 2014 Ray Strode 3.8.4-32 +- Fix session chooser for smartcard login + Resolves: #1159056 + +* Mon Oct 06 2014 Ray Strode 3.8.4-31 +- Fix race that sometimes leads to 90 second stall at shutdown + Resolves: #1107811 + +* Fri Oct 03 2014 Ray Strode 3.8.4-30 +- Fix race in timed login + Resolves: #1043571 + +* Fri May 23 2014 Ray Strode 3.8.4-29 +- rebuild for dist confusion Related: #1086189 -* Tue May 06 2014 Ray Strode 3.8.4-27.1 +* Mon Apr 28 2014 Ray Strode 3.8.4-28 - Fix resource leak when reauthentication client is rejected Resolves: #1086189