diff --git a/SOURCES/0001-display-Add-new-FAILING-state.patch b/SOURCES/0001-display-Add-new-FAILING-state.patch new file mode 100644 index 0000000..fd82498 --- /dev/null +++ b/SOURCES/0001-display-Add-new-FAILING-state.patch @@ -0,0 +1,219 @@ +From f7295f73f424e22eacb940c92e43326d75c901e1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 22 Jul 2024 14:58:47 -0400 +Subject: [PATCH 1/3] display: Add new FAILING state + +We need to be able to detect failure and quit plymouth before +reacting to the failure (and starting Xorg). + +This commit adds a new FAILING state that gets run before FAILED, +so things can be ordered properly +d# +--- + daemon/gdm-display.c | 1 + + daemon/gdm-display.h | 1 + + daemon/gdm-local-display-factory.c | 2 ++ + 3 files changed, 4 insertions(+) + +diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c +index 9438fe72c..0e6249896 100644 +--- a/daemon/gdm-display.c ++++ b/daemon/gdm-display.c +@@ -667,60 +667,61 @@ gdm_display_disconnect (GdmDisplay *self) + xcb_flush (priv->xcb_connection); + + g_clear_pointer (&priv->xcb_connection, xcb_disconnect); + } + + gboolean + gdm_display_unmanage (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + priv = gdm_display_get_instance_private (self); + + gdm_display_disconnect (self); + + if (priv->user_access_file != NULL) { + gdm_display_access_file_close (priv->user_access_file); + g_object_unref (priv->user_access_file); + priv->user_access_file = NULL; + } + + if (priv->access_file != NULL) { + gdm_display_access_file_close (priv->access_file); + g_object_unref (priv->access_file); + priv->access_file = NULL; + } + + if (!priv->session_registered) { + g_warning ("GdmDisplay: Session never registered, failing"); ++ _gdm_display_set_status (self, GDM_DISPLAY_FAILING); + _gdm_display_set_status (self, GDM_DISPLAY_FAILED); + } else { + _gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED); + } + + return TRUE; + } + + gboolean + gdm_display_get_id (GdmDisplay *self, + char **id, + GError **error) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + priv = gdm_display_get_instance_private (self); + if (id != NULL) { + *id = g_strdup (priv->id); + } + + return TRUE; + } + + gboolean + gdm_display_get_x11_display_name (GdmDisplay *self, + char **x11_display, + GError **error) + { +diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h +index ef3736cd3..bd048cd0d 100644 +--- a/daemon/gdm-display.h ++++ b/daemon/gdm-display.h +@@ -9,60 +9,61 @@ + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + + #ifndef __GDM_DISPLAY_H + #define __GDM_DISPLAY_H + + #include + #include + + G_BEGIN_DECLS + + #define GDM_TYPE_DISPLAY (gdm_display_get_type ()) + G_DECLARE_DERIVABLE_TYPE (GdmDisplay, gdm_display, GDM, DISPLAY, GObject) + + typedef enum { + GDM_DISPLAY_UNMANAGED = 0, + GDM_DISPLAY_PREPARED, + GDM_DISPLAY_MANAGED, + GDM_DISPLAY_WAITING_TO_FINISH, + GDM_DISPLAY_FINISHED, ++ GDM_DISPLAY_FAILING, + GDM_DISPLAY_FAILED, + } GdmDisplayStatus; + + struct _GdmDisplayClass + { + GObjectClass parent_class; + + /* methods */ + gboolean (*prepare) (GdmDisplay *display); + void (*manage) (GdmDisplay *self); + }; + + typedef enum + { + GDM_DISPLAY_ERROR_GENERAL, + GDM_DISPLAY_ERROR_GETTING_USER_INFO, + GDM_DISPLAY_ERROR_GETTING_SESSION_INFO, + } GdmDisplayError; + + #define GDM_DISPLAY_ERROR gdm_display_error_quark () + + GQuark gdm_display_error_quark (void); + + int gdm_display_get_status (GdmDisplay *display); + time_t gdm_display_get_creation_time (GdmDisplay *display); + char * gdm_display_open_session_sync (GdmDisplay *display, + GPid pid_of_caller, + uid_t uid_of_caller, + GCancellable *cancellable, + GError **error); +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index 61522dbf0..5dc0aebe5 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -544,60 +544,62 @@ on_display_status_changed (GdmDisplay *display, + "is-initial", &is_initial, + "is-local", &is_local, + "session-type", &session_type, + "session-class", &session_class, + NULL); + + status = gdm_display_get_status (display); + + g_debug ("GdmLocalDisplayFactory: display status changed: %d", status); + switch (status) { + case GDM_DISPLAY_FINISHED: + /* remove the display number from factory->used_display_numbers + so that it may be reused */ + if (num != -1) { + g_hash_table_remove (factory->used_display_numbers, GUINT_TO_POINTER (num)); + } + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + + /* if this is a local display, do a full resync. Only + * seats without displays will get created anyway. This + * ensures we get a new login screen when the user logs out, + * if there isn't one. + */ + if (is_local && g_strcmp0 (session_class, "greeter") != 0) { + /* reset num failures */ + factory->num_failures = 0; + + gdm_local_display_factory_sync_seats (factory); + } + break; ++ case GDM_DISPLAY_FAILING: ++ break; + case GDM_DISPLAY_FAILED: + /* leave the display number in factory->used_display_numbers + so that it doesn't get reused */ + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + + /* Create a new equivalent display if it was static */ + if (is_local) { + + factory->num_failures++; + + /* oh shit */ + if (factory->num_failures > MAX_DISPLAY_FAILURES) + g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors"); + else + ensure_display_for_seat (factory, seat_id); + } + break; + case GDM_DISPLAY_UNMANAGED: + break; + case GDM_DISPLAY_PREPARED: + break; + case GDM_DISPLAY_MANAGED: + #if defined(ENABLE_USER_DISPLAY_SERVER) + g_signal_connect_object (display, + "notify::session-registered", + G_CALLBACK (on_session_registered_cb), + factory, + 0); + #endif + break; +-- +2.44.0 + diff --git a/SOURCES/0001-gdm-session-Force-reuse-vt-mode-for-legacy-Xorg-mode.patch b/SOURCES/0001-gdm-session-Force-reuse-vt-mode-for-legacy-Xorg-mode.patch index c2f7806..4b71ddd 100644 --- a/SOURCES/0001-gdm-session-Force-reuse-vt-mode-for-legacy-Xorg-mode.patch +++ b/SOURCES/0001-gdm-session-Force-reuse-vt-mode-for-legacy-Xorg-mode.patch @@ -1,7 +1,7 @@ From bcab8852cf7249a2220f6c737f7bb8a17b99249a Mon Sep 17 00:00:00 2001 From: rpm-build Date: Mon, 27 Nov 2023 15:29:09 -0500 -Subject: [PATCH] gdm-session: Force reuse vt mode for legacy Xorg mode +Subject: [PATCH 1/2] gdm-session: Force reuse vt mode for legacy Xorg mode In the legacy Xorg mode, the X session and user session are supposed to use the same VT. diff --git a/SOURCES/0001-local-display-factory-Stall-startup-until-main-graph.patch b/SOURCES/0001-local-display-factory-Stall-startup-until-main-graph.patch index 33a411c..d88da45 100644 --- a/SOURCES/0001-local-display-factory-Stall-startup-until-main-graph.patch +++ b/SOURCES/0001-local-display-factory-Stall-startup-until-main-graph.patch @@ -1,4 +1,4 @@ -From e5b3467412874d27c311253e3d5d7e65a61d12a4 Mon Sep 17 00:00:00 2001 +From e88779b0785fe781608b10478ae092e8fd79ae0b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 1 Mar 2022 13:25:02 -0500 Subject: [PATCH 1/4] local-display-factory: Stall startup until main graphics @@ -27,13 +27,13 @@ up and running before proceeding to start a login screen. Closes: https://gitlab.gnome.org/GNOME/gdm/-/issues/763 --- - daemon/gdm-local-display-factory.c | 164 ++++++++++++++++++++++++++--- + daemon/gdm-local-display-factory.c | 168 ++++++++++++++++++++++++++--- daemon/meson.build | 4 + meson.build | 2 + - 4 files changed, 159 insertions(+), 12 deletions(-) + 3 files changed, 162 insertions(+), 12 deletions(-) diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c -index c00e1c47..0b1d3482 100644 +index ca14c31f5..56be1d9db 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -1,100 +1,112 @@ @@ -398,7 +398,7 @@ index c00e1c47..0b1d3482 100644 } g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though system says it doesn't support graphics!"); -@@ -1138,113 +1240,151 @@ on_vt_changed (GIOChannel *source, +@@ -1138,113 +1244,151 @@ on_vt_changed (GIOChannel *source, if (factory->wait_to_finish_timeout_id != 0) { g_debug ("GdmLocalDisplayFactory: deferring previous login screen clean up operation"); g_source_remove (factory->wait_to_finish_timeout_id); @@ -551,7 +551,7 @@ index c00e1c47..0b1d3482 100644 on_display_added (GdmDisplayStore *display_store, const char *id, diff --git a/daemon/meson.build b/daemon/meson.build -index 2e61b644..41f30abe 100644 +index 2e61b6447..41f30abef 100644 --- a/daemon/meson.build +++ b/daemon/meson.build @@ -177,37 +177,41 @@ gdm_daemon_sources = files( @@ -597,7 +597,7 @@ index 2e61b644..41f30abe 100644 install_dir: get_option('sbindir') ) diff --git a/meson.build b/meson.build -index 02d609dc..05d8da41 100644 +index 02d609dc0..05d8da412 100644 --- a/meson.build +++ b/meson.build @@ -11,60 +11,61 @@ i18n = import('i18n') @@ -725,5 +725,5 @@ index 02d609dc..05d8da41 100644 subdir('chooser') endif -- -2.34.1 +2.40.0 diff --git a/SOURCES/0001-session-settings-Explicitly-cache-remote-users.patch b/SOURCES/0001-session-settings-Explicitly-cache-remote-users.patch new file mode 100644 index 0000000..b5da396 --- /dev/null +++ b/SOURCES/0001-session-settings-Explicitly-cache-remote-users.patch @@ -0,0 +1,45 @@ +From cf4664891ede9648d096569900e8b95abd91a633 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 7 Apr 2022 12:44:10 -0400 +Subject: [PATCH] session-settings: Explicitly cache remote users + +Right now a user's cache file won't get written out if they are logging +in with entirely default settings. + +This means remote users have to type in their usernames manually until +they change their session. + +This commit explicitly caches remote users. + +Closes: https://gitlab.gnome.org/GNOME/gdm/-/issues/743 +--- + daemon/gdm-session-settings.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c +index 5b64cb65b..ef5d72e7f 100644 +--- a/daemon/gdm-session-settings.c ++++ b/daemon/gdm-session-settings.c +@@ -406,6 +406,19 @@ gdm_session_settings_save (GdmSessionSettings *settings, + if (settings->priv->language_name != NULL) { + act_user_set_language (user, settings->priv->language_name); + } ++ ++ if (!act_user_is_local_account (user)) { ++ g_autoptr (GError) error = NULL; ++ ++ act_user_manager_cache_user (settings->priv->user_manager, username, &error); ++ ++ if (error != NULL) { ++ g_debug ("GdmSessionSettings: Could not locally cache remote user: %s", error->message); ++ g_object_unref (user); ++ return FALSE; ++ } ++ ++ } + g_object_unref (user); + + return TRUE; +-- +GitLab + diff --git a/SOURCES/0002-local-display-factory-Fix-user-switching-with-legacy.patch b/SOURCES/0002-local-display-factory-Fix-user-switching-with-legacy.patch new file mode 100644 index 0000000..42465d5 --- /dev/null +++ b/SOURCES/0002-local-display-factory-Fix-user-switching-with-legacy.patch @@ -0,0 +1,384 @@ +From 510566699c480226b189215c6222f7e72979baf8 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 22 May 2024 14:05:20 -0400 +Subject: [PATCH 2/2] local-display-factory: Fix user switching with legacy + xorg + +legacy-xorg sessions currently fail to completely user switch. + +This is because the wrong session types are attached to the generated +login screen display. + +This commit refactors the code so the same session types are used for +user switching as are used for the initial login. +--- + daemon/gdm-local-display-factory.c | 78 +++++++++++++++++++++--------- + 1 file changed, 54 insertions(+), 24 deletions(-) + +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index 7447b985a..4efbf0a6d 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -331,118 +331,131 @@ gdm_local_display_factory_get_session_types (GdmLocalDisplayFactory *factory, + if (display_server_enabled (factory, fallback_display_server)) + g_ptr_array_add (session_types_array, (gpointer) get_session_type_for_display_server (factory, fallback_display_server)); + + if (session_types_array->len == 0) + return NULL; + + g_ptr_array_add (session_types_array, NULL); + + session_types = g_strdupv ((char **) session_types_array->pdata); + + return session_types; + } + + static void + on_display_disposed (GdmLocalDisplayFactory *factory, + GdmDisplay *display) + { + g_debug ("GdmLocalDisplayFactory: Display %p disposed", display); + } + + static void + store_display (GdmLocalDisplayFactory *factory, + GdmDisplay *display) + { + GdmDisplayStore *store; + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + gdm_display_store_add (store, display); + } + ++static GdmDisplay * ++create_legacy_xorg_display (GdmLocalDisplayFactory *factory) ++{ ++ guint32 display_number; ++ const char *session_types[] = { "x11", NULL }; ++ GdmDisplay *display; ++ ++ display_number = take_next_display_number (factory); ++ ++ g_debug ("GdmLocalDisplayFactory: Creating legacy Xorg display at :%d", display_number); ++ ++ display = gdm_legacy_display_new (display_number); ++ g_object_set (G_OBJECT (display), ++ "session-type", session_types[0], ++ "supported-session-types", session_types, ++ NULL); ++ ++ return display; ++} ++ + /* + Example: + dbus-send --system --dest=org.gnome.DisplayManager \ + --type=method_call --print-reply --reply-timeout=2000 \ + /org/gnome/DisplayManager/Manager \ + org.gnome.DisplayManager.Manager.GetDisplays + */ + gboolean + gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory, + char **id, + GError **error) + { + gboolean ret; + GdmDisplay *display = NULL; + gboolean is_initial = FALSE; + const char *session_type; + g_autofree gchar *preferred_display_server = NULL; + + g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE); + + ret = FALSE; + + g_debug ("GdmLocalDisplayFactory: Creating transient display"); + + preferred_display_server = get_preferred_display_server (factory); + + #ifdef ENABLE_USER_DISPLAY_SERVER + if (g_strcmp0 (preferred_display_server, "wayland") == 0 || + g_strcmp0 (preferred_display_server, "xorg") == 0) { + g_auto(GStrv) session_types = NULL; + + session_types = gdm_local_display_factory_get_session_types (factory, FALSE); + + if (session_types == NULL) { + g_set_error_literal (error, + GDM_DISPLAY_ERROR, + GDM_DISPLAY_ERROR_GENERAL, + "Both Wayland and Xorg are unavailable"); + return FALSE; + } + + display = gdm_local_display_new (); + g_object_set (G_OBJECT (display), + "session-type", session_types[0], + "supported-session-types", session_types, + NULL); + is_initial = TRUE; + } + #endif +- if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) { +- if (display == NULL) { +- guint32 num; +- +- num = take_next_display_number (factory); +- +- display = gdm_legacy_display_new (num); +- } +- } ++ if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) ++ display = create_legacy_xorg_display (factory); + + if (display == NULL) { + g_set_error_literal (error, + GDM_DISPLAY_ERROR, + GDM_DISPLAY_ERROR_GENERAL, + "Invalid preferred display server configured"); + return FALSE; + } + + g_object_set (display, + "seat-id", "seat0", + "allow-timed-login", FALSE, + "is-initial", is_initial, + NULL); + + store_display (factory, display); + + if (! gdm_display_manage (display)) { + display = NULL; + goto out; + } + + if (! gdm_display_get_id (display, id, NULL)) { + display = NULL; + goto out; + } + + ret = TRUE; + out: + /* ref either held by store or not at all */ +@@ -591,70 +604,87 @@ on_display_status_changed (GdmDisplay *display, + case GDM_DISPLAY_WAITING_TO_FINISH: + break; + default: + g_assert_not_reached (); + break; + } + + g_free (seat_id); + g_free (session_type); + g_free (session_class); + } + + static gboolean + lookup_by_seat_id (const char *id, + GdmDisplay *display, + gpointer user_data) + { + const char *looking_for = user_data; + char *current; + gboolean res; + + g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL); + + res = g_strcmp0 (current, looking_for) == 0; + + g_free(current); + + return res; + } + ++static gboolean ++lookup_initial_display (const char *id, ++ GdmDisplay *display) ++{ ++ gboolean is_initial = FALSE; ++ int status; ++ ++ status = gdm_display_get_status (display); ++ ++ if (status != GDM_DISPLAY_PREPARED && status != GDM_DISPLAY_MANAGED) ++ return FALSE; ++ ++ g_object_get (G_OBJECT (display), "is-initial", &is_initial, NULL); ++ ++ return is_initial; ++} ++ + static gboolean + lookup_prepared_display_by_seat_id (const char *id, + GdmDisplay *display, + gpointer user_data) + { + int status; + + status = gdm_display_get_status (display); + +- if (status != GDM_DISPLAY_PREPARED) ++ if (status != GDM_DISPLAY_PREPARED && status != GDM_DISPLAY_MANAGED) + return FALSE; + + return lookup_by_seat_id (id, display, user_data); + } + + #ifdef HAVE_UDEV + static gboolean + udev_is_settled (GdmLocalDisplayFactory *factory) + { + g_autoptr (GUdevEnumerator) enumerator = NULL; + GList *devices; + GList *node; + + gboolean is_settled = FALSE; + + if (factory->seat0_has_platform_graphics) { + g_debug ("GdmLocalDisplayFactory: udev settled, platform graphics enabled."); + return TRUE; + } + + if (factory->seat0_has_boot_up_graphics) { + g_debug ("GdmLocalDisplayFactory: udev settled, boot up graphics available."); + return TRUE; + } + + if (factory->seat0_graphics_check_timed_out) { + g_debug ("GdmLocalDisplayFactory: udev timed out, proceeding anyway."); + return TRUE; + } + +@@ -834,115 +864,115 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, + /* It is not yet time to force X11 fallback. */ + g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout."); + } + + return; + } + + g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though system says it doesn't support graphics!"); + g_debug ("GdmLocalDisplayFactory: This might indicate an issue where the framebuffer device is not tagged as master-of-seat in udev."); + seat_supports_graphics = TRUE; + wayland_enabled = FALSE; + g_strfreev (session_types); + session_types = g_strdupv ((char **) legacy_session_types); + } else { + g_clear_handle_id (&factory->seat0_graphics_check_timeout_id, g_source_remove); + } + } + + if (!seat_supports_graphics) + return; + + if (session_types != NULL) + g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested", + session_types[0], seat_id); + else if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) + g_debug ("GdmLocalDisplayFactory: Legacy Xorg login display for seat %s requested", + seat_id); + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + +- if (is_seat0) +- display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id); +- else ++ if (is_seat0) { ++ display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id); ++ if (display != NULL && g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) { ++ GdmDisplay *initial_display = NULL; ++ ++ initial_display = gdm_display_store_find (store, lookup_initial_display, (gpointer) NULL); ++ ++ if (initial_display == NULL) ++ display = NULL; ++ } ++ } else { + display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id); ++ } + + /* Ensure we don't create the same display more than once */ + if (display != NULL) { + g_debug ("GdmLocalDisplayFactory: display already created"); + return; + } + + /* If we already have a login window, switch to it */ + if (gdm_get_login_window_session_id (seat_id, &login_session_id)) { + GdmDisplay *display; + + display = gdm_display_store_find (store, + lookup_by_session_id, + (gpointer) login_session_id); + if (display != NULL && + (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED || + gdm_display_get_status (display) == GDM_DISPLAY_WAITING_TO_FINISH)) { + g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL); + g_debug ("GdmLocalDisplayFactory: session %s found, activating.", + login_session_id); + gdm_activate_session_by_id (factory->connection, seat_id, login_session_id); + return; + } + } + + g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id); + + #ifdef ENABLE_USER_DISPLAY_SERVER + if (g_strcmp0 (preferred_display_server, "wayland") == 0 || + g_strcmp0 (preferred_display_server, "xorg") == 0) { + if (is_seat0) { + display = gdm_local_display_new (); + g_object_set (G_OBJECT (display), + "session-type", session_types[0], + "supported-session-types", session_types, + NULL); + } + } + #endif + +- if (display == NULL) { +- guint32 num; +- +- num = take_next_display_number (factory); +- +- display = gdm_legacy_display_new (num); +- g_object_set (G_OBJECT (display), +- "session-type", legacy_session_types[0], +- "supported-session-types", legacy_session_types, +- NULL); +- } ++ if (display == NULL) ++ display = create_legacy_xorg_display (factory); + + g_object_set (display, "seat-id", seat_id, NULL); + g_object_set (display, "is-initial", is_seat0, NULL); + + store_display (factory, display); + + /* let store own the ref */ + g_object_unref (display); + + if (! gdm_display_manage (display)) { + gdm_display_unmanage (display); + } + + return; + } + + static void + delete_display (GdmLocalDisplayFactory *factory, + const char *seat_id) { + + GdmDisplayStore *store; + + g_debug ("GdmLocalDisplayFactory: Removing used_display_numbers on seat %s", seat_id); + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + gdm_display_store_foreach_remove (store, lookup_by_seat_id, (gpointer) seat_id); + } + + static gboolean + gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory) +-- +2.40.0 + diff --git a/SOURCES/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch b/SOURCES/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch new file mode 100644 index 0000000..5c5d8bf --- /dev/null +++ b/SOURCES/0002-manager-Quit-plymouth-at-first-sign-of-failure.patch @@ -0,0 +1,375 @@ +From 27c78eb4efc598281eed9cd521ba1b05ee08e3d2 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 22 Jul 2024 14:59:43 -0400 +Subject: [PATCH 2/3] manager: Quit plymouth at first sign of failure + +Rather than quit plymouth after a replacement X server is already +started, this commit does it a bit earlier, so there is a battle +of display servers. +--- + common/gdm-address.c | 4 ++-- + daemon/gdm-manager.c | 5 +++++ + daemon/gdm-xdmcp-display-factory.c | 10 ++++++---- + 3 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/common/gdm-address.c b/common/gdm-address.c +index a8b73e286..3a507d0af 100644 +--- a/common/gdm-address.c ++++ b/common/gdm-address.c +@@ -107,61 +107,61 @@ gdm_address_new_from_sockaddr (struct sockaddr *sa, + + g_return_val_if_fail (sa != NULL, NULL); + g_return_val_if_fail (size >= sizeof (struct sockaddr), NULL); + g_return_val_if_fail (size <= sizeof (struct sockaddr_storage), NULL); + + addr = g_new0 (GdmAddress, 1); + addr->ss = g_new0 (struct sockaddr_storage, 1); + memcpy (addr->ss, sa, size); + + return addr; + } + + /** + * gdm_address_get_sockaddr_storage: + * @address: A #GdmAddress + * + * This function tanslates @address into a equivalent + * sockaddr_storage + * + * Return value: A newly allocated sockaddr_storage structure the caller must free + * or %NULL if @address did not point to a valid #GdmAddress. + **/ + struct sockaddr_storage * + gdm_address_get_sockaddr_storage (GdmAddress *address) + { + struct sockaddr_storage *ss; + + g_return_val_if_fail (address != NULL, NULL); + g_return_val_if_fail (address->ss != NULL, NULL); + +- ss = g_memdup (address->ss, sizeof (struct sockaddr_storage)); ++ ss = g_memdup2 (address->ss, sizeof (struct sockaddr_storage)); + + return ss; + } + + struct sockaddr_storage * + gdm_address_peek_sockaddr_storage (GdmAddress *address) + { + g_return_val_if_fail (address != NULL, NULL); + + return address->ss; + } + + static gboolean + v4_v4_equal (const struct sockaddr_in *a, + const struct sockaddr_in *b) + { + return a->sin_addr.s_addr == b->sin_addr.s_addr; + } + + #ifdef ENABLE_IPV6 + static gboolean + v6_v6_equal (struct sockaddr_in6 *a, + struct sockaddr_in6 *b) + { + return IN6_ARE_ADDR_EQUAL (&a->sin6_addr, &b->sin6_addr); + } + #endif + + #define SA(__s) ((struct sockaddr *) __s) + #define SIN(__s) ((struct sockaddr_in *) __s) +@@ -502,50 +502,50 @@ gdm_address_is_local (GdmAddress *address) + + while (list != NULL) { + GdmAddress *addr = list->data; + + if (gdm_address_equal (address, addr)) { + return TRUE; + } + + list = list->next; + } + + return FALSE; + } + + /** + * gdm_address_copy: + * @address: A #GdmAddress. + * + * Duplicates @address. + * + * Return value: Duplicated @address or %NULL if @address was not valid. + **/ + GdmAddress * + gdm_address_copy (GdmAddress *address) + { + GdmAddress *addr; + + g_return_val_if_fail (address != NULL, NULL); + + addr = g_new0 (GdmAddress, 1); +- addr->ss = g_memdup (address->ss, sizeof (struct sockaddr_storage)); ++ addr->ss = g_memdup2 (address->ss, sizeof (struct sockaddr_storage)); + + return addr; + } + + /** + * gdm_address_free: + * @address: A #GdmAddress. + * + * Frees the memory allocated for @address. + **/ + void + gdm_address_free (GdmAddress *address) + { + g_return_if_fail (address != NULL); + + g_free (address->ss); + g_free (address); + } + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 08c3cc177..100b967fb 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -1551,70 +1551,75 @@ on_display_status_changed (GdmDisplay *display, + + g_object_get (display, + "is-local", &display_is_local, + NULL); + quit_plymouth = display_is_local && manager->priv->plymouth_is_running; + #endif + + g_object_get (display, + "x11-display-number", &display_number, + "session-type", &session_type, + "doing-initial-setup", &doing_initial_setup, + NULL); + + status = gdm_display_get_status (display); + + switch (status) { + case GDM_DISPLAY_PREPARED: + case GDM_DISPLAY_MANAGED: + if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) || + (display_number != -1 && status == GDM_DISPLAY_MANAGED)) { + char *session_class; + + g_object_get (display, + "session-class", &session_class, + NULL); + if (g_strcmp0 (session_class, "greeter") == 0) + set_up_session (manager, display); + g_free (session_class); + } + break; ++ ++ case GDM_DISPLAY_FAILING: + case GDM_DISPLAY_FAILED: + case GDM_DISPLAY_UNMANAGED: + case GDM_DISPLAY_FINISHED: + #ifdef WITH_PLYMOUTH + if (quit_plymouth) { + plymouth_quit_without_transition (); + manager->priv->plymouth_is_running = FALSE; + } + #endif + ++ if (status == GDM_DISPLAY_FAILING) ++ break; ++ + g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL); + + if (display == manager->priv->automatic_login_display) { + g_clear_weak_pointer (&manager->priv->automatic_login_display); + + manager->priv->did_automatic_login = TRUE; + + #ifdef ENABLE_WAYLAND_SUPPORT + if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) { + /* we're going to fall back to X11, so try to autologin again + */ + manager->priv->did_automatic_login = FALSE; + } + #endif + } + break; + default: + break; + } + + } + + static void + on_display_removed (GdmDisplayStore *display_store, + GdmDisplay *display, + GdmManager *manager) + { + char *id; + + gdm_display_get_id (display, &id, NULL); +diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c +index abb58faeb..e82cfe1b4 100644 +--- a/daemon/gdm-xdmcp-display-factory.c ++++ b/daemon/gdm-xdmcp-display-factory.c +@@ -891,87 +891,87 @@ gdm_xdmcp_send_unwilling (GdmXdmcpDisplayFactory *factory, + header.length = 4 + factory->servhost.length + status.length; + header.version = XDM_PROTOCOL_VERSION; + XdmcpWriteHeader (&factory->buf, &header); + + XdmcpWriteARRAY8 (&factory->buf, &factory->servhost); + XdmcpWriteARRAY8 (&factory->buf, &status); + XdmcpFlush (factory->socket_fd, + &factory->buf, + (XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address), + (int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address))); + + last_time = time (NULL); + } + + #define SIN(__s) ((struct sockaddr_in *) __s) + #define SIN6(__s) ((struct sockaddr_in6 *) __s) + + static void + set_port_for_request (GdmAddress *address, + ARRAY8 *port) + { + struct sockaddr_storage *ss; + + ss = gdm_address_peek_sockaddr_storage (address); + + /* we depend on this being 2 elsewhere as well */ + port->length = 2; + + switch (ss->ss_family) { + case AF_INET: +- port->data = (CARD8 *)g_memdup (&(SIN (ss)->sin_port), port->length); ++ port->data = (CARD8 *)g_memdup2 (&(SIN (ss)->sin_port), port->length); + break; + case AF_INET6: +- port->data = (CARD8 *)g_memdup (&(SIN6 (ss)->sin6_port), port->length); ++ port->data = (CARD8 *)g_memdup2 (&(SIN6 (ss)->sin6_port), port->length); + break; + default: + port->data = NULL; + break; + } + } + + static void + set_address_for_request (GdmAddress *address, + ARRAY8 *addr) + { + struct sockaddr_storage *ss; + + ss = gdm_address_peek_sockaddr_storage (address); + + switch (ss->ss_family) { + case AF_INET: + addr->length = sizeof (struct in_addr); +- addr->data = g_memdup (&SIN (ss)->sin_addr, addr->length); ++ addr->data = g_memdup2 (&SIN (ss)->sin_addr, addr->length); + break; + case AF_INET6: + addr->length = sizeof (struct in6_addr); +- addr->data = g_memdup (&SIN6 (ss)->sin6_addr, addr->length); ++ addr->data = g_memdup2 (&SIN6 (ss)->sin6_addr, addr->length); + break; + default: + addr->length = 0; + addr->data = NULL; + break; + } + + } + + static void + gdm_xdmcp_send_forward_query (GdmXdmcpDisplayFactory *factory, + IndirectClient *ic, + GdmAddress *address, + GdmAddress *display_address, + ARRAYofARRAY8Ptr authlist) + { + XdmcpHeader header; + int i; + ARRAY8 addr; + ARRAY8 port; + char *host; + char *serv; + + g_assert (ic != NULL); + g_assert (ic->chosen_address != NULL); + + host = NULL; + gdm_address_get_numeric_info (ic->chosen_address, &host, NULL); + g_debug ("GdmXdmcpDisplayFactory: Sending forward query to %s", + host ? host : "(null)"); +@@ -2063,60 +2063,62 @@ on_display_status_changed (GdmDisplay *display, + { + int status; + GdmLaunchEnvironment *launch_environment; + GdmSession *session; + GdmAddress *address; + gint32 session_number; + int display_number; + + launch_environment = NULL; + g_object_get (display, "launch-environment", &launch_environment, NULL); + + session = NULL; + if (launch_environment != NULL) { + session = gdm_launch_environment_get_session (launch_environment); + } + + status = gdm_display_get_status (display); + + g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status); + switch (status) { + case GDM_DISPLAY_FINISHED: + g_object_get (display, + "remote-address", &address, + "x11-display-number", &display_number, + "session-number", &session_number, + NULL); + gdm_xdmcp_send_alive (factory, address, display_number, session_number); + + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + break; ++ case GDM_DISPLAY_FAILING: ++ break; + case GDM_DISPLAY_FAILED: + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + break; + case GDM_DISPLAY_UNMANAGED: + if (session != NULL) { + g_signal_handlers_disconnect_by_func (G_OBJECT (session), + G_CALLBACK (on_client_disconnected), + display); + } + break; + case GDM_DISPLAY_PREPARED: + break; + case GDM_DISPLAY_MANAGED: + if (session != NULL) { + g_signal_connect_object (G_OBJECT (session), + "client-disconnected", + G_CALLBACK (on_client_disconnected), + display, G_CONNECT_SWAPPED); + g_signal_connect_object (G_OBJECT (session), + "disconnected", + G_CALLBACK (on_client_disconnected), + display, G_CONNECT_SWAPPED); + } + break; + default: + g_assert_not_reached (); + break; + } + + g_clear_object (&launch_environment); +-- +2.44.0 + diff --git a/SOURCES/0003-manager-Quit-plymouth-synchronously.patch b/SOURCES/0003-manager-Quit-plymouth-synchronously.patch new file mode 100644 index 0000000..160e870 --- /dev/null +++ b/SOURCES/0003-manager-Quit-plymouth-synchronously.patch @@ -0,0 +1,94 @@ +From 190a9f31446ddab66c8b5c2e246a6253f85bde76 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 24 Jul 2024 08:40:08 -0400 +Subject: [PATCH 3/3] manager: Quit plymouth synchronously + +Plymouth needs to finish quitting before we start Xorg, so we can't +run it async. This command makes sure it gets run synchronously. +--- + daemon/gdm-manager.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 100b967fb..d4ad949fe 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -167,67 +167,72 @@ plymouth_prepare_for_transition (void) + + error = NULL; + res = g_spawn_command_line_sync ("plymouth deactivate", + NULL, NULL, NULL, &error); + if (! res) { + g_warning ("Could not deactivate plymouth: %s", error->message); + g_error_free (error); + } + } + + static gboolean + plymouth_quit_with_transition (void) + { + gboolean res; + GError *error; + + error = NULL; + res = g_spawn_command_line_async ("plymouth quit --retain-splash", &error); + if (! res) { + g_warning ("Could not quit plymouth: %s", error->message); + g_error_free (error); + } + + return G_SOURCE_REMOVE; + } + + static void + plymouth_quit_without_transition (void) + { + gboolean res; +- GError *error; ++ g_autoptr (GError) error = NULL; ++ g_autofree char *standard_error = NULL; ++ int wait_status = 0; + + error = NULL; +- res = g_spawn_command_line_async ("plymouth quit", &error); ++ res = g_spawn_command_line_sync ("plymouth quit", NULL, &standard_error, &wait_status, &error); + if (! res) { + g_warning ("Could not quit plymouth: %s", error->message); +- g_error_free (error); ++ } else if (!WIFEXITED (wait_status) || WEXITSTATUS (wait_status) != 0) { ++ g_warning ("plymouth errored on quit command%s%s", ++ standard_error? ":" : "", ++ standard_error?: ""); + } + } + #endif + + static char * + get_session_id_for_pid (pid_t pid, + GError **error) + { + char *session, *gsession; + int ret; + + session = NULL; + ret = sd_pid_get_session (pid, &session); + if (ret < 0) { + g_set_error (error, + GDM_DISPLAY_ERROR, + GDM_DISPLAY_ERROR_GETTING_SESSION_INFO, + "Error getting session id from systemd: %s", + g_strerror (-ret)); + return NULL; + } + + if (session != NULL) { + gsession = g_strdup (session); + free (session); + + return gsession; + } else { + return NULL; + } +-- +2.44.0 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index 30a8d20..01a067a 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -11,7 +11,7 @@ Name: gdm Epoch: 1 Version: 40.1 -Release: 23%{?dist} +Release: 27%{?dist} Summary: The GNOME Display Manager License: GPLv2+ @@ -43,7 +43,7 @@ Patch60001: 0001-session-settings-Fetch-session-from-user-even-if-use.patch Patch70001: 0001-manager-Fix-btmp-record-accounting.patch -Patch80001: 0001-gdm-session-Force-reuse-vt-mode-for-legacy-Xorg-mode.patch +Patch80002: 0001-session-settings-Explicitly-cache-remote-users.patch # Latest udev rules and support code Patch90001: 0001-local-display-factory-Stall-startup-until-main-graph.patch @@ -51,6 +51,13 @@ Patch90002: 0002-common-Add-API-to-reload-settings-from-disk.patch Patch90003: 0003-common-Reload-settings-when-graphics-initialize.patch Patch90004: 0004-data-Use-latest-upstream-udev-rules.patch +Patch100001: 0001-gdm-session-Force-reuse-vt-mode-for-legacy-Xorg-mode.patch +Patch100002: 0002-local-display-factory-Fix-user-switching-with-legacy.patch + +Patch110001: 0001-display-Add-new-FAILING-state.patch +Patch110002: 0002-manager-Quit-plymouth-at-first-sign-of-failure.patch +Patch110003: 0003-manager-Quit-plymouth-synchronously.patch + # Non-upstreamable workarounds Patch66610001: 0001-data-reap-gdm-sessions-on-shutdown.patch @@ -353,6 +360,23 @@ dconf update || : %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Wed Jul 24 2024 Ray Strode - 40.1-27 +- More fixes with wayland->xorg fallback + Related: RHEL-35045 + Resolves: RHEL-50393 + +* Tue Jul 23 2024 Ray Strode - 40.1-26 +- Fix failure doing wayland->xorg fallback + Related: RHEL-35045 + +* Wed May 01 2024 Ray Strode - 40.1-25 +- Fix user switching with PreferredDisplayServer=legacy-xorg + Related: RHEL-29845 + +* Tue Jan 16 2024 Andrew Lukoshko - 40.1-24 +- Explicitly cache remote users + Resolves: RHEL-21791 + * Fri Dec 15 2023 Ray Strode - 40.1-23 - Make /var/log/gdm tmpfiles.d snippet match files manifest to fix installability test