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

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