From 7ae91c45261349bcb51d4b9a66fb467a3e761c62 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jun 10 2014 19:12:24 +0000 Subject: import gdm-3.8.4-28.el7_0.1 --- diff --git a/SOURCES/just-in-time-reauthentication.patch b/SOURCES/just-in-time-reauthentication.patch index 772247e..fa51ec1 100644 --- a/SOURCES/just-in-time-reauthentication.patch +++ b/SOURCES/just-in-time-reauthentication.patch @@ -1433,3 +1433,671 @@ index 4c47045..7eb2172 100644 -- 1.8.4.2 +From a63ed886a5b232cc44938badd37daf394215d3b9 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 10 Apr 2014 08:56:10 -0400 +Subject: [PATCH 1/4] session: introduce new client-rejected signal + +If a client gets rejected because it's not allowed to connect +to a particular session, we really need to inform the owner +of the session object so it can do any clean up it needs to do, +if necessary. +--- + daemon/gdm-session.c | 24 ++++++++++++++++++++++++ + daemon/gdm-session.h | 1 + + 2 files changed, 25 insertions(+) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index e24ec7c..044a57c 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -117,60 +117,61 @@ struct _GdmSessionPrivate + + uid_t allowed_user; + + char *fallback_session_name; + + GDBusServer *worker_server; + GDBusServer *outside_server; + GHashTable *environment; + }; + + enum { + PROP_0, + PROP_VERIFICATION_MODE, + PROP_ALLOWED_USER, + PROP_DISPLAY_NAME, + PROP_DISPLAY_HOSTNAME, + PROP_DISPLAY_IS_LOCAL, + PROP_DISPLAY_DEVICE, + PROP_DISPLAY_SEAT_ID, + PROP_DISPLAY_X11_AUTHORITY_FILE, + PROP_USER_X11_AUTHORITY_FILE, + PROP_CONVERSATION_ENVIRONMENT, + }; + + enum { + CONVERSATION_STARTED = 0, + CONVERSATION_STOPPED, + SETUP_COMPLETE, + CANCELLED, + HOSTNAME_SELECTED, ++ CLIENT_REJECTED, + CLIENT_CONNECTED, + CLIENT_DISCONNECTED, + CLIENT_READY_FOR_SESSION_TO_START, + DISCONNECTED, + VERIFICATION_COMPLETE, + SESSION_OPENED, + SESSION_STARTED, + SESSION_START_FAILED, + SESSION_EXITED, + SESSION_DIED, + REAUTHENTICATION_STARTED, + REAUTHENTICATED, + LAST_SIGNAL + }; + + static guint signals [LAST_SIGNAL] = { 0, }; + + G_DEFINE_TYPE (GdmSession, + gdm_session, + G_TYPE_OBJECT); + + static GdmSessionConversation * + find_conversation_by_name (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + + conversation = g_hash_table_lookup (self->priv->conversations, service_name); + + if (conversation == NULL) { +@@ -1561,68 +1562,78 @@ setup_worker_server (GdmSession *self) + + server = gdm_dbus_setup_private_server (observer, &error); + g_object_unref (observer); + + if (server == NULL) { + g_warning ("Cannot create worker D-Bus server for the session: %s", + error->message); + return; + } + + g_signal_connect_object (server, + "new-connection", + G_CALLBACK (handle_connection_from_worker), + self, + 0); + self->priv->worker_server = server; + + g_dbus_server_start (server); + + g_debug ("GdmSession: D-Bus server for workers listening on %s", + g_dbus_server_get_client_address (self->priv->worker_server)); + } + + static gboolean + allow_user_function (GDBusAuthObserver *observer, + GIOStream *stream, + GCredentials *credentials, + GdmSession *self) + { + uid_t client_uid; ++ GPid pid_of_client; + + client_uid = g_credentials_get_unix_user (credentials, NULL); + if (client_uid == self->priv->allowed_user) { + return TRUE; + } + + g_debug ("GdmSession: User not allowed"); + ++ pid_of_client = credentials_get_unix_pid (credentials); ++ g_signal_emit (G_OBJECT (self), ++ signals [CLIENT_REJECTED], ++ 0, ++ credentials, ++ (guint) ++ pid_of_client); ++ ++ + return FALSE; + } + + static void + setup_outside_server (GdmSession *self) + { + GDBusAuthObserver *observer; + GDBusServer *server; + GError *error = NULL; + + g_debug ("GdmSession: Creating D-Bus server for greeters and such"); + + observer = g_dbus_auth_observer_new (); + g_signal_connect_object (observer, + "authorize-authenticated-peer", + G_CALLBACK (allow_user_function), + self, + 0); + + server = gdm_dbus_setup_private_server (observer, &error); + g_object_unref (observer); + + if (server == NULL) { + g_warning ("Cannot create greeter D-Bus server for the session: %s", + error->message); + return; + } + + g_signal_connect_object (server, + "new-connection", +@@ -3186,60 +3197,73 @@ gdm_session_class_init (GdmSessionClass *session_class) + G_STRUCT_OFFSET (GdmSessionClass, reauthentication_started), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_INT, + G_TYPE_STRING); + signals [REAUTHENTICATED] = + g_signal_new ("reauthenticated", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionClass, reauthenticated), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + signals [CANCELLED] = + g_signal_new ("cancelled", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionClass, cancelled), + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + ++ signals [CLIENT_REJECTED] = ++ g_signal_new ("client-rejected", ++ GDM_TYPE_SESSION, ++ G_SIGNAL_RUN_FIRST, ++ G_STRUCT_OFFSET (GdmSessionClass, client_rejected), ++ NULL, ++ NULL, ++ NULL, ++ G_TYPE_NONE, ++ 2, ++ G_TYPE_CREDENTIALS, ++ G_TYPE_UINT); ++ + signals [CLIENT_CONNECTED] = + g_signal_new ("client-connected", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionClass, client_connected), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_CREDENTIALS, + G_TYPE_UINT); + + signals [CLIENT_DISCONNECTED] = + g_signal_new ("client-disconnected", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionClass, client_disconnected), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_CREDENTIALS, + G_TYPE_UINT); + signals [CLIENT_READY_FOR_SESSION_TO_START] = + g_signal_new ("client-ready-for-session-to-start", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GdmSessionClass, client_ready_for_session_to_start), +diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h +index 2511eca..8b93e2c 100644 +--- a/daemon/gdm-session.h ++++ b/daemon/gdm-session.h +@@ -30,60 +30,61 @@ G_BEGIN_DECLS + #define GDM_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SESSION, GdmSessionClass)) + #define GDM_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SESSION)) + #define GDM_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SESSION)) + #define GDM_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION, GdmSessionClass)) + + typedef struct _GdmSessionPrivate GdmSessionPrivate; + + typedef enum + { + GDM_SESSION_VERIFICATION_MODE_LOGIN, + GDM_SESSION_VERIFICATION_MODE_CHOOSER, + GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE + } GdmSessionVerificationMode; + + typedef struct + { + GObject parent; + GdmSessionPrivate *priv; + } GdmSession; + + typedef struct + { + GObjectClass parent_class; + + /* Signals */ + void (* client_ready_for_session_to_start) (GdmSession *session, + const char *service_name, + gboolean client_is_ready); + + void (* cancelled) (GdmSession *session); ++ void (* client_rejected) (GdmSession *session); + void (* client_connected) (GdmSession *session); + void (* client_disconnected) (GdmSession *session); + void (* disconnected) (GdmSession *session); + void (* verification_complete) (GdmSession *session, + const char *service_name); + void (* session_opened) (GdmSession *session, + const char *service_name, + const char *session_id); + void (* session_started) (GdmSession *session, + const char *service_name, + const char *session_id, + int pid); + void (* session_start_failed) (GdmSession *session, + const char *service_name, + const char *message); + void (* session_exited) (GdmSession *session, + int exit_code); + void (* session_died) (GdmSession *session, + int signal_number); + void (* reauthentication_started) (GdmSession *session, + GPid pid_of_caller); + void (* reauthenticated) (GdmSession *session, + const char *service_name); + void (* conversation_started) (GdmSession *session, + const char *service_name); + void (* conversation_stopped) (GdmSession *session, + const char *service_name); + void (* setup_complete) (GdmSession *session, + const char *service_name); + } GdmSessionClass; +-- +1.9.0 + + +From d11dd2511e08ab73757b8e97572c912c1f2fff8d Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 10 Apr 2014 09:13:57 -0400 +Subject: [PATCH 2/4] manager: stuff pid associated with transient session on + session object + +In the event the session object is not associated with an audit session, +we want some way to match the object back to a client. This commit +stores the pid of the caller on the object. +--- + daemon/gdm-manager.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index e6fd0b4..4d60ac0 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -843,60 +843,63 @@ open_temporary_reauthentication_channel (GdmManager *self, + { + GdmSession *session; + char **environment; + const char *display, *auth_file; + char *address; + + /* Note we're just using a minimal environment here rather than the + * session's environment because the caller is unprivileged and the + * associated worker will be privileged */ + environment = g_get_environ (); + display = ""; + auth_file = "/dev/null"; + + session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE, + uid, + display, + NULL, + NULL, + seat_id, + auth_file, + is_remote == FALSE, + (const char * const *) + environment); + g_strfreev (environment); + + g_object_set_data_full (G_OBJECT (session), + "caller-session-id", + g_strdup (session_id), + (GDestroyNotify) + g_free); ++ g_object_set_data (G_OBJECT (session), ++ "caller-pid", ++ GINT_TO_POINTER ((gint) pid)); + g_object_weak_ref (G_OBJECT (self), + (GWeakNotify) + gdm_session_close, + session); + g_object_weak_ref (G_OBJECT (self), + (GWeakNotify) + g_object_unref, + session); + g_object_weak_ref (G_OBJECT (session), + (GWeakNotify) + remove_session_weak_refs, + self); + + g_signal_connect (session, + "client-connected", + G_CALLBACK (on_reauthentication_client_connected), + self); + g_signal_connect (session, + "client-disconnected", + G_CALLBACK (on_reauthentication_client_disconnected), + self); + g_signal_connect (session, + "cancelled", + G_CALLBACK (on_reauthentication_cancelled), + self); + g_signal_connect (session, + "conversation-started", + G_CALLBACK (on_reauthentication_conversation_started), + self); + g_signal_connect (session, +-- +1.9.0 + + +From 24c3d14d5336aa59d15f1cfdb59643dd254a62bd Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 10 Apr 2014 09:22:07 -0400 +Subject: [PATCH 3/4] manager: don't leak session objects when client is + rejected + +if a client creates a transient reauthentication session and then we reject +the client when it tries to connect to it, then we need to clean up +the associated session object. + +This commit does that. +--- + daemon/gdm-manager.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 4d60ac0..084fbb4 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -752,60 +752,102 @@ unlock_session (GdmManager *manager, + unlock_systemd_session (manager, ssid); + return; + } + #endif + + #ifdef WITH_CONSOLE_KIT + unlock_consolekit_session (manager, ssid); + #endif + } + static void + on_reauthentication_client_connected (GdmSession *session, + GCredentials *credentials, + GPid pid_of_client, + GdmManager *self) + { + g_debug ("GdmManager: client connected to reauthentication server"); + } + + static void + on_reauthentication_client_disconnected (GdmSession *session, + GCredentials *credentials, + GPid pid_of_client, + GdmManager *self) + { + g_debug ("GdmManger: client disconnected from reauthentication server"); + gdm_session_close (session); + g_object_unref (session); + } + + static void ++on_reauthentication_client_rejected (GdmSession *session, ++ GCredentials *credentials, ++ GPid pid_of_client, ++ GdmManager *self) ++{ ++ GPid pid; ++ ++ g_debug ("GdmManger: client with pid %ld rejected from reauthentication server", (long) pid_of_client); ++ ++ if (gdm_session_client_is_connected (session)) { ++ /* we already have a client connected, ignore this rejected one */ ++ return; ++ } ++ ++ pid = (GPid) GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), "caller-pid")); ++ ++ if (pid != pid_of_client) { ++ const char *session_id; ++ char *client_session_id; ++ ++ /* rejected client isn't the process that started the ++ * transient reauthentication session. If it's not even from the ++ * same audit session, ignore it since it doesn't "own" the ++ * reauthentication session ++ */ ++ client_session_id = get_session_id_for_pid (self->priv->connection, ++ pid_of_client, ++ NULL); ++ session_id = g_object_get_data (G_OBJECT (session), "caller-session-id"); ++ ++ if (g_strcmp0 (session_id, client_session_id) != 0) { ++ return; ++ } ++ } ++ ++ /* client was rejected, so clean up its session object ++ */ ++ gdm_session_close (session); ++ g_object_unref (session); ++} ++ ++static void + on_reauthentication_cancelled (GdmSession *session, + GdmManager *self) + { + g_debug ("GdmManager: client cancelled reauthentication request"); + gdm_session_close (session); + g_object_unref (session); + } + + static void + on_reauthentication_conversation_started (GdmSession *session, + const char *service_name, + GdmManager *self) + { + g_debug ("GdmManager: reauthentication service '%s' started", + service_name); + } + + static void + on_reauthentication_conversation_stopped (GdmSession *session, + const char *service_name, + GdmManager *self) + { + g_debug ("GdmManager: reauthentication service '%s' stopped", + service_name); + } + + static void + on_reauthentication_verification_complete (GdmSession *session, + const char *service_name, + GdmManager *self) +@@ -868,60 +910,64 @@ open_temporary_reauthentication_channel (GdmManager *self, + g_object_set_data_full (G_OBJECT (session), + "caller-session-id", + g_strdup (session_id), + (GDestroyNotify) + g_free); + g_object_set_data (G_OBJECT (session), + "caller-pid", + GINT_TO_POINTER ((gint) pid)); + g_object_weak_ref (G_OBJECT (self), + (GWeakNotify) + gdm_session_close, + session); + g_object_weak_ref (G_OBJECT (self), + (GWeakNotify) + g_object_unref, + session); + g_object_weak_ref (G_OBJECT (session), + (GWeakNotify) + remove_session_weak_refs, + self); + + g_signal_connect (session, + "client-connected", + G_CALLBACK (on_reauthentication_client_connected), + self); + g_signal_connect (session, + "client-disconnected", + G_CALLBACK (on_reauthentication_client_disconnected), + self); + g_signal_connect (session, ++ "client-rejected", ++ G_CALLBACK (on_reauthentication_client_rejected), ++ self); ++ g_signal_connect (session, + "cancelled", + G_CALLBACK (on_reauthentication_cancelled), + self); + g_signal_connect (session, + "conversation-started", + G_CALLBACK (on_reauthentication_conversation_started), + self); + g_signal_connect (session, + "conversation-stopped", + G_CALLBACK (on_reauthentication_conversation_stopped), + self); + g_signal_connect (session, + "verification-complete", + G_CALLBACK (on_reauthentication_verification_complete), + self); + + address = gdm_session_get_server_address (session); + return address; + } + + static gboolean + gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager, + GDBusMethodInvocation *invocation, + const char *username) + { + GdmManager *self = GDM_MANAGER (manager); + const char *sender = NULL; + GError *error = NULL; + GDBusConnection *connection; + GdmDisplay *display = NULL; +-- +1.9.0 + + +From 9d67a7fd3acdc4b063020dfca53f676c2f1449d1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 10 Apr 2014 09:27:59 -0400 +Subject: [PATCH 4/4] manager: be more accepting of callers with uids different + from their session + +If a user runs su in their session, that switched user will now be +running in a session that doesn't belong to it. GDM won't allow a user +access to the worker process associated with the session in this case. +Instead, it will try to create a temporary just-in-time reauthentication +channel so reauthentication can happen without having the user talking to +another user's worker. Unfortunately, a logic error in the code means, +the user won't access to its own just-in-time channel. + +This commit fixes that. +--- + daemon/gdm-manager.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 084fbb4..5809792 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -568,61 +568,61 @@ get_display_and_details_for_bus_sender (GdmManager *self, + if (session_id == NULL) { + g_debug ("GdmManager: Error while retrieving session id for sender: %s", + error->message); + g_error_free (error); + goto out; + } + + if (out_session_id != NULL) { + *out_session_id = g_strdup (session_id); + } + + if (out_is_login_screen != NULL) { + *out_is_login_screen = is_login_session (self, connection, session_id, &error); + + if (error != NULL) { + g_debug ("GdmManager: Error while checking if sender is login screen: %s", + error->message); + g_error_free (error); + goto out; + } + } + + if (!get_uid_for_session_id (connection, session_id, &session_uid, &error)) { + g_debug ("GdmManager: Error while retrieving uid for session: %s", + error->message); + g_error_free (error); + goto out; + } + + if (out_uid != NULL) +- *out_uid = session_uid; ++ *out_uid = caller_uid; + + if (caller_uid != session_uid) { + g_debug ("GdmManager: uid for sender and uid for session don't match"); + goto out; + } + + if (out_seat_id != NULL) { + *out_seat_id = get_seat_id_for_session_id (connection, session_id, &error); + + if (error != NULL) { + g_debug ("GdmManager: Error while retrieving seat id for session: %s", + error->message); + g_clear_error (&error); + } + } + + if (out_is_remote != NULL) { + *out_is_remote = is_remote_session (self, connection, session_id, &error); + + if (error != NULL) { + g_debug ("GdmManager: Error while retrieving remoteness for session: %s", + error->message); + g_clear_error (&error); + } + } + + display = gdm_display_store_find (self->priv->display_store, + lookup_by_session_id, + (gpointer) session_id); + if (out_display != NULL) +-- +1.9.0 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index 4bbc5c4..b09e3d7 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: 27%{?dist} +Release: 28%{?dist}.1 Epoch: 1 License: GPLv2+ Group: User Interface/X @@ -364,6 +364,18 @@ 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 + Related: #1086189 + +* Tue May 06 2014 Ray Strode 3.8.4-27.1 +- Fix resource leak when reauthentication client is rejected + Resolves: #1086189 + +- Don't reject reauthentication clients with uids that don't + match the uid of those clients' logind sessions. + Related: #1086189 1057179 + * Wed Apr 23 2014 Ray Strode 3.8.4-27 - One more PATH logic update Related: #1080153