Blame SOURCES/0001-manager-Don-t-leak-session-objects.patch

400dab
From de229615d80fd7c8a38ab5d5d7b30aa98f43721d Mon Sep 17 00:00:00 2001
400dab
From: Ray Strode <rstrode@redhat.com>
400dab
Date: Mon, 14 Sep 2020 16:20:09 -0400
400dab
Subject: [PATCH 1/3] manager: Don't leak session objects
400dab
400dab
The first is from create_user_session_for display.  Most callers don't
400dab
check the return value, so it should just be void.
400dab
400dab
The user data associated with the session also isn't unlinked from the
400dab
display when the display is finishing up, preventing the display and
400dab
session object from getting freed.
400dab
400dab
This commit makes both changes.
400dab
---
400dab
 daemon/gdm-manager.c | 17 +++++++++--------
400dab
 1 file changed, 9 insertions(+), 8 deletions(-)
400dab
400dab
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
400dab
index bff602a07..738671679 100644
400dab
--- a/daemon/gdm-manager.c
400dab
+++ b/daemon/gdm-manager.c
400dab
@@ -94,63 +94,63 @@ struct GdmManagerPrivate
400dab
 #ifdef  WITH_PLYMOUTH
400dab
         guint                     plymouth_is_running : 1;
400dab
 #endif
400dab
         guint                     did_automatic_login : 1;
400dab
 };
400dab
 
400dab
 enum {
400dab
         PROP_0,
400dab
         PROP_XDMCP_ENABLED,
400dab
         PROP_SHOW_LOCAL_GREETER
400dab
 };
400dab
 
400dab
 enum {
400dab
         DISPLAY_ADDED,
400dab
         DISPLAY_REMOVED,
400dab
         LAST_SIGNAL
400dab
 };
400dab
 
400dab
 typedef enum {
400dab
         SESSION_RECORD_LOGIN,
400dab
         SESSION_RECORD_LOGOUT,
400dab
         SESSION_RECORD_FAILED,
400dab
 } SessionRecord;
400dab
 
400dab
 static guint signals [LAST_SIGNAL] = { 0, };
400dab
 
400dab
 static void     gdm_manager_class_init  (GdmManagerClass *klass);
400dab
 static void     gdm_manager_init        (GdmManager      *manager);
400dab
 static void     gdm_manager_dispose     (GObject         *object);
400dab
 
400dab
-static GdmSession *create_user_session_for_display (GdmManager *manager,
400dab
-                                                    GdmDisplay *display,
400dab
-                                                    uid_t       allowed_user);
400dab
+static void     create_user_session_for_display (GdmManager *manager,
400dab
+                                                 GdmDisplay *display,
400dab
+                                                 uid_t       allowed_user);
400dab
 static void     start_user_session (GdmManager                *manager,
400dab
                                     StartUserSessionOperation *operation);
400dab
 static void     clean_user_session (GdmSession *session);
400dab
 
400dab
 static gpointer manager_object = NULL;
400dab
 
400dab
 static void manager_interface_init (GdmDBusManagerIface *interface);
400dab
 
400dab
 G_DEFINE_TYPE_WITH_CODE (GdmManager,
400dab
                          gdm_manager,
400dab
                          GDM_DBUS_TYPE_MANAGER_SKELETON,
400dab
                          G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_MANAGER,
400dab
                                                 manager_interface_init));
400dab
 
400dab
 #ifdef WITH_PLYMOUTH
400dab
 static gboolean
400dab
 plymouth_is_running (void)
400dab
 {
400dab
         int      status;
400dab
         gboolean res;
400dab
         GError  *error;
400dab
 
400dab
         error = NULL;
400dab
         res = g_spawn_command_line_sync ("/bin/plymouth --ping",
400dab
                                          NULL, NULL, &status, &error);
400dab
         if (! res) {
400dab
                 g_debug ("Could not ping plymouth: %s", error->message);
400dab
                 g_error_free (error);
400dab
                 return FALSE;
400dab
         }
400dab
@@ -1343,61 +1343,62 @@ get_automatic_login_details (GdmManager *manager,
400dab
         return enabled;
400dab
 }
400dab
 
400dab
 static const char *
400dab
 get_username_for_greeter_display (GdmManager *manager,
400dab
                                   GdmDisplay *display)
400dab
 {
400dab
         gboolean doing_initial_setup = FALSE;
400dab
 
400dab
         g_object_get (G_OBJECT (display),
400dab
                       "doing-initial-setup", &doing_initial_setup,
400dab
                       NULL);
400dab
 
400dab
         if (doing_initial_setup) {
400dab
                 return INITIAL_SETUP_USERNAME;
400dab
         } else {
400dab
                 return GDM_USERNAME;
400dab
         }
400dab
 }
400dab
 
400dab
 static void
400dab
 set_up_automatic_login_session (GdmManager *manager,
400dab
                                 GdmDisplay *display)
400dab
 {
400dab
         GdmSession *session;
400dab
         char       *display_session_type = NULL;
400dab
 
400dab
         /* 0 is root user; since the daemon talks to the session object
400dab
          * directly, itself, for automatic login
400dab
          */
400dab
-        session = create_user_session_for_display (manager, display, 0);
400dab
+        create_user_session_for_display (manager, display, 0);
400dab
+        session = get_user_session_for_display (display);
400dab
 
400dab
         g_object_get (G_OBJECT (display),
400dab
                       "session-type", &display_session_type,
400dab
                       NULL);
400dab
 
400dab
         g_object_set (G_OBJECT (session),
400dab
                       "display-is-initial", FALSE,
400dab
                       NULL);
400dab
 
400dab
         g_debug ("GdmManager: Starting automatic login conversation");
400dab
         gdm_session_start_conversation (session, "gdm-autologin");
400dab
 }
400dab
 
400dab
 static void
400dab
 set_up_chooser_session (GdmManager *manager,
400dab
                         GdmDisplay *display)
400dab
 {
400dab
         const char *allowed_user;
400dab
         struct passwd *passwd_entry;
400dab
 
400dab
         allowed_user = get_username_for_greeter_display (manager, display);
400dab
 
400dab
         if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
400dab
                 g_warning ("GdmManager: couldn't look up username %s",
400dab
                            allowed_user);
400dab
                 gdm_display_unmanage (display);
400dab
                 gdm_display_finish (display);
400dab
                 return;
400dab
         }
400dab
 
400dab
@@ -1549,60 +1550,62 @@ on_display_status_changed (GdmDisplay *display,
400dab
                       "session-type", &session_type,
400dab
                       NULL);
400dab
 
400dab
         status = gdm_display_get_status (display);
400dab
 
400dab
         switch (status) {
400dab
                 case GDM_DISPLAY_PREPARED:
400dab
                 case GDM_DISPLAY_MANAGED:
400dab
                         if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
400dab
                             (display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
400dab
                                 char *session_class;
400dab
 
400dab
                                 g_object_get (display,
400dab
                                               "session-class", &session_class,
400dab
                                               NULL);
400dab
                                 if (g_strcmp0 (session_class, "greeter") == 0)
400dab
                                         set_up_session (manager, display);
400dab
                                 g_free (session_class);
400dab
                         }
400dab
                         break;
400dab
                 case GDM_DISPLAY_FAILED:
400dab
                 case GDM_DISPLAY_UNMANAGED:
400dab
                 case GDM_DISPLAY_FINISHED:
400dab
 #ifdef WITH_PLYMOUTH
400dab
                         if (quit_plymouth) {
400dab
                                 plymouth_quit_without_transition ();
400dab
                                 manager->priv->plymouth_is_running = FALSE;
400dab
                         }
400dab
 #endif
400dab
 
400dab
+                        g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
400dab
+
400dab
                         if (display == manager->priv->automatic_login_display) {
400dab
                                 g_clear_weak_pointer (&manager->priv->automatic_login_display);
400dab
 
400dab
                                 manager->priv->did_automatic_login = TRUE;
400dab
 
400dab
 #ifdef ENABLE_WAYLAND_SUPPORT
400dab
                                 if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) {
400dab
                                         /* we're going to fall back to X11, so try to autologin again
400dab
                                          */
400dab
                                         manager->priv->did_automatic_login = FALSE;
400dab
                                 }
400dab
 #endif
400dab
                         }
400dab
                         break;
400dab
                 default:
400dab
                         break;
400dab
         }
400dab
 
400dab
 }
400dab
 
400dab
 static void
400dab
 on_display_removed (GdmDisplayStore *display_store,
400dab
                     GdmDisplay      *display,
400dab
                     GdmManager      *manager)
400dab
 {
400dab
         char    *id;
400dab
 
400dab
         gdm_display_get_id (display, &id, NULL);
400dab
         g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
400dab
         g_free (id);
400dab
@@ -2292,61 +2295,61 @@ on_session_reauthentication_started (GdmSession *session,
400dab
                                      int         pid_of_caller,
400dab
                                      const char *address,
400dab
                                      GdmManager *manager)
400dab
 {
400dab
         GDBusMethodInvocation *invocation;
400dab
         gpointer               source_tag;
400dab
 
400dab
         g_debug ("GdmManager: reauthentication started");
400dab
 
400dab
         source_tag = GINT_TO_POINTER (pid_of_caller);
400dab
 
400dab
         invocation = g_hash_table_lookup (manager->priv->open_reauthentication_requests,
400dab
                                           source_tag);
400dab
 
400dab
         if (invocation != NULL) {
400dab
                 g_hash_table_steal (manager->priv->open_reauthentication_requests,
400dab
                                     source_tag);
400dab
                 gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
400dab
                                                                          invocation,
400dab
                                                                          address);
400dab
         }
400dab
 }
400dab
 
400dab
 static void
400dab
 clean_user_session (GdmSession *session)
400dab
 {
400dab
         g_object_set_data (G_OBJECT (session), "gdm-display", NULL);
400dab
         g_object_unref (session);
400dab
 }
400dab
 
400dab
-static GdmSession *
400dab
+static void
400dab
 create_user_session_for_display (GdmManager *manager,
400dab
                                  GdmDisplay *display,
400dab
                                  uid_t       allowed_user)
400dab
 {
400dab
         GdmSession *session;
400dab
         gboolean    display_is_local = FALSE;
400dab
         char       *display_name = NULL;
400dab
         char       *display_device = NULL;
400dab
         char       *remote_hostname = NULL;
400dab
         char       *display_auth_file = NULL;
400dab
         char       *display_seat_id = NULL;
400dab
         char       *display_id = NULL;
400dab
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
         char       *display_session_type = NULL;
400dab
         gboolean    greeter_is_wayland;
400dab
 #endif
400dab
 
400dab
         g_object_get (G_OBJECT (display),
400dab
                       "id", &display_id,
400dab
                       "x11-display-name", &display_name,
400dab
                       "is-local", &display_is_local,
400dab
                       "remote-hostname", &remote_hostname,
400dab
                       "x11-authority-file", &display_auth_file,
400dab
                       "seat-id", &display_seat_id,
400dab
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
                       "session-type", &display_session_type,
400dab
 #endif
400dab
                       NULL);
400dab
         display_device = get_display_device (manager, display);
400dab
 
400dab
@@ -2402,70 +2405,68 @@ create_user_session_for_display (GdmManager *manager,
400dab
                           "conversation-stopped",
400dab
                           G_CALLBACK (on_session_conversation_stopped),
400dab
                           manager);
400dab
         g_signal_connect (session,
400dab
                           "authentication-failed",
400dab
                           G_CALLBACK (on_session_authentication_failed),
400dab
                           manager);
400dab
         g_signal_connect (session,
400dab
                           "session-opened",
400dab
                           G_CALLBACK (on_user_session_opened),
400dab
                           manager);
400dab
         g_signal_connect (session,
400dab
                           "session-started",
400dab
                           G_CALLBACK (on_user_session_started),
400dab
                           manager);
400dab
         g_signal_connect (session,
400dab
                           "session-start-failed",
400dab
                           G_CALLBACK (on_session_start_failed),
400dab
                           manager);
400dab
         g_signal_connect (session,
400dab
                           "session-exited",
400dab
                           G_CALLBACK (on_user_session_exited),
400dab
                           manager);
400dab
         g_signal_connect (session,
400dab
                           "session-died",
400dab
                           G_CALLBACK (on_user_session_died),
400dab
                           manager);
400dab
         g_object_set_data (G_OBJECT (session), "gdm-display", display);
400dab
         g_object_set_data_full (G_OBJECT (display),
400dab
                                 "gdm-user-session",
400dab
-                                g_object_ref (session),
400dab
+                                session,
400dab
                                 (GDestroyNotify)
400dab
                                 clean_user_session);
400dab
 
400dab
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
         greeter_is_wayland = g_strcmp0 (display_session_type, "wayland") == 0;
400dab
         g_object_set (G_OBJECT (session), "ignore-wayland", !greeter_is_wayland, NULL);
400dab
 #endif
400dab
-
400dab
-        return session;
400dab
 }
400dab
 
400dab
 static void
400dab
 on_display_added (GdmDisplayStore *display_store,
400dab
                   const char      *id,
400dab
                   GdmManager      *manager)
400dab
 {
400dab
         GdmDisplay *display;
400dab
 
400dab
         display = gdm_display_store_lookup (display_store, id);
400dab
 
400dab
         if (display != NULL) {
400dab
                 g_dbus_object_manager_server_export (manager->priv->object_manager,
400dab
                                                      gdm_display_get_object_skeleton (display));
400dab
 
400dab
                 g_signal_connect (display, "notify::status",
400dab
                                   G_CALLBACK (on_display_status_changed),
400dab
                                   manager);
400dab
                 g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id);
400dab
         }
400dab
 }
400dab
 
400dab
 GQuark
400dab
 gdm_manager_error_quark (void)
400dab
 {
400dab
         static GQuark ret = 0;
400dab
         if (ret == 0) {
400dab
                 ret = g_quark_from_static_string ("gdm_manager_error");
400dab
         }
400dab
 
400dab
-- 
400dab
2.26.2
400dab