From 84adb87a6b0cc728ffd895b2c057b23a41b67b90 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 05 2022 10:13:08 +0000 Subject: import gdm-40.1-13.el9_0.2 --- diff --git a/SOURCES/0001-data-disable-wayland-on-certain-hardware.patch b/SOURCES/0001-data-disable-wayland-on-certain-hardware.patch deleted file mode 100644 index 3391cbf..0000000 --- a/SOURCES/0001-data-disable-wayland-on-certain-hardware.patch +++ /dev/null @@ -1,58 +0,0 @@ -From db206f3b4626dda65cf5517d2ae1ab633d791fef Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Mon, 11 Feb 2019 18:14:07 -0500 -Subject: [PATCH] data: disable wayland on certain hardware - -We're having issues with wayland on passthrough to virt -setups and with the vendor nvidia driver on hybrid graphics -setups, so disable it in those cases. ---- - data/61-gdm.rules.in | 36 ++++++++++++++++++++++++++++++++---- - 1 file changed, 32 insertions(+), 4 deletions(-) - -diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in -index b1da191f8..d863a4a4d 100644 ---- a/data/61-gdm.rules.in -+++ b/data/61-gdm.rules.in -@@ -1,6 +1,34 @@ - # disable Wayland on Hi1710 chipsets --ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" --# disable Wayland when using the proprietary nvidia driver --DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ -+# disable Wayland on Matrox chipsets -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ -+# disable Wayland on aspeed chipsets -+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ -+# disable Wayland on hybrid systems with vendor nvidia driver -+# default to Xorg on single gpu vendor nvidia systems -+DRIVER=="nvidia", ENV{GDM_HAS_VENDOR_NVIDIA_DRIVER}="1" -+DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon PreferredDisplayServer xorg" -+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_NVIDIA_DRIVER}=="1", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nvidia_drm", ATTR{parameters/modeset}=="N", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ -+# disable Wayland on passthrough graphics setups for now (assumes passthrough if -+# there is more than one card, and one of the cards is virt: cirrus, bochs, qxl) -+ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", ENV{GDM_HAS_VIRTUAL_GPU}="1" -+ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", ENV{GDM_HAS_VIRTUAL_GPU}="1" -+ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", ENV{GDM_HAS_VIRTUAL_GPU}="1" -+ -+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_VIRTUAL_GPU}=="1", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ - # disable Wayland if modesetting is disabled --IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" --- -2.31.1 - 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 new file mode 100644 index 0000000..33a411c --- /dev/null +++ b/SOURCES/0001-local-display-factory-Stall-startup-until-main-graph.patch @@ -0,0 +1,729 @@ +From e5b3467412874d27c311253e3d5d7e65a61d12a4 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 + card is ready + +At the moment, GDM waits until systemd says the system supports +graphics (via the CanGraphical logind property). + +Unfortunately, this property isn't really what we need, since it flips +to true when *any* graphics are available, not when the main graphics +for the system are ready. + +This is a problem on hybrid graphics systems, if one card is slower to +load than another. In particular, the vendor nvidia driver can be slow +to load because it has multiple kernel modules it loads in series. + +Indeed on fast systems, that use the vendor nvidia driver, it's not +unusual for boot to get to a point where all of userspace up to and +including GDM is executed before the graphics are ready to go. + +This commit tries to mitigate the situation by adding an additional, +check aside from CanGraphical to test if the system is ready. + +This check waits for the graphics card associated with boot to be fully +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/meson.build | 4 + + meson.build | 2 + + 4 files changed, 159 insertions(+), 12 deletions(-) + +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index c00e1c47..0b1d3482 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -1,100 +1,112 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + */ + + #include "config.h" + + #include + #include + + #include + #include + #include + #include + ++#ifdef HAVE_UDEV ++#include ++#endif ++ + #include + + #include "gdm-common.h" + #include "gdm-manager.h" + #include "gdm-display-factory.h" + #include "gdm-local-display-factory.h" + #include "gdm-local-display-factory-glue.h" + + #include "gdm-settings-keys.h" + #include "gdm-settings-direct.h" + #include "gdm-display-store.h" + #include "gdm-local-display.h" + #include "gdm-legacy-display.h" + + #define GDM_DBUS_PATH "/org/gnome/DisplayManager" + #define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory" + #define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory" + + #define MAX_DISPLAY_FAILURES 5 + #define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */ + #define SEAT0_GRAPHICS_CHECK_TIMEOUT 10 /* seconds */ + + struct _GdmLocalDisplayFactory + { +- GdmDisplayFactory parent; ++ GdmDisplayFactory parent; ++#ifdef HAVE_UDEV ++ GUdevClient *gudev_client; ++#endif + + GdmDBusLocalDisplayFactory *skeleton; + GDBusConnection *connection; + GHashTable *used_display_numbers; + + /* FIXME: this needs to be per seat? */ + guint num_failures; + + guint seat_new_id; + guint seat_removed_id; + guint seat_properties_changed_id; + ++ gboolean seat0_has_platform_graphics; ++ gboolean seat0_has_boot_up_graphics; ++ + gboolean seat0_graphics_check_timed_out; + guint seat0_graphics_check_timeout_id; + ++ gulong uevent_handler_id; ++ + #if defined(ENABLE_USER_DISPLAY_SERVER) + unsigned int active_vt; + guint active_vt_watch_id; + guint wait_to_finish_timeout_id; + #endif + + gboolean is_started; + }; + + enum { + PROP_0, + }; + + static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass); + static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory); + static void gdm_local_display_factory_finalize (GObject *object); + + static void ensure_display_for_seat (GdmLocalDisplayFactory *factory, + const char *seat_id); + + static void on_display_status_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmLocalDisplayFactory *factory); + + static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory); + static gpointer local_display_factory_object = NULL; + static gboolean lookup_by_session_id (const char *id, + GdmDisplay *display, + gpointer user_data); + +@@ -594,142 +606,236 @@ lookup_by_seat_id (const char *id, + 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_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) + 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; ++ } ++ ++ g_debug ("GdmLocalDisplayFactory: Checking if udev has settled enough to support graphics."); ++ ++ enumerator = g_udev_enumerator_new (factory->gudev_client); ++ ++ g_udev_enumerator_add_match_name (enumerator, "card*"); ++ g_udev_enumerator_add_match_tag (enumerator, "master-of-seat"); ++ g_udev_enumerator_add_match_subsystem (enumerator, "drm"); ++ ++ devices = g_udev_enumerator_execute (enumerator); ++ if (!devices) { ++ g_debug ("GdmLocalDisplayFactory: udev has no candidate graphics devices available yet."); ++ return FALSE; ++ } ++ ++ node = devices; ++ while (node != NULL) { ++ GUdevDevice *device = node->data; ++ GList *next_node = node->next; ++ g_autoptr (GUdevDevice) platform_device = NULL; ++ g_autoptr (GUdevDevice) pci_device = NULL; ++ ++ platform_device = g_udev_device_get_parent_with_subsystem (device, "platform", NULL); ++ ++ if (platform_device != NULL) { ++ g_debug ("GdmLocalDisplayFactory: Found embedded platform graphics, proceeding."); ++ factory->seat0_has_platform_graphics = TRUE; ++ is_settled = TRUE; ++ break; ++ } ++ ++ pci_device = g_udev_device_get_parent_with_subsystem (device, "pci", NULL); ++ ++ if (pci_device != NULL) { ++ gboolean boot_vga; ++ ++ boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga"); ++ ++ if (boot_vga == 1) { ++ g_debug ("GdmLocalDisplayFactory: Found primary PCI graphics adapter, proceeding."); ++ factory->seat0_has_boot_up_graphics = TRUE; ++ is_settled = TRUE; ++ break; ++ } else { ++ g_debug ("GdmLocalDisplayFactory: Found secondary PCI graphics adapter, not proceeding yet."); ++ } ++ } ++ node = next_node; ++ } ++ ++ g_debug ("GdmLocalDisplayFactory: udev has %ssettled enough for graphics.", is_settled? "" : "not "); ++ g_list_free_full (devices, g_object_unref); ++ ++ if (is_settled) ++ g_clear_signal_handler (&factory->uevent_handler_id, factory->gudev_client); ++ ++ return is_settled; ++} ++#endif ++ + static int + on_seat0_graphics_check_timeout (gpointer user_data) + { + GdmLocalDisplayFactory *factory = user_data; + + factory->seat0_graphics_check_timeout_id = 0; + + /* Simply try to re-add seat0. If it is there already (i.e. CanGraphical + * turned TRUE, then we'll find it and it will not be created again). + */ + factory->seat0_graphics_check_timed_out = TRUE; + ensure_display_for_seat (factory, "seat0"); + + return G_SOURCE_REMOVE; + } + + static void + ensure_display_for_seat (GdmLocalDisplayFactory *factory, + const char *seat_id) + { + int ret; + gboolean seat_supports_graphics; + gboolean is_seat0; + g_auto (GStrv) session_types = NULL; + const char *legacy_session_types[] = { "x11", NULL }; + GdmDisplayStore *store; + GdmDisplay *display = NULL; + g_autofree char *login_session_id = NULL; + gboolean wayland_enabled = FALSE, xorg_enabled = FALSE; + g_autofree gchar *preferred_display_server = NULL; + gboolean falling_back = FALSE; ++ gboolean waiting_on_udev = FALSE; + + gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled); + gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled); + + preferred_display_server = get_preferred_display_server (factory); + + if (g_strcmp0 (preferred_display_server, "none") == 0) { + g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display"); + return; + } + +- ret = sd_seat_can_graphical (seat_id); ++#ifdef HAVE_UDEV ++ waiting_on_udev = !udev_is_settled (factory); ++#endif + +- if (ret < 0) { +- g_critical ("Failed to query CanGraphical information for seat %s", seat_id); +- return; +- } ++ if (!waiting_on_udev) { ++ ret = sd_seat_can_graphical (seat_id); + +- if (ret == 0) { +- g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics"); +- seat_supports_graphics = FALSE; ++ if (ret < 0) { ++ g_critical ("Failed to query CanGraphical information for seat %s", seat_id); ++ return; ++ } ++ ++ if (ret == 0) { ++ g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics"); ++ seat_supports_graphics = FALSE; ++ } else { ++ g_debug ("GdmLocalDisplayFactory: System supports graphics"); ++ seat_supports_graphics = TRUE; ++ } + } else { +- g_debug ("GdmLocalDisplayFactory: System supports graphics"); +- seat_supports_graphics = TRUE; ++ g_debug ("GdmLocalDisplayFactory: udev is still settling, so not creating display yet"); ++ seat_supports_graphics = FALSE; + } + + if (g_strcmp0 (seat_id, "seat0") == 0) { + is_seat0 = TRUE; + + falling_back = factory->num_failures > 0; + session_types = gdm_local_display_factory_get_session_types (factory, falling_back); + + if (session_types == NULL) { + g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable"); + seat_supports_graphics = FALSE; + } else { + g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s", + session_types[0], falling_back? " fallback" : ""); + } + } else { + is_seat0 = FALSE; + + g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id); + /* Force legacy X11 for all auxiliary seats */ + seat_supports_graphics = TRUE; + session_types = g_strdupv ((char **) legacy_session_types); + } + + /* For seat0, we have a fallback logic to still try starting it after + * SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if +- * CanGraphical is unset. ++ * CanGraphical is unset or udev otherwise never finds a suitable graphics card. + * This is ugly, but it means we'll come up eventually in some + * scenarios where no master device is present. + * Note that we'll force an X11 fallback even though there might be + * cases where an wayland capable device is present and simply not marked as + * master-of-seat. In these cases, this should likely be fixed in the + * udev rules. + * + * At the moment, systemd always sets CanGraphical for non-seat0 seats. + * This is because non-seat0 seats are defined by having master-of-seat + * set. This means we can avoid the fallback check for non-seat0 seats, + * which simplifies the code. + */ + if (is_seat0) { + if (!seat_supports_graphics) { + if (!factory->seat0_graphics_check_timed_out) { + if (factory->seat0_graphics_check_timeout_id == 0) { + g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT); + factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT, + on_seat0_graphics_check_timeout, + factory); + + } else { + /* 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!"); +@@ -1138,113 +1240,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); + } + + factory->wait_to_finish_timeout_id = g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT, + (GSourceFunc) + on_finish_waiting_for_seat0_displays_timeout, + factory); + } + } + } + + /* if user jumped back to initial vt and it's empty put a login screen + * on it (unless a login screen is already running elsewhere, then + * jump to that login screen) + */ + if (factory->active_vt != GDM_INITIAL_VT) { + g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring"); + return G_SOURCE_CONTINUE; + } + + g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change"); + + ensure_display_for_seat (factory, "seat0"); + + return G_SOURCE_CONTINUE; + } + #endif + ++#ifdef HAVE_UDEV ++static void ++on_uevent (GUdevClient *client, ++ const char *action, ++ GUdevDevice *device, ++ GdmLocalDisplayFactory *factory) ++{ ++ if (!g_udev_device_get_device_file (device)) ++ return; ++ ++ if (g_strcmp0 (action, "add") != 0 && ++ g_strcmp0 (action, "change") != 0) ++ return; ++ ++ if (!udev_is_settled (factory)) ++ return; ++ ++ g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id); ++ factory->uevent_handler_id = 0; ++ ++ ensure_display_for_seat (factory, "seat0"); ++} ++#endif ++ + static void + gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory) + { + g_autoptr (GIOChannel) io_channel = NULL; ++ const char *subsystems[] = { "drm", NULL }; + + factory->seat_new_id = g_dbus_connection_signal_subscribe (factory->connection, + "org.freedesktop.login1", + "org.freedesktop.login1.Manager", + "SeatNew", + "/org/freedesktop/login1", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + on_seat_new, + g_object_ref (factory), + g_object_unref); + factory->seat_removed_id = g_dbus_connection_signal_subscribe (factory->connection, + "org.freedesktop.login1", + "org.freedesktop.login1.Manager", + "SeatRemoved", + "/org/freedesktop/login1", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + on_seat_removed, + g_object_ref (factory), + g_object_unref); + factory->seat_properties_changed_id = g_dbus_connection_signal_subscribe (factory->connection, + "org.freedesktop.login1", + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + NULL, + "org.freedesktop.login1.Seat", + G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE, + on_seat_properties_changed, + g_object_ref (factory), + g_object_unref); ++#ifdef HAVE_UDEV ++ factory->gudev_client = g_udev_client_new (subsystems); ++ factory->uevent_handler_id = g_signal_connect (factory->gudev_client, ++ "uevent", ++ G_CALLBACK (on_uevent), ++ factory); ++#endif + + #if defined(ENABLE_USER_DISPLAY_SERVER) + io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL); + + if (io_channel != NULL) { + factory->active_vt_watch_id = + g_io_add_watch (io_channel, + G_IO_PRI, + (GIOFunc) + on_vt_changed, + factory); + } + #endif + } + + static void + gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory) + { ++ if (factory->uevent_handler_id) { ++ g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id); ++ factory->uevent_handler_id = 0; ++ } ++ g_clear_object (&factory->gudev_client); ++ + if (factory->seat_new_id) { + g_dbus_connection_signal_unsubscribe (factory->connection, + factory->seat_new_id); + factory->seat_new_id = 0; + } + if (factory->seat_removed_id) { + g_dbus_connection_signal_unsubscribe (factory->connection, + factory->seat_removed_id); + factory->seat_removed_id = 0; + } + if (factory->seat_properties_changed_id) { + g_dbus_connection_signal_unsubscribe (factory->connection, + factory->seat_properties_changed_id); + factory->seat_properties_changed_id = 0; + } + #if defined(ENABLE_USER_DISPLAY_SERVER) + if (factory->active_vt_watch_id) { + g_source_remove (factory->active_vt_watch_id); + factory->active_vt_watch_id = 0; + } + if (factory->wait_to_finish_timeout_id != 0) { + g_source_remove (factory->wait_to_finish_timeout_id); + factory->wait_to_finish_timeout_id = 0; + } + #endif + } + + static void + on_display_added (GdmDisplayStore *display_store, + const char *id, +diff --git a/daemon/meson.build b/daemon/meson.build +index 2e61b644..41f30abe 100644 +--- a/daemon/meson.build ++++ b/daemon/meson.build +@@ -177,37 +177,41 @@ gdm_daemon_sources = files( + 'gdm-session-record.c', + 'gdm-session-worker-common.c', + 'gdm-session-worker-job.c', + 'gdm-session.c', + 'main.c', + ) + + gdm_daemon_gen_sources = [ + display_dbus_gen, + local_display_factory_dbus_gen, + manager_dbus_gen, + local_display_dbus_gen, + session_dbus_gen, + session_worker_dbus_gen, + gdm_session_enums, + ] + + if xdmcp_dep.found() + gdm_daemon_deps += xdmcp_dep + + gdm_daemon_sources = [ + gdm_daemon_sources, + files( + 'gdm-xdmcp-display-factory.c', + 'gdm-xdmcp-display.c', + 'gdm-xdmcp-chooser-display.c', + ), + ] + endif + ++if gudev_dep.found() ++ gdm_daemon_deps += gudev_dep ++endif ++ + gdm_daemon = executable('gdm', + [ gdm_daemon_sources, gdm_daemon_gen_sources ], + dependencies: gdm_daemon_deps, + include_directories: config_h_dir, + install: true, + install_dir: get_option('sbindir') + ) +diff --git a/meson.build b/meson.build +index 02d609dc..05d8da41 100644 +--- a/meson.build ++++ b/meson.build +@@ -11,60 +11,61 @@ i18n = import('i18n') + + # Compiler + cc = meson.get_compiler('c') + + # Options + gdm_prefix = get_option('prefix') + + gdmconfdir = (get_option('sysconfsubdir') == '')? gdm_prefix / get_option('sysconfdir') : gdm_prefix / get_option('sysconfdir') / get_option('sysconfsubdir') + dmconfdir = (get_option('dmconfdir') != '')? get_option('dmconfdir') : gdm_prefix / get_option('sysconfdir') / 'dm' + udev_dir = get_option('udev-dir') + at_spi_registryd_dir = (get_option('at-spi-registryd-dir') != '')? get_option('at-spi-registryd-dir') : gdm_prefix / get_option('libexecdir') + lang_config_file = (get_option('lang-file') != '')? get_option('lang-file') : gdm_prefix / get_option('sysconfdir') / 'locale.conf' + pam_mod_dir = (get_option('pam-mod-dir') != '')? get_option('pam-mod-dir') : gdm_prefix / get_option('libdir') / 'security' + dbus_sys_dir = (get_option('dbus-sys') != '')? get_option('dbus-sys') : get_option('sysconfdir') / 'dbus-1' / 'system.d' + gdm_defaults_conf = (get_option('defaults-conf') != '')? get_option('defaults-conf') : gdm_prefix / get_option('datadir') / 'gdm' / 'defaults.conf' + gdm_custom_conf = (get_option('custom-conf') != '')? get_option('custom-conf') : gdmconfdir / 'custom.conf' + gnome_settings_daemon_dir = (get_option('gnome-settings-daemon-dir') != '')? get_option('gnome-settings-daemon-dir') : gdm_prefix / get_option('libexecdir') + gdm_run_dir = (get_option('run-dir') != '')? get_option('run-dir') : gdm_prefix / get_option('localstatedir') / 'run' / 'gdm' + gdm_runtime_conf = (get_option('runtime-conf') != '')? get_option('runtime-conf') : gdm_run_dir / 'custom.conf' + gdm_pid_file = (get_option('pid-file') != '')? get_option('pid-file') : gdm_run_dir / 'gdm.pid' + ran_once_marker_dir = (get_option('ran-once-marker-dir') != '')? get_option('ran-once-marker-dir') : gdm_run_dir + working_dir = (get_option('working-dir') != '')? get_option('working-dir') : gdm_prefix / get_option('localstatedir') / 'lib' / 'gdm' + gdm_xauth_dir = (get_option('xauth-dir') != '')? get_option('xauth-dir') : gdm_run_dir + gdm_screenshot_dir = (get_option('screenshot-dir') != '')? get_option('screenshot-dir') : gdm_run_dir / 'greeter' + + # Common variables + config_h_dir = include_directories('.') + + # Dependencies + udev_dep = dependency('udev') ++gudev_dep = dependency('gudev-1.0', version: '>= 232') + + glib_min_version = '2.56.0' + + glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version) + gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version) + gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version) + gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version) + gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1') + libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4') + accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35') + xcb_dep = dependency('xcb') + keyutils_dep = dependency('libkeyutils', required: false) + libselinux_dep = dependency('libselinux', required: get_option('selinux')) + + # udev + if udev_dir == '' + if udev_dep.found() + udev_prefix = udev_dep.get_pkgconfig_variable('udevdir') + else + udev_prefix = gdm_prefix / 'lib' / 'udev' + endif + udev_dir = udev_prefix / 'rules.d' + endif + + # X11 + x_deps = declare_dependency( + dependencies: [ + dependency('x11'), + dependency('xau'), + ], +@@ -217,60 +218,61 @@ conf.set('HAVE_UTMP_H', have_utmp_header) + conf.set('HAVE_UTMPX_H', have_utmpx_header) + conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r) + conf.set('UTMP', utmp_struct) + conf.set('HAVE_GETUTXENT', cc.has_function('getutxent')) + conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp')) + conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx')) + conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil')) + conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil')) + conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil')) + conf.set('HAVE_PAM_SYSLOG', have_pam_syslog) + conf.set('HAVE_KEYUTILS', keyutils_dep.found()) + conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported) + conf.set('HAVE_SELINUX', libselinux_dep.found()) + conf.set('HAVE_XSERVER_WITH_LISTEN', xserver_has_listen) + conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server')) + conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal')) + conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support')) + conf.set('ENABLE_PROFILING', get_option('profiling')) + conf.set('GDM_INITIAL_VT', get_option('initial-vt')) + conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf) + conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf) + conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf) + conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path')) + conf.set_quoted('GDM_USERNAME', get_option('user')) + conf.set_quoted('GDM_GROUPNAME', get_option('group')) + conf.set('HAVE_LIBXDMCP', xdmcp_dep.found()) + conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server) + conf.set('WITH_PLYMOUTH', plymouth_dep.found()) + conf.set_quoted('X_SERVER', x_bin) + conf.set_quoted('X_PATH', x_path) ++conf.set('HAVE_UDEV', gudev_dep.found()) + conf.set('HAVE_UT_UT_HOST', utmp_has_host_field) + conf.set('HAVE_UT_UT_PID', utmp_has_pid_field) + conf.set('HAVE_UT_UT_ID', utmp_has_id_field) + conf.set('HAVE_UT_UT_NAME', utmp_has_name_field) + conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field) + conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field) + conf.set('HAVE_UT_UT_USER', utmp_has_user_field) + conf.set('HAVE_UT_UT_TIME', utmp_has_time_field) + conf.set('HAVE_UT_UT_TV', utmp_has_tv_field) + conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field) + conf.set('ENABLE_IPV6', get_option('ipv6')) + configure_file(output: 'config.h', configuration: conf) + + # Subdirs + subdir('data') + subdir('common') + if pam_extensions_supported + subdir('pam-extensions') + endif + subdir('daemon') + subdir('libgdm') + subdir('utils') + subdir('pam_gdm') + subdir('po') + if libcheck_dep.found() + subdir('tests') + endif + if xdmcp_dep.found() + subdir('chooser') + endif +-- +2.34.1 + diff --git a/SOURCES/0001-meson-Fix-detection-of-Xorg-versions-that-need-liste.patch b/SOURCES/0001-meson-Fix-detection-of-Xorg-versions-that-need-liste.patch new file mode 100644 index 0000000..0b6b1ec --- /dev/null +++ b/SOURCES/0001-meson-Fix-detection-of-Xorg-versions-that-need-liste.patch @@ -0,0 +1,144 @@ +From b8caa1a18f284cc9b59a2e0273780a51b6fd7528 Mon Sep 17 00:00:00 2001 +From: Alan Coopersmith +Date: Thu, 7 Oct 2021 18:22:11 -0700 +Subject: [PATCH 1/2] meson: Fix detection of Xorg versions that need -listen + tcp + +Closes #704 +--- + meson.build | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/meson.build b/meson.build +index 64b98628..52ac1941 100644 +--- a/meson.build ++++ b/meson.build +@@ -42,60 +42,63 @@ udev_dep = dependency('udev') + glib_min_version = '2.56.0' + + glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version) + gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version) + gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version) + gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version) + gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1') + libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4') + accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35') + xcb_dep = dependency('xcb') + keyutils_dep = dependency('libkeyutils', required: false) + libselinux_dep = dependency('libselinux', required: get_option('selinux')) + + # udev + if udev_dir == '' + if udev_dep.found() + udev_prefix = udev_dep.get_pkgconfig_variable('udevdir') + else + udev_prefix = gdm_prefix / 'lib' / 'udev' + endif + udev_dir = udev_prefix / 'rules.d' + endif + + # X11 + x_deps = declare_dependency( + dependencies: [ + dependency('x11'), + dependency('xau'), + ], + ) ++# Xserver 1.17 & later default to -nolisten and require -listen for remote access ++xserver_deps = dependency('xorg-server', version : '>=1.17', required : false) ++xserver_nolisten_default = xserver_deps.found() + find_x_server_script = find_program('build-aux/find-x-server.sh', native: true) + find_x_server_out = run_command(find_x_server_script).stdout().strip() + if find_x_server_out != '' + x_bin = find_x_server_out + x_bin_path_split = x_bin.split('/') + i = 0 + x_path = '/' + foreach dir : x_bin_path_split + if i < x_bin_path_split.length() - 1 + x_path = x_path / dir + endif + i = i + 1 + endforeach + else + # what to do, what to do, this is wrong, but this just sets the + # defaults, perhaps this user is cross compiling or some such + x_path = '/usr/bin/X11:/usr/X11R6/bin:/opt/X11R6/bin' + x_bin = '/usr/bin/X' + endif + xdmcp_dep = cc.find_library('Xdmcp', required: get_option('xdmcp')) + if xdmcp_dep.found() and get_option('tcp-wrappers') + libwrap_dep = cc.find_library('wrap') + endif + # systemd + systemd_dep = dependency('systemd') + libsystemd_dep = dependency('libsystemd') + if meson.version().version_compare('>= 0.53') + systemd_multiseat_x = find_program('systemd-multi-seat-x', + required: false, + dirs: [ +@@ -197,60 +200,61 @@ conf.set_quoted('SYSCONFDIR', gdm_prefix / get_option('sysconfdir')) + conf.set_quoted('BINDIR', gdm_prefix / get_option('bindir')) + conf.set_quoted('LIBDIR', gdm_prefix / get_option('libdir')) + conf.set_quoted('LIBEXECDIR', gdm_prefix / get_option('libexecdir')) + conf.set_quoted('LOGDIR', get_option('log-dir')) + conf.set_quoted('DMCONFDIR', dmconfdir) + conf.set_quoted('GDMCONFDIR', gdmconfdir) + conf.set_quoted('GDM_SCREENSHOT_DIR', gdm_screenshot_dir) + conf.set_quoted('GDM_XAUTH_DIR', gdm_xauth_dir) + conf.set_quoted('GDM_RAN_ONCE_MARKER_DIR', ran_once_marker_dir) + conf.set_quoted('GDM_RUN_DIR', gdm_run_dir) + conf.set_quoted('GNOMELOCALEDIR', gdm_prefix / get_option('localedir')) + conf.set_quoted('AT_SPI_REGISTRYD_DIR', at_spi_registryd_dir) + conf.set_quoted('GDM_PID_FILE', gdm_pid_file) + conf.set_quoted('GNOME_SETTINGS_DAEMON_DIR', gnome_settings_daemon_dir) + conf.set_quoted('LANG_CONFIG_FILE', lang_config_file) + conf.set('HAVE_ADT', have_adt) + conf.set('HAVE_UTMP_H', have_utmp_header) + conf.set('HAVE_UTMPX_H', have_utmpx_header) + conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r) + conf.set('UTMP', utmp_struct) + conf.set('HAVE_GETUTXENT', cc.has_function('getutxent')) + conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp')) + conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx')) + conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil')) + conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil')) + conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil')) + conf.set('HAVE_PAM_SYSLOG', have_pam_syslog) + conf.set('HAVE_KEYUTILS', keyutils_dep.found()) + conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported) + conf.set('HAVE_SELINUX', libselinux_dep.found()) ++conf.set('HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY', xserver_nolisten_default) + conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server')) + conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal')) + conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support')) + conf.set('ENABLE_PROFILING', get_option('profiling')) + conf.set('GDM_INITIAL_VT', get_option('initial-vt')) + conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf) + conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf) + conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf) + conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path')) + conf.set_quoted('GDM_USERNAME', get_option('user')) + conf.set_quoted('GDM_GROUPNAME', get_option('group')) + conf.set('HAVE_LIBXDMCP', xdmcp_dep.found()) + conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server) + conf.set('WITH_PLYMOUTH', plymouth_dep.found()) + conf.set_quoted('X_SERVER', x_bin) + conf.set_quoted('X_PATH', x_path) + conf.set('HAVE_UT_UT_HOST', utmp_has_host_field) + conf.set('HAVE_UT_UT_PID', utmp_has_pid_field) + conf.set('HAVE_UT_UT_ID', utmp_has_id_field) + conf.set('HAVE_UT_UT_NAME', utmp_has_name_field) + conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field) + conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field) + conf.set('HAVE_UT_UT_USER', utmp_has_user_field) + conf.set('HAVE_UT_UT_TIME', utmp_has_time_field) + conf.set('HAVE_UT_UT_TV', utmp_has_tv_field) + conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field) + conf.set('ENABLE_IPV6', get_option('ipv6')) + configure_file(output: 'config.h', configuration: conf) + + # Subdirs +-- +2.34.1 + diff --git a/SOURCES/0001-session-settings-Fetch-session-from-user-even-if-use.patch b/SOURCES/0001-session-settings-Fetch-session-from-user-even-if-use.patch new file mode 100644 index 0000000..109ec15 --- /dev/null +++ b/SOURCES/0001-session-settings-Fetch-session-from-user-even-if-use.patch @@ -0,0 +1,89 @@ +From 8a29f79124f38e2106b263bacb6b5ab4cdb255d0 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 9 Mar 2022 10:46:21 -0500 +Subject: [PATCH] session-settings: Fetch session from user even if user isn't + cached + +Now that accountsservice supports session templates, GDM can't assume +that no-cache file means, there's nothing worth reading. + +Unfortunately, GDM does exactly that. It bypasses fetching the users +session if it doesn't think the user has one. + +This commit removes that no-longer-correct optimization. +--- + daemon/gdm-session-settings.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c +index 5b64cb65..fbf6897b 100644 +--- a/daemon/gdm-session-settings.c ++++ b/daemon/gdm-session-settings.c +@@ -270,64 +270,60 @@ gdm_session_settings_new (void) + GdmSessionSettings *settings; + + settings = g_object_new (GDM_TYPE_SESSION_SETTINGS, + NULL); + + return settings; + } + + gboolean + gdm_session_settings_is_loaded (GdmSessionSettings *settings) + { + if (settings->priv->user == NULL) { + return FALSE; + } + + return act_user_is_loaded (settings->priv->user); + } + + static void + load_settings_from_user (GdmSessionSettings *settings) + { + const char *session_name; + const char *session_type; + const char *language_name; + + if (!act_user_is_loaded (settings->priv->user)) { + g_warning ("GdmSessionSettings: trying to load user settings from unloaded user"); + return; + } + +- /* if the user doesn't have saved state, they don't have any settings worth reading */ +- if (!act_user_get_saved (settings->priv->user)) +- goto out; +- + session_type = act_user_get_session_type (settings->priv->user); + session_name = act_user_get_session (settings->priv->user); + + g_debug ("GdmSessionSettings: saved session is %s (type %s)", session_name, session_type); + + if (session_type != NULL && session_type[0] != '\0') { + gdm_session_settings_set_session_type (settings, session_type); + } + + if (session_name != NULL && session_name[0] != '\0') { + gdm_session_settings_set_session_name (settings, session_name); + } + + language_name = act_user_get_language (settings->priv->user); + + g_debug ("GdmSessionSettings: saved language is %s", language_name); + if (language_name != NULL && language_name[0] != '\0') { + gdm_session_settings_set_language_name (settings, language_name); + } + + out: + g_object_notify (G_OBJECT (settings), "is-loaded"); + } + + static void + on_user_is_loaded_changed (ActUser *user, + GParamSpec *pspec, + GdmSessionSettings *settings) + { + if (act_user_is_loaded (settings->priv->user)) { +-- +2.34.1 + diff --git a/SOURCES/0001-xdmcp-display-factory-Set-supported-session-types-fo.patch b/SOURCES/0001-xdmcp-display-factory-Set-supported-session-types-fo.patch index 154622b..f3eefe7 100644 --- a/SOURCES/0001-xdmcp-display-factory-Set-supported-session-types-fo.patch +++ b/SOURCES/0001-xdmcp-display-factory-Set-supported-session-types-fo.patch @@ -1,7 +1,7 @@ -From 984690b76527baae0f7da0af00467669b49886ef Mon Sep 17 00:00:00 2001 +From 36b9fd4f6e055e236175979d9a1527df71aeac1f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 14 Sep 2021 11:00:33 -0400 -Subject: [PATCH 1/3] xdmcp-display-factory: Set supported session types for +Subject: [PATCH 1/5] xdmcp-display-factory: Set supported session types for XDMCP displays The lower levels of GDM now expect the session types supported by a @@ -118,5 +118,5 @@ index ce8f026e..abb58fae 100644 ARRAY8Ptr authorization_data) { -- -2.31.1 +2.34.1 diff --git a/SOURCES/0002-common-Add-API-to-reload-settings-from-disk.patch b/SOURCES/0002-common-Add-API-to-reload-settings-from-disk.patch new file mode 100644 index 0000000..b6696e6 --- /dev/null +++ b/SOURCES/0002-common-Add-API-to-reload-settings-from-disk.patch @@ -0,0 +1,356 @@ +From d3e073fa1cd314b344db1ec22f0add2702a6c299 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 15 Feb 2022 14:33:22 -0500 +Subject: [PATCH 2/4] common: Add API to reload settings from disk + +Ideally we would reread /run/gdm/custom.conf after we've decided +graphics setup is complete. This is because the file may not +get written out by udev until after GDM is already started and waiting. + +As a first step to get there, this commit adds an API for rereading +the file, and changes the SIGHUP handler to use it (instead of +the complete teardown and reinitialization it was doing before). +--- + common/gdm-settings-direct.c | 9 +++++++++ + common/gdm-settings-direct.h | 2 ++ + common/gdm-settings.c | 14 ++++++++++++-- + common/gdm-settings.h | 1 + + daemon/main.c | 12 ++---------- + 5 files changed, 26 insertions(+), 12 deletions(-) + +diff --git a/common/gdm-settings-direct.c b/common/gdm-settings-direct.c +index ddb31908..5fbe0326 100644 +--- a/common/gdm-settings-direct.c ++++ b/common/gdm-settings-direct.c +@@ -224,35 +224,44 @@ hashify_list (GdmSettingsEntry *entry, + + gboolean + gdm_settings_direct_init (GdmSettings *settings, + const char *file, + const char *root) + { + GSList *list; + + g_return_val_if_fail (file != NULL, FALSE); + g_return_val_if_fail (root != NULL, FALSE); + + g_debug ("Settings Direct Init"); + if (schemas != NULL) { + g_hash_table_unref (schemas); + schemas = NULL; + } + + if (! gdm_settings_parse_schemas (file, root, &list)) { + g_warning ("Unable to parse schemas"); + return FALSE; + } + + schemas = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)gdm_settings_entry_free); + g_slist_foreach (list, (GFunc)hashify_list, NULL); + + settings_object = settings; + + return TRUE; + } + ++void ++gdm_settings_direct_reload (void) ++{ ++ if (!settings_object) ++ return; ++ ++ gdm_settings_reload (settings_object); ++} ++ + void + gdm_settings_direct_shutdown (void) + { + + } +diff --git a/common/gdm-settings-direct.h b/common/gdm-settings-direct.h +index 156489cd..6754955f 100644 +--- a/common/gdm-settings-direct.h ++++ b/common/gdm-settings-direct.h +@@ -3,48 +3,50 @@ + * Copyright (C) 2007 William Jon McCann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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_SETTINGS_DIRECT_H + #define __GDM_SETTINGS_DIRECT_H + + #include + #include "gdm-settings.h" + + G_BEGIN_DECLS + + gboolean gdm_settings_direct_init (GdmSettings *settings, + const char *schemas_file, + const char *root); ++ ++void gdm_settings_direct_reload (void); + void gdm_settings_direct_shutdown (void); + + gboolean gdm_settings_direct_get (const char *key, + GValue *value); + gboolean gdm_settings_direct_set (const char *key, + GValue *value); + gboolean gdm_settings_direct_get_int (const char *key, + int *value); + gboolean gdm_settings_direct_get_uint (const char *key, + uint *value); + gboolean gdm_settings_direct_get_boolean (const char *key, + gboolean *value); + gboolean gdm_settings_direct_get_string (const char *key, + char **value); + + G_END_DECLS + + #endif /* __GDM_SETTINGS_DIRECT_H */ +diff --git a/common/gdm-settings.c b/common/gdm-settings.c +index e6f46ec3..96c2f8d3 100644 +--- a/common/gdm-settings.c ++++ b/common/gdm-settings.c +@@ -157,84 +157,94 @@ gdm_settings_class_init (GdmSettingsClass *klass) + object_class->finalize = gdm_settings_finalize; + + signals [VALUE_CHANGED] = + g_signal_new ("value-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + } + + static void + backend_value_changed (GdmSettingsBackend *backend, + const char *key, + const char *old_value, + const char *new_value, + GdmSettings *settings) + { + g_debug ("Emitting value-changed %s %s %s", key, old_value, new_value); + + /* proxy it to internal listeners */ + g_signal_emit (settings, signals [VALUE_CHANGED], 0, key, old_value, new_value); + } + +-static void +-gdm_settings_init (GdmSettings *settings) ++void ++gdm_settings_reload (GdmSettings *settings) + { + GList *l; + GdmSettingsBackend *backend; + ++ g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL); ++ g_list_free (settings->backends); ++ settings->backends = NULL; ++ + backend = gdm_settings_desktop_backend_new (GDM_CUSTOM_CONF); + if (backend) + settings->backends = g_list_prepend (NULL, backend); + + backend = gdm_settings_desktop_backend_new (GDM_RUNTIME_CONF); + if (backend) + settings->backends = g_list_prepend (settings->backends, backend); + + for (l = settings->backends; l; l = g_list_next (l)) { + backend = l->data; + + g_signal_connect (backend, + "value-changed", + G_CALLBACK (backend_value_changed), + settings); + } + } + ++static void ++gdm_settings_init (GdmSettings *settings) ++{ ++ gdm_settings_reload (settings); ++} ++ + static void + gdm_settings_finalize (GObject *object) + { + GdmSettings *settings; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_SETTINGS (object)); + + settings = GDM_SETTINGS (object); + + g_return_if_fail (settings != NULL); + + g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL); + g_list_free (settings->backends); + settings->backends = NULL; + + settings_object = NULL; + + G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object); + } + + GdmSettings * + gdm_settings_new (void) + { + if (settings_object != NULL) { + g_object_ref (settings_object); + } else { + settings_object = g_object_new (GDM_TYPE_SETTINGS, NULL); + } + +diff --git a/common/gdm-settings.h b/common/gdm-settings.h +index 786868a9..07b64785 100644 +--- a/common/gdm-settings.h ++++ b/common/gdm-settings.h +@@ -13,45 +13,46 @@ + * 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_SETTINGS_H + #define __GDM_SETTINGS_H + + #include + + G_BEGIN_DECLS + + #define GDM_TYPE_SETTINGS (gdm_settings_get_type ()) + G_DECLARE_FINAL_TYPE (GdmSettings, gdm_settings, GDM, SETTINGS, GObject) + + typedef enum + { + GDM_SETTINGS_ERROR_GENERAL, + GDM_SETTINGS_ERROR_KEY_NOT_FOUND + } GdmSettingsError; + + #define GDM_SETTINGS_ERROR gdm_settings_error_quark () + + GQuark gdm_settings_error_quark (void); + + GdmSettings * gdm_settings_new (void); ++void gdm_settings_reload (GdmSettings *settings); + + /* exported */ + + gboolean gdm_settings_get_value (GdmSettings *settings, + const char *key, + char **value, + GError **error); + gboolean gdm_settings_set_value (GdmSettings *settings, + const char *key, + const char *value, + GError **error); + + G_END_DECLS + + #endif /* __GDM_SETTINGS_H */ +diff --git a/daemon/main.c b/daemon/main.c +index 1b893fe0..344d1b74 100644 +--- a/daemon/main.c ++++ b/daemon/main.c +@@ -240,70 +240,62 @@ gdm_daemon_lookup_user (uid_t *uidp, + if G_UNLIKELY (gid == 0) { + gdm_fail (_("The GDM group should not be root. Aborting!")); + } + + if (uidp != NULL) { + *uidp = uid; + } + + if (gidp != NULL) { + *gidp = gid; + } + + g_free (username); + g_free (groupname); + } + + static gboolean + on_shutdown_signal_cb (gpointer user_data) + { + GMainLoop *mainloop = user_data; + + g_main_loop_quit (mainloop); + + return FALSE; + } + + static gboolean + on_sighup_cb (gpointer user_data) + { + g_debug ("Got HUP signal"); +- /* Reread config stuff like system config files, VPN service +- * files, etc +- */ +- g_object_unref (settings); +- settings = gdm_settings_new (); +- if (settings != NULL) { +- if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) { +- g_warning ("Unable to initialize settings"); +- } +- } ++ ++ gdm_settings_reload (settings); + + return TRUE; + } + + static gboolean + is_debug_set (void) + { + gboolean debug; + gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug); + return debug; + } + + /* SIGUSR1 is used by the X server to tell us that we're ready, so + * block it. We'll unblock it in the worker thread in gdm-server.c + */ + static void + block_sigusr1 (void) + { + sigset_t mask; + + sigemptyset (&mask); + sigaddset (&mask, SIGUSR1); + sigprocmask (SIG_BLOCK, &mask, NULL); + } + + int + main (int argc, + char **argv) + { + GMainLoop *main_loop; +-- +2.34.1 + diff --git a/SOURCES/0002-daemon-Don-t-update-session-type-if-no-saved-session.patch b/SOURCES/0002-daemon-Don-t-update-session-type-if-no-saved-session.patch index eddae95..c6b5abc 100644 --- a/SOURCES/0002-daemon-Don-t-update-session-type-if-no-saved-session.patch +++ b/SOURCES/0002-daemon-Don-t-update-session-type-if-no-saved-session.patch @@ -1,7 +1,7 @@ -From 1e877db3a4a8cb8e4eb4fbdaef3f6a7434e6a57d Mon Sep 17 00:00:00 2001 +From b09ab8a73d5a4133f72846d529bbbfb7802ca535 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 6 Sep 2021 08:40:46 -0400 -Subject: [PATCH 2/3] daemon: Don't update session type if no saved session +Subject: [PATCH 2/5] daemon: Don't update session type if no saved session At the moment we always set the session type when the session name is read. But users don't always have a session type specified. @@ -105,5 +105,5 @@ index 2b941e5e..b54687d5 100644 } } -- -2.31.1 +2.34.1 diff --git a/SOURCES/0002-daemon-Support-X-servers-built-with-Dlisten_tcp-true.patch b/SOURCES/0002-daemon-Support-X-servers-built-with-Dlisten_tcp-true.patch new file mode 100644 index 0000000..a822f49 --- /dev/null +++ b/SOURCES/0002-daemon-Support-X-servers-built-with-Dlisten_tcp-true.patch @@ -0,0 +1,327 @@ +From cc67c8de39358031fddc5ca7d8c993271d6606a7 Mon Sep 17 00:00:00 2001 +From: Alan Coopersmith +Date: Thu, 7 Oct 2021 18:22:11 -0700 +Subject: [PATCH 2/2] daemon: Support X servers built with -Dlisten_tcp=true + +Xorg since version 1.17 doesn't listen to tcp sockets by default +unless it's explicitly built with -Dlisten_tcp=true. + +GDM currently assumes X servers 1.17 and later are always built +without specifying -Dlisten_tcp=true and doesn't work properly +otherwise. + +This commit enhances GDM to better handle these non-standard builds by +always passing '-nolisten tcp' on the command line when tcp should +be disabled, and likewise always passing '-listen tcp' on the command +line, assuming the X server is new enough to support it, when tcp +should be enabled. + +Related #704 +--- + daemon/gdm-server.c | 21 +++++++++++---------- + daemon/gdm-x-session.c | 12 ++++++------ + meson.build | 4 ++-- + 3 files changed, 19 insertions(+), 18 deletions(-) + +diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c +index 1ba00d45..e5d23521 100644 +--- a/daemon/gdm-server.c ++++ b/daemon/gdm-server.c +@@ -290,72 +290,73 @@ gdm_server_resolve_command_line (GdmServer *server, + if (strcmp (arg, "-query") == 0 || + strcmp (arg, "-indirect") == 0) + query_in_arglist = TRUE; + } + + argv = g_renew (char *, argv, len + 12); + /* shift args down one */ + for (i = len - 1; i >= 1; i--) { + argv[i+1] = argv[i]; + } + + /* server number is the FIRST argument, before any others */ + argv[1] = g_strdup (server->display_name); + len++; + + if (server->auth_file != NULL) { + argv[len++] = g_strdup ("-auth"); + argv[len++] = g_strdup (server->auth_file); + } + + if (server->display_seat_id != NULL) { + argv[len++] = g_strdup ("-seat"); + argv[len++] = g_strdup (server->display_seat_id); + } + + /* If we were compiled with Xserver >= 1.17 we need to specify + * '-listen tcp' as the X server dosen't listen on tcp sockets + * by default anymore. In older versions we need to pass + * -nolisten tcp to disable listening on tcp sockets. + */ +-#ifdef HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY +- if (!server->disable_tcp && ! query_in_arglist) { +- argv[len++] = g_strdup ("-listen"); +- argv[len++] = g_strdup ("tcp"); +- } +-#else +- if (server->disable_tcp && ! query_in_arglist) { +- argv[len++] = g_strdup ("-nolisten"); +- argv[len++] = g_strdup ("tcp"); +- } ++ if (!query_in_arglist) { ++ if (server->disable_tcp) { ++ argv[len++] = g_strdup ("-nolisten"); ++ argv[len++] = g_strdup ("tcp"); ++ } + ++#ifdef HAVE_XSERVER_WITH_LISTEN ++ if (!server->disable_tcp) { ++ argv[len++] = g_strdup ("-listen"); ++ argv[len++] = g_strdup ("tcp"); ++ } + #endif ++ } + + if (vtarg != NULL && ! gotvtarg) { + argv[len++] = g_strdup (vtarg); + } + + argv[len++] = NULL; + + *argvp = argv; + *argcp = len; + + return TRUE; + } + + static void + rotate_logs (const char *path, + guint n_copies) + { + int i; + + for (i = n_copies - 1; i > 0; i--) { + char *name_n; + char *name_n1; + + name_n = g_strdup_printf ("%s.%d", path, i); + if (i > 1) { + name_n1 = g_strdup_printf ("%s.%d", path, i - 1); + } else { + name_n1 = g_strdup (path); + } + +diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c +index 5962da57..0b07ab5b 100644 +--- a/daemon/gdm-x-session.c ++++ b/daemon/gdm-x-session.c +@@ -233,70 +233,70 @@ spawn_x_server (State *state, + + if (g_getenv ("XDG_VTNR") != NULL) { + int vt; + + vt = atoi (g_getenv ("XDG_VTNR")); + + if (vt > 0 && vt < 64) { + vt_string = g_strdup_printf ("vt%d", vt); + } + } + + display_fd_string = g_strdup_printf ("%d", DISPLAY_FILENO); + + g_ptr_array_add (arguments, X_SERVER); + + if (vt_string != NULL) { + g_ptr_array_add (arguments, vt_string); + } + + g_ptr_array_add (arguments, "-displayfd"); + g_ptr_array_add (arguments, display_fd_string); + + g_ptr_array_add (arguments, "-auth"); + g_ptr_array_add (arguments, auth_file); + + /* If we were compiled with Xserver >= 1.17 we need to specify + * '-listen tcp' as the X server doesn't listen on tcp sockets + * by default anymore. In older versions we need to pass + * -nolisten tcp to disable listening on tcp sockets. + */ +-#ifdef HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY +- if (allow_remote_connections) { +- g_ptr_array_add (arguments, "-listen"); +- g_ptr_array_add (arguments, "tcp"); +- } +-#else + if (!allow_remote_connections) { + g_ptr_array_add (arguments, "-nolisten"); + g_ptr_array_add (arguments, "tcp"); + } ++ ++#ifdef HAVE_XSERVER_WITH_LISTEN ++ if (allow_remote_connections) { ++ g_ptr_array_add (arguments, "-listen"); ++ g_ptr_array_add (arguments, "tcp"); ++ } + #endif + + g_ptr_array_add (arguments, "-background"); + g_ptr_array_add (arguments, "none"); + + g_ptr_array_add (arguments, "-noreset"); + g_ptr_array_add (arguments, "-keeptty"); + g_ptr_array_add (arguments, "-novtswitch"); + + g_ptr_array_add (arguments, "-verbose"); + if (state->debug_enabled) { + g_ptr_array_add (arguments, "7"); + } else { + g_ptr_array_add (arguments, "3"); + } + + if (state->debug_enabled) { + g_ptr_array_add (arguments, "-core"); + } + g_ptr_array_add (arguments, NULL); + + subprocess = g_subprocess_launcher_spawnv (launcher, + (const char * const *) arguments->pdata, + &error); + g_free (display_fd_string); + g_clear_object (&launcher); + g_ptr_array_free (arguments, TRUE); + + if (subprocess == NULL) { + g_debug ("could not start X server: %s", error->message); +diff --git a/meson.build b/meson.build +index 52ac1941..02d609dc 100644 +--- a/meson.build ++++ b/meson.build +@@ -44,61 +44,61 @@ glib_min_version = '2.56.0' + glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version) + gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version) + gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version) + gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version) + gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1') + libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4') + accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35') + xcb_dep = dependency('xcb') + keyutils_dep = dependency('libkeyutils', required: false) + libselinux_dep = dependency('libselinux', required: get_option('selinux')) + + # udev + if udev_dir == '' + if udev_dep.found() + udev_prefix = udev_dep.get_pkgconfig_variable('udevdir') + else + udev_prefix = gdm_prefix / 'lib' / 'udev' + endif + udev_dir = udev_prefix / 'rules.d' + endif + + # X11 + x_deps = declare_dependency( + dependencies: [ + dependency('x11'), + dependency('xau'), + ], + ) + # Xserver 1.17 & later default to -nolisten and require -listen for remote access + xserver_deps = dependency('xorg-server', version : '>=1.17', required : false) +-xserver_nolisten_default = xserver_deps.found() ++xserver_has_listen = xserver_deps.found() + find_x_server_script = find_program('build-aux/find-x-server.sh', native: true) + find_x_server_out = run_command(find_x_server_script).stdout().strip() + if find_x_server_out != '' + x_bin = find_x_server_out + x_bin_path_split = x_bin.split('/') + i = 0 + x_path = '/' + foreach dir : x_bin_path_split + if i < x_bin_path_split.length() - 1 + x_path = x_path / dir + endif + i = i + 1 + endforeach + else + # what to do, what to do, this is wrong, but this just sets the + # defaults, perhaps this user is cross compiling or some such + x_path = '/usr/bin/X11:/usr/X11R6/bin:/opt/X11R6/bin' + x_bin = '/usr/bin/X' + endif + xdmcp_dep = cc.find_library('Xdmcp', required: get_option('xdmcp')) + if xdmcp_dep.found() and get_option('tcp-wrappers') + libwrap_dep = cc.find_library('wrap') + endif + # systemd + systemd_dep = dependency('systemd') + libsystemd_dep = dependency('libsystemd') + if meson.version().version_compare('>= 0.53') + systemd_multiseat_x = find_program('systemd-multi-seat-x', + required: false, + dirs: [ +@@ -200,61 +200,61 @@ conf.set_quoted('SYSCONFDIR', gdm_prefix / get_option('sysconfdir')) + conf.set_quoted('BINDIR', gdm_prefix / get_option('bindir')) + conf.set_quoted('LIBDIR', gdm_prefix / get_option('libdir')) + conf.set_quoted('LIBEXECDIR', gdm_prefix / get_option('libexecdir')) + conf.set_quoted('LOGDIR', get_option('log-dir')) + conf.set_quoted('DMCONFDIR', dmconfdir) + conf.set_quoted('GDMCONFDIR', gdmconfdir) + conf.set_quoted('GDM_SCREENSHOT_DIR', gdm_screenshot_dir) + conf.set_quoted('GDM_XAUTH_DIR', gdm_xauth_dir) + conf.set_quoted('GDM_RAN_ONCE_MARKER_DIR', ran_once_marker_dir) + conf.set_quoted('GDM_RUN_DIR', gdm_run_dir) + conf.set_quoted('GNOMELOCALEDIR', gdm_prefix / get_option('localedir')) + conf.set_quoted('AT_SPI_REGISTRYD_DIR', at_spi_registryd_dir) + conf.set_quoted('GDM_PID_FILE', gdm_pid_file) + conf.set_quoted('GNOME_SETTINGS_DAEMON_DIR', gnome_settings_daemon_dir) + conf.set_quoted('LANG_CONFIG_FILE', lang_config_file) + conf.set('HAVE_ADT', have_adt) + conf.set('HAVE_UTMP_H', have_utmp_header) + conf.set('HAVE_UTMPX_H', have_utmpx_header) + conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r) + conf.set('UTMP', utmp_struct) + conf.set('HAVE_GETUTXENT', cc.has_function('getutxent')) + conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp')) + conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx')) + conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil')) + conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil')) + conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil')) + conf.set('HAVE_PAM_SYSLOG', have_pam_syslog) + conf.set('HAVE_KEYUTILS', keyutils_dep.found()) + conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported) + conf.set('HAVE_SELINUX', libselinux_dep.found()) +-conf.set('HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY', xserver_nolisten_default) ++conf.set('HAVE_XSERVER_WITH_LISTEN', xserver_has_listen) + conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server')) + conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal')) + conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support')) + conf.set('ENABLE_PROFILING', get_option('profiling')) + conf.set('GDM_INITIAL_VT', get_option('initial-vt')) + conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf) + conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf) + conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf) + conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path')) + conf.set_quoted('GDM_USERNAME', get_option('user')) + conf.set_quoted('GDM_GROUPNAME', get_option('group')) + conf.set('HAVE_LIBXDMCP', xdmcp_dep.found()) + conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server) + conf.set('WITH_PLYMOUTH', plymouth_dep.found()) + conf.set_quoted('X_SERVER', x_bin) + conf.set_quoted('X_PATH', x_path) + conf.set('HAVE_UT_UT_HOST', utmp_has_host_field) + conf.set('HAVE_UT_UT_PID', utmp_has_pid_field) + conf.set('HAVE_UT_UT_ID', utmp_has_id_field) + conf.set('HAVE_UT_UT_NAME', utmp_has_name_field) + conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field) + conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field) + conf.set('HAVE_UT_UT_USER', utmp_has_user_field) + conf.set('HAVE_UT_UT_TIME', utmp_has_time_field) + conf.set('HAVE_UT_UT_TV', utmp_has_tv_field) + conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field) + conf.set('ENABLE_IPV6', get_option('ipv6')) + configure_file(output: 'config.h', configuration: conf) + + # Subdirs +-- +2.34.1 + diff --git a/SOURCES/0003-common-Reload-settings-when-graphics-initialize.patch b/SOURCES/0003-common-Reload-settings-when-graphics-initialize.patch new file mode 100644 index 0000000..4113958 --- /dev/null +++ b/SOURCES/0003-common-Reload-settings-when-graphics-initialize.patch @@ -0,0 +1,155 @@ +From a9928bfcc9c6d81d60e047b7838d4107835b8f89 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 15 Feb 2022 14:33:22 -0500 +Subject: [PATCH 3/4] common: Reload settings when graphics initialize + +If GDM starts faster than graphics initialize, then the +udev rules that write out /run/gdm/custom.conf might get +run too late for GDM to notice. + +This commit changes GDM to reread its config after graphicals +initialization completes. + +https://gitlab.gnome.org/GNOME/gdm/-/issues/763 +--- + daemon/gdm-local-display-factory.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index 0b1d3482..8bca8ce9 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -1023,64 +1023,66 @@ on_seat_properties_changed (GDBusConnection *connection, + g_autoptr(GVariant) changed_prop = NULL; + g_autofree const gchar **invalidated_props = NULL; + gboolean changed = FALSE; + int ret; + + /* Extract seat id, i.e. the last element of the object path. */ + seat = strrchr (object_path, '/'); + if (seat == NULL) + return; + seat += 1; + + /* Valid seat IDs must start with seat, i.e. ignore "auto" */ + if (!g_str_has_prefix (seat, "seat")) + return; + + g_variant_get (parameters, "(s@a{sv}^a&s)", NULL, &changed_props, &invalidated_props); + + changed_prop = g_variant_lookup_value (changed_props, "CanGraphical", NULL); + if (changed_prop) + changed = TRUE; + if (!changed && g_strv_contains (invalidated_props, "CanGraphical")) + changed = TRUE; + + if (!changed) + return; + + ret = sd_seat_can_graphical (seat); + if (ret < 0) + return; + +- if (ret != 0) ++ if (ret != 0) { ++ gdm_settings_direct_reload (); + ensure_display_for_seat (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat); +- else ++ } else { + delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat); ++ } + } + + static gboolean + lookup_by_session_id (const char *id, + GdmDisplay *display, + gpointer user_data) + { + const char *looking_for = user_data; + const char *current; + + current = gdm_display_get_session_id (display); + return g_strcmp0 (current, looking_for) == 0; + } + + static gboolean + lookup_by_tty (const char *id, + GdmDisplay *display, + gpointer user_data) + { + const char *tty_to_find = user_data; + g_autofree char *tty_to_check = NULL; + const char *session_id; + int ret; + + session_id = gdm_display_get_session_id (display); + + if (!session_id) + return FALSE; + + ret = sd_session_get_tty (session_id, &tty_to_check); +@@ -1260,60 +1262,61 @@ on_vt_changed (GIOChannel *source, + } + + g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change"); + + ensure_display_for_seat (factory, "seat0"); + + return G_SOURCE_CONTINUE; + } + #endif + + #ifdef HAVE_UDEV + static void + on_uevent (GUdevClient *client, + const char *action, + GUdevDevice *device, + GdmLocalDisplayFactory *factory) + { + if (!g_udev_device_get_device_file (device)) + return; + + if (g_strcmp0 (action, "add") != 0 && + g_strcmp0 (action, "change") != 0) + return; + + if (!udev_is_settled (factory)) + return; + + g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id); + factory->uevent_handler_id = 0; + ++ gdm_settings_direct_reload (); + ensure_display_for_seat (factory, "seat0"); + } + #endif + + static void + gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory) + { + g_autoptr (GIOChannel) io_channel = NULL; + const char *subsystems[] = { "drm", NULL }; + + factory->seat_new_id = g_dbus_connection_signal_subscribe (factory->connection, + "org.freedesktop.login1", + "org.freedesktop.login1.Manager", + "SeatNew", + "/org/freedesktop/login1", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + on_seat_new, + g_object_ref (factory), + g_object_unref); + factory->seat_removed_id = g_dbus_connection_signal_subscribe (factory->connection, + "org.freedesktop.login1", + "org.freedesktop.login1.Manager", + "SeatRemoved", + "/org/freedesktop/login1", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + on_seat_removed, + g_object_ref (factory), + g_object_unref); +-- +2.34.1 + diff --git a/SOURCES/0003-daemon-Infer-session-type-from-desktop-file-if-user-.patch b/SOURCES/0003-daemon-Infer-session-type-from-desktop-file-if-user-.patch index fa2bf13..f0d568b 100644 --- a/SOURCES/0003-daemon-Infer-session-type-from-desktop-file-if-user-.patch +++ b/SOURCES/0003-daemon-Infer-session-type-from-desktop-file-if-user-.patch @@ -1,7 +1,7 @@ -From 3eea287750d63cfe94fe777111e1cd04141eecb3 Mon Sep 17 00:00:00 2001 +From 7084aea50bdc16ccecb4474ca79403429e79ec0e Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 29 Sep 2021 11:03:41 -0400 -Subject: [PATCH 3/3] daemon: Infer session type from desktop file if user has +Subject: [PATCH 3/5] daemon: Infer session type from desktop file if user has no saved session type The accountsservice user cache file can specify a session type @@ -83,5 +83,5 @@ index b54687d5..a65fa0f9 100644 if (conversation->worker_pid == pid) { return conversation; -- -2.31.1 +2.34.1 diff --git a/SOURCES/0004-daemon-Consolidate-session-type-and-supported-sessio.patch b/SOURCES/0004-daemon-Consolidate-session-type-and-supported-sessio.patch new file mode 100644 index 0000000..7968261 --- /dev/null +++ b/SOURCES/0004-daemon-Consolidate-session-type-and-supported-sessio.patch @@ -0,0 +1,559 @@ +From d76d6ff0761d47df938f1dab0daeeecac2feb56e Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 6 Sep 2021 08:43:28 -0400 +Subject: [PATCH 4/5] daemon: Consolidate session-type and + supported-session-types list + +There's currently a bug in computing the session-type to use. + +The `i > 0` check means wayland will overwrite x11 in the +transient session type list. + +Morever, the separation between "session-type" and +"supported-session-types" is a little redundant. Since +supported-session-types is a sorted list, the first item should +always be the same as "session-type". + +This commit addresses the bug and the redundant logic, by computing +the supported session types early in the function and indexing into +it to get the session-type. + +A future cleanup could probably get rid of session-type entirely. + +https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/153 +--- + daemon/gdm-local-display-factory.c | 193 +++++++++++++++++------------ + 1 file changed, 116 insertions(+), 77 deletions(-) + +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index 141d64c6..eba38671 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -197,164 +197,226 @@ get_preferred_display_server (GdmLocalDisplayFactory *factory) + } + + if (!wayland_enabled && !xorg_enabled) { + return g_strdup ("none"); + } + + gdm_settings_direct_get_string (GDM_KEY_PREFERRED_DISPLAY_SERVER, &preferred_display_server); + + if (g_strcmp0 (preferred_display_server, "wayland") == 0) { + if (wayland_enabled) + return g_strdup (preferred_display_server); + else + return g_strdup ("xorg"); + } + + if (g_strcmp0 (preferred_display_server, "xorg") == 0) { + if (xorg_enabled) + return g_strdup (preferred_display_server); + else + return g_strdup ("wayland"); + } + + if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) { + if (xorg_enabled) + return g_strdup (preferred_display_server); + } + + return g_strdup ("none"); + } + ++struct GdmDisplayServerConfiguration { ++ const char *display_server; ++ const char *key; ++ const char *binary; ++ const char *session_type; ++} display_server_configuration[] = { ++#ifdef ENABLE_WAYLAND_SUPPORT ++ { "wayland", GDM_KEY_WAYLAND_ENABLE, "/usr/bin/Xwayland", "wayland" }, ++#endif ++ { "xorg", GDM_KEY_XORG_ENABLE, "/usr/bin/Xorg", "x11" }, ++ { NULL, NULL, NULL }, ++}; ++ ++static gboolean ++display_server_enabled (GdmLocalDisplayFactory *factory, ++ const char *display_server) ++{ ++ size_t i; ++ ++ for (i = 0; display_server_configuration[i].display_server != NULL; i++) { ++ const char *key = display_server_configuration[i].key; ++ const char *binary = display_server_configuration[i].binary; ++ gboolean enabled = FALSE; ++ ++ if (!g_str_equal (display_server_configuration[i].display_server, ++ display_server)) ++ continue; ++ ++ if (!gdm_settings_direct_get_boolean (key, &enabled) || !enabled) ++ return FALSE; ++ ++ if (!g_file_test (binary, G_FILE_TEST_IS_EXECUTABLE)) ++ return FALSE; ++ ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ + static const char * +-gdm_local_display_factory_get_session_type (GdmLocalDisplayFactory *factory, +- gboolean should_fall_back) ++get_session_type_for_display_server (GdmLocalDisplayFactory *factory, ++ const char *display_server) ++{ ++ size_t i; ++ ++ for (i = 0; display_server_configuration[i].display_server != NULL; i++) { ++ if (!g_str_equal (display_server_configuration[i].display_server, ++ display_server)) ++ continue; ++ ++ return display_server_configuration[i].session_type; ++ } ++ ++ return NULL; ++} ++ ++static char ** ++gdm_local_display_factory_get_session_types (GdmLocalDisplayFactory *factory, ++ gboolean should_fall_back) + { +- const char *session_types[3] = { NULL }; +- gsize i, session_type_index = 0; + g_autofree gchar *preferred_display_server = NULL; ++ const char *fallback_display_server = NULL; ++ gboolean wayland_preferred = FALSE; ++ gboolean xorg_preferred = FALSE; ++ g_autoptr (GPtrArray) session_types_array = NULL; ++ char **session_types; ++ ++ session_types_array = g_ptr_array_new (); + + preferred_display_server = get_preferred_display_server (factory); + +- if (g_strcmp0 (preferred_display_server, "wayland") != 0 && +- g_strcmp0 (preferred_display_server, "xorg") != 0) +- return NULL; ++ g_debug ("GdmLocalDisplayFactory: Getting session type (prefers %s, falling back: %s)", ++ preferred_display_server, should_fall_back? "yes" : "no"); + +- for (i = 0; i < G_N_ELEMENTS (session_types) - 1; i++) { +-#ifdef ENABLE_WAYLAND_SUPPORT +- if (i > 0 || +- g_strcmp0 (preferred_display_server, "wayland") == 0) { +- gboolean wayland_enabled = FALSE; +- if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) { +- if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE)) { +- session_types[i] = "wayland"; +- continue; +- } +- } +- } +-#endif ++ wayland_preferred = g_str_equal (preferred_display_server, "wayland"); ++ xorg_preferred = g_str_equal (preferred_display_server, "xorg"); ++ ++ if (wayland_preferred) ++ fallback_display_server = "xorg"; ++ else if (xorg_preferred) ++ fallback_display_server = "wayland"; ++ else ++ return NULL; + +- if (i > 0 || +- g_strcmp0 (preferred_display_server, "xorg") == 0) { +- gboolean xorg_enabled = FALSE; +- if (gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled)) { +- if (xorg_enabled && g_file_test ("/usr/bin/Xorg", G_FILE_TEST_IS_EXECUTABLE)) { +- session_types[i] = "x11"; +- continue; +- } +- } +- } ++ if (!should_fall_back) { ++ if (display_server_enabled (factory, preferred_display_server)) ++ g_ptr_array_add (session_types_array, (gpointer) get_session_type_for_display_server (factory, preferred_display_server)); + } + +- if (should_fall_back) +- session_type_index++; ++ 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)); + +- return session_types[session_type_index]; ++ 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); + } + + /* + 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) { +- session_type = gdm_local_display_factory_get_session_type (factory, FALSE); ++ g_auto(GStrv) session_types = NULL; + +- if (session_type == 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_type, NULL); ++ g_object_set (G_OBJECT (display), ++ "session-type", session_types[0], ++ "supported-session-tyes", 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 (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)) { +@@ -549,243 +611,220 @@ lookup_prepared_display_by_seat_id (const char *id, + + if (status != GDM_DISPLAY_PREPARED) + return FALSE; + + return lookup_by_seat_id (id, display, user_data); + } + + static int + on_seat0_graphics_check_timeout (gpointer user_data) + { + GdmLocalDisplayFactory *factory = user_data; + + factory->seat0_graphics_check_timeout_id = 0; + + /* Simply try to re-add seat0. If it is there already (i.e. CanGraphical + * turned TRUE, then we'll find it and it will not be created again). + */ + factory->seat0_graphics_check_timed_out = TRUE; + ensure_display_for_seat (factory, "seat0"); + + return G_SOURCE_REMOVE; + } + + static void + ensure_display_for_seat (GdmLocalDisplayFactory *factory, + const char *seat_id) + { + int ret; + gboolean seat_supports_graphics; + gboolean is_seat0; +- const char *session_type = "wayland"; ++ g_auto (GStrv) session_types = NULL; ++ const char *legacy_session_types[] = { "x11", NULL }; + GdmDisplayStore *store; + GdmDisplay *display = NULL; + g_autofree char *login_session_id = NULL; + gboolean wayland_enabled = FALSE, xorg_enabled = FALSE; + g_autofree gchar *preferred_display_server = NULL; +- gboolean falling_back; ++ gboolean falling_back = FALSE; + + gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled); + gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled); + + preferred_display_server = get_preferred_display_server (factory); + + if (g_strcmp0 (preferred_display_server, "none") == 0) { + g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display"); + return; + } + + ret = sd_seat_can_graphical (seat_id); + + if (ret < 0) { + g_critical ("Failed to query CanGraphical information for seat %s", seat_id); + return; + } + + if (ret == 0) { + g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics"); + seat_supports_graphics = FALSE; + } else { + g_debug ("GdmLocalDisplayFactory: System supports graphics"); + seat_supports_graphics = TRUE; + } + + if (g_strcmp0 (seat_id, "seat0") == 0) { + is_seat0 = TRUE; + + falling_back = factory->num_failures > 0; +- session_type = gdm_local_display_factory_get_session_type (factory, falling_back); ++ session_types = gdm_local_display_factory_get_session_types (factory, falling_back); + + g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s", +- session_type, falling_back? " fallback" : ""); ++ session_types[0], falling_back? " fallback" : ""); + } else { + is_seat0 = FALSE; + + g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id); + /* Force legacy X11 for all auxiliary seats */ + seat_supports_graphics = TRUE; +- session_type = "x11"; ++ session_types = g_strdupv ((char **) legacy_session_types); + } + + /* For seat0, we have a fallback logic to still try starting it after + * SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if + * CanGraphical is unset. + * This is ugly, but it means we'll come up eventually in some + * scenarios where no master device is present. + * Note that we'll force an X11 fallback even though there might be + * cases where an wayland capable device is present and simply not marked as + * master-of-seat. In these cases, this should likely be fixed in the + * udev rules. + * + * At the moment, systemd always sets CanGraphical for non-seat0 seats. + * This is because non-seat0 seats are defined by having master-of-seat + * set. This means we can avoid the fallback check for non-seat0 seats, + * which simplifies the code. + */ + if (is_seat0) { + if (!seat_supports_graphics) { + if (!factory->seat0_graphics_check_timed_out) { + if (factory->seat0_graphics_check_timeout_id == 0) { + g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT); + factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT, + on_seat0_graphics_check_timeout, + factory); + + } else { + /* 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; +- session_type = "x11"; + 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_type != NULL) ++ if (session_types != NULL) + g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested", +- session_type, seat_id); ++ 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 + 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) { +- g_autoptr (GPtrArray) supported_session_types = NULL; +- +- if (session_type == NULL) { +- g_warning ("GdmLocalDisplayFactory: Both Wayland and Xorg sessions are unavailable"); +- return; +- } +- +- supported_session_types = g_ptr_array_new (); +- +- if (g_strcmp0 (preferred_display_server, "wayland") == 0) { +- if (wayland_enabled) +- g_ptr_array_add (supported_session_types, "wayland"); +- } else { +- if (xorg_enabled) +- g_ptr_array_add (supported_session_types, "x11"); +- } +- +- if (!falling_back) { +- if (g_strcmp0 (preferred_display_server, "wayland") == 0) { +- if (xorg_enabled) +- g_ptr_array_add (supported_session_types, "x11"); +- } else { +- if (wayland_enabled) +- g_ptr_array_add (supported_session_types, "wayland"); +- } +- } +- +- g_ptr_array_add (supported_session_types, NULL); +- + display = gdm_local_display_new (); +- g_object_set (G_OBJECT (display), "session-type", session_type, NULL); +- g_object_set (G_OBJECT (display), "supported-session-types", supported_session_types->pdata, NULL); ++ g_object_set (G_OBJECT (display), ++ "session-type", session_types[0], ++ "supported-session-types", session_types, ++ NULL); + } + } + #endif + + if (display == NULL) { + guint32 num; +- const char *supported_session_types[] = { "x11", NULL }; + + num = take_next_display_number (factory); + + display = gdm_legacy_display_new (num); +- g_object_set (G_OBJECT (display), "supported-session-types", supported_session_types, NULL); ++ g_object_set (G_OBJECT (display), ++ "session-type", legacy_session_types[0], ++ "supported-session-types", legacy_session_types, ++ NULL); + } + + 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 +-- +2.34.1 + diff --git a/SOURCES/0004-data-Use-latest-upstream-udev-rules.patch b/SOURCES/0004-data-Use-latest-upstream-udev-rules.patch new file mode 100644 index 0000000..44abca1 --- /dev/null +++ b/SOURCES/0004-data-Use-latest-upstream-udev-rules.patch @@ -0,0 +1,163 @@ +From 0131864b339dc0cc5f23def75e6caa5872c9ed11 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 7 Mar 2022 10:16:39 -0500 +Subject: [PATCH 4/4] data: Use latest upstream udev rules + +This pulls in the latest udev rule from upstream that gives us +wayland on nvidia when we can, and disables wayland on nvidia +when we should. + +It also pulls in the latest handling for passthrough gpus. +--- + data/61-gdm.rules.in | 139 +++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 135 insertions(+), 4 deletions(-) + +diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in +index b1da191f..5dae00ea 100644 +--- a/data/61-gdm.rules.in ++++ b/data/61-gdm.rules.in +@@ -1,6 +1,137 @@ ++# identify virtio graphics cards to find passthrough setups ++SUBSYSTEM!="virtio", GOTO="gdm_virtio_device_end" ++ACTION!="add", GOTO="gdm_virtio_device_end" ++ATTR{vendor}=="0x1af4", ATTR{device}=="0x0010", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_virtio_device_end" ++LABEL="gdm_virtio_device_end" ++ ++SUBSYSTEM!="pci", GOTO="gdm_pci_device_end" ++ACTION!="bind", GOTO="gdm_pci_device_end" ++ ++# identify virtio graphics cards to find passthrough setups ++# cirrus ++ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end" ++# vga ++ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end" ++# qxl ++ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end" ++ + # disable Wayland on Hi1710 chipsets +-ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" +-# disable Wayland when using the proprietary nvidia driver +-DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" ++ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", GOTO="gdm_disable_wayland" ++ ++# disable Wayland on Matrox chipsets ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", GOTO="gdm_disable_wayland" ++ ++# disable Wayland on aspeed chipsets ++ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", GOTO="gdm_disable_wayland" ++ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", GOTO="gdm_disable_wayland" ++ ++LABEL="gdm_pci_device_end" ++ + # disable Wayland if modesetting is disabled +-IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" ++KERNEL!="card[0-9]*", GOTO="gdm_nomodeset_end" ++SUBSYSTEM!="drm", GOTO="gdm_nomodeset_end" ++IMPORT{parent}="GDM_MACHINE_HAS_VIRTUAL_GPU" ++ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}!="1", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-hardware-gpu" ++# but keep it enabled for simple framebuffer drivers ++DRIVERS=="simple-framebuffer", GOTO="gdm_nomodeset_end" ++IMPORT{cmdline}="nomodeset", GOTO="gdm_disable_wayland" ++LABEL="gdm_nomodeset_end" ++ ++# The vendor nvidia driver has multiple modules that need to be loaded before GDM can make an ++# informed choice on which way to proceed, so force GDM to wait until NVidia's modules are ++# loaded before starting up. ++KERNEL!="nvidia", GOTO="gdm_nvidia_end" ++SUBSYSTEM!="module", GOTO="gdm_nvidia_end" ++ACTION!="add", GOTO="gdm_nvidia_end" ++RUN+="/usr/bin/touch /run/udev/gdm-machine-has-vendor-nvidia-driver" ++ ++# Check if suspend/resume services necessary for working wayland support is available ++TEST{0711}!="/usr/bin/nvidia-sleep.sh", GOTO="gdm_disable_wayland" ++TEST{0711}!="/usr/lib/systemd/system-sleep/nvidia", GOTO="gdm_disable_wayland" ++IMPORT{program}="/bin/sh -c \"sed -e 's/: /=/g' -e 's/\([^[:upper:]]\)\([[:upper:]]\)/\1_\2/g' -e 's/[[:lower:]]/\U&/g' -e 's/^/NVIDIA_/' /proc/driver/nvidia/params\"" ++ENV{NVIDIA_PRESERVE_VIDEO_MEMORY_ALLOCATIONS}!="1", GOTO="gdm_disable_wayland" ++IMPORT{program}="/bin/sh -c 'echo NVIDIA_HIBERNATE=`systemctl is-enabled nvidia-hibernate`'" ++ENV{NVIDIA_HIBERNATE}!="enabled", GOTO="gdm_disable_wayland" ++IMPORT{program}="/bin/sh -c 'echo NVIDIA_RESUME=`systemctl is-enabled nvidia-resume`'" ++ENV{NVIDIA_RESUME}!="enabled", GOTO="gdm_disable_wayland" ++IMPORT{program}="/bin/sh -c 'echo NVIDIA_SUSPEND=`systemctl is-enabled nvidia-suspend`'" ++ENV{NVIDIA_SUSPEND}!="enabled", GOTO="gdm_disable_wayland" ++LABEL="gdm_nvidia_end" ++ ++# If this machine has an internal panel, take note, since it's probably a laptop ++# FIXME: It could be "ghost connectors" make this pop positive for some workstations ++# in the wild. If so, we may have to fallback to looking at the chassis type from ++# dmi data or acpi ++KERNEL!="card[0-9]-eDP-*", GOTO="gdm_laptop_check_end" ++SUBSYSTEM!="drm", GOTO="gdm_laptop_check_end" ++ACTION!="add", GOTO="gdm_laptop_check_end" ++RUN+="/usr/bin/touch /run/udev/gdm-machine-is-laptop" ++GOTO="gdm_hybrid_nvidia_laptop_check" ++LABEL="gdm_laptop_check_end" ++ ++# If this is a hybrid graphics setup, take note ++KERNEL!="card[1-9]*", GOTO="gdm_hybrid_graphics_check_end" ++KERNEL=="card[1-9]-*", GOTO="gdm_hybrid_graphics_check_end" ++SUBSYSTEM!="drm", GOTO="gdm_hybrid_graphics_check_end" ++ACTION!="add", GOTO="gdm_hybrid_graphics_check_end" ++RUN+="/usr/bin/touch /run/udev/gdm-machine-has-hybrid-graphics" ++LABEL="gdm_hybrid_graphics_check_end" ++ ++# If this is a hybrid graphics laptop with vendor nvidia driver, disable wayland ++LABEL="gdm_hybrid_nvidia_laptop_check" ++TEST!="/run/udev/gdm-machine-is-laptop", GOTO="gdm_hybrid_nvidia_laptop_check_end" ++TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_hybrid_nvidia_laptop_check_end" ++TEST!="/run/udev/gdm-machine-has-vendor-nvidia-driver", GOTO="gdm_hybrid_nvidia_laptop_check_end" ++GOTO="gdm_disable_wayland" ++LABEL="gdm_hybrid_nvidia_laptop_check_end" ++ ++# Disable wayland in situation where we're in a guest with a virtual gpu and host passthrough gpu ++LABEL="gdm_virt_passthrough_check" ++TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_virt_passthrough_check_end" ++TEST!="/run/udev/gdm-machine-has-virtual-gpu", GOTO="gdm_virt_passthrough_check_end" ++TEST!="/run/udev/gdm-machine-has-hardware-gpu", GOTO="gdm_virt_passthrough_check_end" ++GOTO="gdm_disable_wayland" ++LABEL="gdm_virt_passthrough_check_end" ++ ++# Disable wayland when there are multiple virtual gpus ++LABEL="gdm_virt_multi_gpu_check" ++TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_virt_multi_gpu_check_end" ++TEST!="/run/udev/gdm-machine-has-virtual-gpu", GOTO="gdm_virt_multi_gpu_check_end" ++TEST=="/run/udev/gdm-machine-has-hardware-gpu", GOTO="gdm_virt_multi_gpu_check_end" ++LABEL="gdm_virt_multi_gpu_check_end" ++ ++# Disable wayland when nvidia modeset is disabled or when drivers are a lower ++# version than 470, ++# For versions above 470 but lower than 510 prefer Xorg, ++# Above 510, prefer Wayland. ++KERNEL!="nvidia_drm", GOTO="gdm_nvidia_drm_end" ++SUBSYSTEM!="module", GOTO="gdm_nvidia_drm_end" ++ACTION!="add", GOTO="gdm_nvidia_drm_end" ++# disable wayland if nvidia-drm modeset is not enabled ++ATTR{parameters/modeset}!="Y", GOTO="gdm_disable_wayland" ++# disable wayland for nvidia drivers versions lower than 470 ++ATTR{version}=="4[0-6][0-9].*|[0-3][0-9][0-9].*|[0-9][0-9].*|[0-9].*", GOTO="gdm_disable_wayland" ++# For nvidia drivers versions Above 510, keep Wayland by default ++ATTR{version}=="[5-9][1-9][0-9].*", GOTO="gdm_end" ++# For nvidia drivers versions 470-495, prefer Xorg by default ++GOTO="gdm_prefer_xorg" ++LABEL="gdm_nvidia_drm_end" ++ ++GOTO="gdm_end" ++ ++LABEL="gdm_prefer_xorg" ++RUN+="@libexecdir@/gdm-runtime-config set daemon PreferredDisplayServer xorg" ++GOTO="gdm_end" ++ ++LABEL="gdm_disable_wayland" ++RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" ++GOTO="gdm_end" ++ ++LABEL="gdm_end" +-- +2.34.1 + diff --git a/SOURCES/0005-local-display-factory-Don-t-crash-if-Xorg-and-Waylan.patch b/SOURCES/0005-local-display-factory-Don-t-crash-if-Xorg-and-Waylan.patch new file mode 100644 index 0000000..800ed00 --- /dev/null +++ b/SOURCES/0005-local-display-factory-Don-t-crash-if-Xorg-and-Waylan.patch @@ -0,0 +1,96 @@ +From 0e467e3fb32d9e2a7499069699527638eb2c2be1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 7 Oct 2021 15:34:27 -0400 +Subject: [PATCH 5/5] local-display-factory: Don't crash if Xorg and Wayland + are both unavailable + +At the moment if Wayland doesn't work, the login screen will fall back +to Xorg, and if Xorg doesn't work the login screen will fall back to +Wayland. + +But if the fall back choice is disabled explicitly, GDM will just crash. + +This commit fixes the crash. + +Closes: https://gitlab.gnome.org/GNOME/gdm/-/issues/739 +--- + daemon/gdm-local-display-factory.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index eba38671..120847f9 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -651,62 +651,67 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, + gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled); + + preferred_display_server = get_preferred_display_server (factory); + + if (g_strcmp0 (preferred_display_server, "none") == 0) { + g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display"); + return; + } + + ret = sd_seat_can_graphical (seat_id); + + if (ret < 0) { + g_critical ("Failed to query CanGraphical information for seat %s", seat_id); + return; + } + + if (ret == 0) { + g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics"); + seat_supports_graphics = FALSE; + } else { + g_debug ("GdmLocalDisplayFactory: System supports graphics"); + seat_supports_graphics = TRUE; + } + + if (g_strcmp0 (seat_id, "seat0") == 0) { + is_seat0 = TRUE; + + falling_back = factory->num_failures > 0; + session_types = gdm_local_display_factory_get_session_types (factory, falling_back); + +- g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s", +- session_types[0], falling_back? " fallback" : ""); ++ if (session_types == NULL) { ++ g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable"); ++ seat_supports_graphics = FALSE; ++ } else { ++ g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s", ++ session_types[0], falling_back? " fallback" : ""); ++ } + } else { + is_seat0 = FALSE; + + g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id); + /* Force legacy X11 for all auxiliary seats */ + seat_supports_graphics = TRUE; + session_types = g_strdupv ((char **) legacy_session_types); + } + + /* For seat0, we have a fallback logic to still try starting it after + * SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if + * CanGraphical is unset. + * This is ugly, but it means we'll come up eventually in some + * scenarios where no master device is present. + * Note that we'll force an X11 fallback even though there might be + * cases where an wayland capable device is present and simply not marked as + * master-of-seat. In these cases, this should likely be fixed in the + * udev rules. + * + * At the moment, systemd always sets CanGraphical for non-seat0 seats. + * This is because non-seat0 seats are defined by having master-of-seat + * set. This means we can avoid the fallback check for non-seat0 seats, + * which simplifies the code. + */ + if (is_seat0) { + if (!seat_supports_graphics) { + if (!factory->seat0_graphics_check_timed_out) { + if (factory->seat0_graphics_check_timeout_id == 0) { + g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT); + factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT, +-- +2.34.1 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index 8ab5bb5..cdf00f1 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -11,7 +11,7 @@ Name: gdm Epoch: 1 Version: 40.1 -Release: 11%{?dist} +Release: 13%{?dist}.2 Summary: The GNOME Display Manager License: GPLv2+ @@ -28,26 +28,37 @@ Patch10001: 0001-local-display-factory-Provide-more-flexibility-for-c.patch Patch20001: 0001-xdmcp-display-factory-Set-supported-session-types-fo.patch Patch20002: 0002-daemon-Don-t-update-session-type-if-no-saved-session.patch Patch20003: 0003-daemon-Infer-session-type-from-desktop-file-if-user-.patch +Patch20004: 0004-daemon-Consolidate-session-type-and-supported-sessio.patch +Patch20005: 0005-local-display-factory-Don-t-crash-if-Xorg-and-Waylan.patch Patch30001: 0001-local-display-factory-Don-t-try-to-respawn-displays-.patch Patch40001: 0001-session-worker-Set-session_vt-0-out-of-pam-uninitial.patch -# Questionable feature to support logging in over multiple XDMCP consoles at the same time -Patch60001: 0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch -Patch60002: 0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch -Patch60003: 0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch +Patch50001: 0001-meson-Fix-detection-of-Xorg-versions-that-need-liste.patch +Patch50002: 0002-daemon-Support-X-servers-built-with-Dlisten_tcp-true.patch + +Patch60001: 0001-session-settings-Fetch-session-from-user-even-if-use.patch + +# Latest udev rules and support code +Patch70001: 0001-local-display-factory-Stall-startup-until-main-graph.patch +Patch70002: 0002-common-Add-API-to-reload-settings-from-disk.patch +Patch70003: 0003-common-Reload-settings-when-graphics-initialize.patch +Patch70004: 0004-data-Use-latest-upstream-udev-rules.patch # Non-upstreamable workarounds Patch66610001: 0001-data-reap-gdm-sessions-on-shutdown.patch +# Questionable feature to support logging in over multiple XDMCP consoles at the same time +Patch66620001: 0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch +Patch66620002: 0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch +Patch66620003: 0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch + # Non-upstreamable integration patches Patch99910001: 0001-Honor-initial-setup-being-disabled-by-distro-install.patch Patch99930001: 0001-data-add-system-dconf-databases-to-gdm-profile.patch -Patch99940001: 0001-data-disable-wayland-on-certain-hardware.patch - Patch99950001: 0001-data-Disable-network-configuration-on-login-screen.patch @@ -68,6 +79,7 @@ BuildRequires: pkgconfig(accountsservice) >= 0.6.3 BuildRequires: pkgconfig(check) BuildRequires: pkgconfig(gobject-introspection-1.0) BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} +BuildRequires: pkgconfig(gudev-1.0) BuildRequires: pkgconfig(iso-codes) BuildRequires: pkgconfig(libcanberra-gtk3) BuildRequires: pkgconfig(libselinux) @@ -333,6 +345,25 @@ dconf update || : %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Thu Mar 24 2022 Ray Strode - 40.1-13.2 +- Fix erroneous jump back to login screen on udev events after login + Resolves: #2065901 + +* Wed Mar 09 2022 Ray Strode - 40.1-13.1 +- Fix accountsservice user templates + Resolves: #2057483 + +* Mon Mar 07 2022 Ray Strode - 40.1-13 +- Pull in latest udev rules and race fixes for handling + udev rules. + Related: #2017938 + +* Tue Feb 22 2022 Ray Strode - 40.1-12 +- More fixes from RHEL 8: + - Fix DisallowTCP=false + - Fix crash when both wayland and xorg are unavailable + Related: #2056931 + * Wed Oct 27 2021 Ray Strode - 40.1-11 - Pull in RHEL 8 patches and drop unused patches Related: #2017859