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

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