From 9518ddfb0c62118859127c8aadb44cdc25f22bd9 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 7 Dec 2021 13:22:59 -0500 Subject: [PATCH] import gdm-40.1-11.el9 --- ...tup-being-disabled-by-distro-install.patch | 103 +++++- ...etwork-configuration-on-login-screen.patch | 103 ++++++ ...ystem-dconf-databases-to-gdm-profile.patch | 6 +- ...1-data-reap-gdm-sessions-on-shutdown.patch | 55 +++ ...ctory-Don-t-try-to-respawn-displays-.patch | 325 +++++++++++++++++ ...ltiple-xdmcp-logins-for-the-same-use.patch | 344 ++++++++++++++++++ ...et-session_vt-0-out-of-pam-uninitial.patch | 84 +++++ ...ctory-Set-supported-session-types-fo.patch | 122 +++++++ ...ate-session-type-if-no-saved-session.patch | 109 ++++++ ...n-run-session-bus-on-non-seat0-seats.patch | 151 ++++++++ ...sion-type-from-desktop-file-if-user-.patch | 87 +++++ ...ogin-screen-over-XDMCP-connects-to-i.patch | 105 ++++++ SOURCES/default.pa-for-gdm | 1 - SPECS/gdm.spec | 51 ++- 14 files changed, 1629 insertions(+), 17 deletions(-) create mode 100644 SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch create mode 100644 SOURCES/0001-data-reap-gdm-sessions-on-shutdown.patch create mode 100644 SOURCES/0001-local-display-factory-Don-t-try-to-respawn-displays-.patch create mode 100644 SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch create mode 100644 SOURCES/0001-session-worker-Set-session_vt-0-out-of-pam-uninitial.patch create mode 100644 SOURCES/0001-xdmcp-display-factory-Set-supported-session-types-fo.patch create mode 100644 SOURCES/0002-daemon-Don-t-update-session-type-if-no-saved-session.patch create mode 100644 SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch create mode 100644 SOURCES/0003-daemon-Infer-session-type-from-desktop-file-if-user-.patch create mode 100644 SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch diff --git a/SOURCES/0001-Honor-initial-setup-being-disabled-by-distro-install.patch b/SOURCES/0001-Honor-initial-setup-being-disabled-by-distro-install.patch index b46e5e4..b712857 100644 --- a/SOURCES/0001-Honor-initial-setup-being-disabled-by-distro-install.patch +++ b/SOURCES/0001-Honor-initial-setup-being-disabled-by-distro-install.patch @@ -1,4 +1,4 @@ -From 42b18e4c84d470f33cdec5fc1f481cb25c25cf0d Mon Sep 17 00:00:00 2001 +From f6ebcec5d48aeff718a9db9b8ff812fd404a61ed Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Mon, 23 Jan 2017 20:19:51 +0100 Subject: [PATCH] Honor initial setup being disabled by distro installer @@ -14,15 +14,41 @@ that but more might be added in the future. https://bugzilla.gnome.org/show_bug.cgi?id=777708 --- - daemon/Makefile.am | 1 + daemon/gdm-display.c | 29 +++++++++++++++++++++++++++++ - 2 files changed, 30 insertions(+) + 1 file changed, 29 insertions(+) diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c -index 5e193f2..878be88 100644 +index 34467856..9438fe72 100644 --- a/daemon/gdm-display.c +++ b/daemon/gdm-display.c -@@ -1547,6 +1547,31 @@ kernel_cmdline_initial_setup_force_state (gboolean *force_state) +@@ -1621,103 +1621,132 @@ kernel_cmdline_initial_setup_force_state (gboolean *force_state) + GError *error = NULL; + gchar *contents = NULL; + gchar *setup_argument = NULL; + + g_return_val_if_fail (force_state != NULL, FALSE); + + if (!g_file_get_contents ("/proc/cmdline", &contents, NULL, &error)) { + g_debug ("GdmDisplay: Could not check kernel parameters, not forcing initial setup: %s", + error->message); + g_clear_error (&error); + return FALSE; + } + + g_debug ("GdmDisplay: Checking kernel command buffer %s", contents); + + if (!kernel_cmdline_initial_setup_argument (contents, &setup_argument, &error)) { + g_debug ("GdmDisplay: Failed to read kernel commandline: %s", error->message); + g_clear_pointer (&contents, g_free); + return FALSE; + } + + g_clear_pointer (&contents, g_free); + + /* Poor-man's check for truthy or falsey values */ + *force_state = setup_argument[0] == '1'; + + g_free (setup_argument); return TRUE; } @@ -54,7 +80,43 @@ index 5e193f2..878be88 100644 static gboolean wants_initial_setup (GdmDisplay *self) { -@@ -1587,6 +1612,10 @@ wants_initial_setup (GdmDisplay *self) + GdmDisplayPrivate *priv; + gboolean enabled = FALSE; + gboolean forced = FALSE; + + priv = gdm_display_get_instance_private (self); + + if (already_done_initial_setup_on_this_boot ()) { + return FALSE; + } + + if (kernel_cmdline_initial_setup_force_state (&forced)) { + if (forced) { + g_debug ("GdmDisplay: Forcing gnome-initial-setup"); + return TRUE; + } + + g_debug ("GdmDisplay: Forcing no gnome-initial-setup"); + return FALSE; + } + + /* don't run initial-setup on remote displays + */ + if (!priv->is_local) { + return FALSE; + } + + /* don't run if the system has existing users */ + if (priv->have_existing_user_accounts) { + return FALSE; + } + + /* don't run if initial-setup is unavailable */ + if (!can_create_environment ("gnome-initial-setup")) { + return FALSE; + } + + if (!gdm_settings_direct_get_boolean (GDM_KEY_INITIAL_SETUP_ENABLE, &enabled)) { return FALSE; } @@ -65,6 +127,33 @@ index 5e193f2..878be88 100644 return enabled; } + void + gdm_display_start_greeter_session (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + GdmSession *session; + char *display_name; + char *seat_id; + char *hostname; + char *auth_file = NULL; + + priv = gdm_display_get_instance_private (self); + g_return_if_fail (g_strcmp0 (priv->session_class, "greeter") == 0); + + g_debug ("GdmDisplay: Running greeter"); + + display_name = NULL; + seat_id = NULL; + hostname = NULL; + + g_object_get (self, + "x11-display-name", &display_name, + "seat-id", &seat_id, + "remote-hostname", &hostname, + NULL); + if (priv->access_file != NULL) { + auth_file = gdm_display_access_file_get_path (priv->access_file); + } -- -2.19.0 +2.32.0 diff --git a/SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch b/SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch new file mode 100644 index 0000000..7a1d38d --- /dev/null +++ b/SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch @@ -0,0 +1,103 @@ +From aa1c4a7708df2edbc12f2ada7249208aef586d1e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 8 Jun 2021 20:45:00 +0200 +Subject: [PATCH] data: Disable network configuration on login screen + +--- + data/meson.build | 10 ++++++++++ + data/org.gnome.gdm.rules.in | 8 ++++++++ + 2 files changed, 18 insertions(+) + create mode 100644 data/org.gnome.gdm.rules.in + +diff --git a/data/meson.build b/data/meson.build +index 7c5222ea..20d39a36 100644 +--- a/data/meson.build ++++ b/data/meson.build +@@ -130,60 +130,70 @@ pam_data_files_map = { + ], + 'arch': [ + 'gdm-autologin', + 'gdm-launch-environment', + 'gdm-fingerprint', + 'gdm-smartcard', + 'gdm-password', + ], + 'none': [], + # We should no longer have 'autodetect' at this point + } + + pam_data_files = pam_data_files_map[default_pam_config] + pam_prefix = (get_option('pam-prefix') != '')? get_option('pam-prefix') : get_option('sysconfdir') + foreach _pam_filename : pam_data_files + install_data('pam-@0@/@1@.pam'.format(default_pam_config, _pam_filename), + rename: _pam_filename, + install_dir: pam_prefix / 'pam.d', + ) + endforeach + + gdm_rules = configure_file( + input: '61-gdm.rules.in', + output: '@BASENAME@', + configuration: { + 'libexecdir': gdm_prefix / get_option('libexecdir'), + }, + install_dir: udev_dir, + ) + ++# Polkit rules ++polkit_rules = configure_file( ++ input: 'org.gnome.gdm.rules.in', ++ output: '@BASENAME@', ++ configuration: { ++ 'GDM_USERNAME': get_option('user'), ++ }, ++ install_dir: get_option('datadir') / 'polkit-1' / 'rules.d', ++) ++ + # DBus service files + service_config = configuration_data() + service_config.set('sbindir', gdm_prefix / get_option('sbindir')) + service_config.set('GDM_INITIAL_VT', get_option('initial-vt')) + service_config.set('LANG_CONFIG_FILE', lang_config_file) + if plymouth_dep.found() + service_config.set('PLYMOUTH_QUIT_SERVICE', 'plymouth-quit.service') + else + service_config.set('PLYMOUTH_QUIT_SERVICE', '') + endif + + if get_option('systemdsystemunitdir') != '' + systemd_systemunitdir = get_option('systemdsystemunitdir') + else + systemd_systemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir') + endif + + if get_option('systemduserunitdir') != '' + systemd_userunitdir = get_option('systemduserunitdir') + else + systemd_userunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir', + define_variable: ['prefix', get_option('prefix')]) + endif + + configure_file( + input: 'gdm.service.in', + output: '@BASENAME@', + configuration: service_config, + install_dir: systemd_systemunitdir, + format: 'cmake' +diff --git a/data/org.gnome.gdm.rules.in b/data/org.gnome.gdm.rules.in +new file mode 100644 +index 00000000..09544f11 +--- /dev/null ++++ b/data/org.gnome.gdm.rules.in +@@ -0,0 +1,8 @@ ++polkit.addRule(function(action, subject) { ++ if (action.id == "org.freedesktop.NetworkManager.network-control" && ++ subject.user == "@GDM_USERNAME@") { ++ return polkit.Result.NO; ++ } ++ ++ return polkit.Result.NOT_HANDLED; ++}); +-- +2.32.0 + diff --git a/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch b/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch index 2985995..bfaf66c 100644 --- a/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch +++ b/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch @@ -1,4 +1,4 @@ -From b1557adf711577c62609f8a784f11fad66eb54ef Mon Sep 17 00:00:00 2001 +From 3e62d7b423175102bd2376adc9cf58ad736b23b0 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 31 Jul 2013 17:32:55 -0400 Subject: [PATCH] data: add system dconf databases to gdm profile @@ -9,7 +9,7 @@ This way system settings can affect the login screen. 1 file changed, 4 insertions(+) diff --git a/data/dconf/gdm.in b/data/dconf/gdm.in -index 4d8bf1748..9694078fb 100644 +index 4d8bf174..9694078f 100644 --- a/data/dconf/gdm.in +++ b/data/dconf/gdm.in @@ -1,2 +1,6 @@ @@ -20,5 +20,5 @@ index 4d8bf1748..9694078fb 100644 +system-db:distro file-db:@DATADIR@/@PACKAGE@/greeter-dconf-defaults -- -2.28.0 +2.32.0 diff --git a/SOURCES/0001-data-reap-gdm-sessions-on-shutdown.patch b/SOURCES/0001-data-reap-gdm-sessions-on-shutdown.patch new file mode 100644 index 0000000..fb878aa --- /dev/null +++ b/SOURCES/0001-data-reap-gdm-sessions-on-shutdown.patch @@ -0,0 +1,55 @@ +From a4743b9b2b355f84da3904e7da93ec3c7a521895 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 26 Jul 2019 14:06:16 -0400 +Subject: [PATCH] data: reap gdm sessions on shutdown + +If GDM gets shutdown we should make sure all sessions get shutdown too. + +This is a bit of a safety net in case any processes in the session are +lingering after the orderly shutdown. +--- + data/gdm.service.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/data/gdm.service.in b/data/gdm.service.in +index 17e8a8de..195bd0fd 100644 +--- a/data/gdm.service.in ++++ b/data/gdm.service.in +@@ -1,33 +1,34 @@ + [Unit] + Description=GNOME Display Manager + + # replaces the getty + Conflicts=getty@tty${GDM_INITIAL_VT}.service + After=getty@tty${GDM_INITIAL_VT}.service + + # replaces plymouth-quit since it quits plymouth on its own + Conflicts=${PLYMOUTH_QUIT_SERVICE} + After=${PLYMOUTH_QUIT_SERVICE} + + # Needs all the dependencies of the services it's replacing + # pulled from getty@.service and ${PLYMOUTH_QUIT_SERVICE} + # (except for plymouth-quit-wait.service since it waits until + # plymouth is quit, which we do) + After=rc-local.service plymouth-start.service systemd-user-sessions.service + + # GDM takes responsibility for stopping plymouth, so if it fails + # for any reason, make sure plymouth still stops + OnFailure=plymouth-quit.service + + [Service] + ExecStart=${sbindir}/gdm ++ExecStopPost=-/usr/bin/bash -c 'for f in /run/systemd/sessions/*; do [ -f $f ] && /usr/bin/fgrep -q SERVICE=gdm $f && loginctl terminate-session $(basename $f); done' + KillMode=mixed + Restart=always + IgnoreSIGPIPE=no + BusName=org.gnome.DisplayManager + EnvironmentFile=-${LANG_CONFIG_FILE} + ExecReload=/bin/kill -SIGHUP $MAINPID + KeyringMode=shared + + [Install] + Alias=display-manager.service +-- +2.32.0 + diff --git a/SOURCES/0001-local-display-factory-Don-t-try-to-respawn-displays-.patch b/SOURCES/0001-local-display-factory-Don-t-try-to-respawn-displays-.patch new file mode 100644 index 0000000..45344c5 --- /dev/null +++ b/SOURCES/0001-local-display-factory-Don-t-try-to-respawn-displays-.patch @@ -0,0 +1,325 @@ +From 9261fcd05667fc5f8b81880577e41a566db821a8 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 15 Sep 2021 11:23:17 -0400 +Subject: [PATCH] local-display-factory: Don't try to respawn displays on + shutdown + +At the moment in the shutdown path we may try to respawn displays +that just got killed. + +The respawning happens when things are half torn down leading to +crashes. + +This commit makes sure we turn off the respawn logic in the shutdown +path. +--- + daemon/gdm-local-display-factory.c | 11 ++++++++++- + daemon/gdm-manager.c | 2 ++ + 2 files changed, 12 insertions(+), 1 deletion(-) + +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index 141d64c6..bca41f6e 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -46,60 +46,62 @@ + #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; + + 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_graphics_check_timed_out; + guint seat0_graphics_check_timeout_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); + + G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY) + + GQuark + gdm_local_display_factory_error_quark (void) + { + static GQuark ret = 0; + if (ret == 0) { +@@ -416,60 +418,64 @@ on_session_registered_cb (GObject *gobject, + GParamSpec *pspec, + gpointer user_data) + { + GdmDisplay *display = GDM_DISPLAY (gobject); + GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (user_data); + gboolean registered; + + g_object_get (display, "session-registered", ®istered, NULL); + + if (!registered) + return; + + g_debug ("GdmLocalDisplayFactory: session registered on display, looking for any background displays to kill"); + + finish_waiting_displays_on_seat (factory, "seat0"); + } + + static void + on_display_status_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmLocalDisplayFactory *factory) + { + int status; + int num; + char *seat_id = NULL; + char *session_type = NULL; + char *session_class = NULL; + gboolean is_initial = TRUE; + gboolean is_local = TRUE; + ++ ++ if (!factory->is_started) ++ return; ++ + num = -1; + gdm_display_get_x11_display_number (display, &num, NULL); + + g_object_get (display, + "seat-id", &seat_id, + "is-initial", &is_initial, + "is-local", &is_local, + "session-type", &session_type, + "session-class", &session_class, + NULL); + + status = gdm_display_get_status (display); + + g_debug ("GdmLocalDisplayFactory: display status changed: %d", status); + switch (status) { + case GDM_DISPLAY_FINISHED: + /* remove the display number from factory->used_display_numbers + so that it may be reused */ + if (num != -1) { + g_hash_table_remove (factory->used_display_numbers, GUINT_TO_POINTER (num)); + } + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); + + /* if this is a local display, do a full resync. Only + * seats without displays will get created anyway. This + * ensures we get a new login screen when the user logs out, + * if there isn't one. + */ + if (is_local && g_strcmp0 (session_class, "greeter") != 0) { + /* reset num failures */ +@@ -1204,99 +1210,102 @@ on_display_added (GdmDisplayStore *display_store, + + display = gdm_display_store_lookup (display_store, id); + + if (display != NULL) { + g_signal_connect_object (display, "notify::status", + G_CALLBACK (on_display_status_changed), + factory, + 0); + + g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory); + } + } + + static void + on_display_removed (GdmDisplayStore *display_store, + GdmDisplay *display, + GdmLocalDisplayFactory *factory) + { + g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), factory); + g_object_weak_unref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory); + } + + static gboolean + gdm_local_display_factory_start (GdmDisplayFactory *base_factory) + { + GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory); + GdmDisplayStore *store; + + g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE); + ++ factory->is_started = TRUE; ++ + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + + g_signal_connect_object (G_OBJECT (store), + "display-added", + G_CALLBACK (on_display_added), + factory, + 0); + + g_signal_connect_object (G_OBJECT (store), + "display-removed", + G_CALLBACK (on_display_removed), + factory, + 0); + + gdm_local_display_factory_start_monitor (factory); + return gdm_local_display_factory_sync_seats (factory); + } + + static gboolean + gdm_local_display_factory_stop (GdmDisplayFactory *base_factory) + { + GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory); + GdmDisplayStore *store; + + g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE); + + gdm_local_display_factory_stop_monitor (factory); + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + + g_signal_handlers_disconnect_by_func (G_OBJECT (store), + G_CALLBACK (on_display_added), + factory); + g_signal_handlers_disconnect_by_func (G_OBJECT (store), + G_CALLBACK (on_display_removed), + factory); +- + g_clear_handle_id (&factory->seat0_graphics_check_timeout_id, g_source_remove); + ++ factory->is_started = FALSE; ++ + return TRUE; + } + + static void + gdm_local_display_factory_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) + { + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static void + gdm_local_display_factory_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static gboolean +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 4c2752fe..cc61efc9 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -2741,60 +2741,62 @@ unexport_display (const char *id, + GdmDisplay *display, + GdmManager *manager) + { + if (!g_dbus_connection_is_closed (manager->priv->connection)) + g_dbus_object_manager_server_unexport (manager->priv->object_manager, id); + } + + static void + finish_display (const char *id, + GdmDisplay *display, + GdmManager *manager) + { + gdm_display_stop_greeter_session (display); + if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) + gdm_display_unmanage (display); + gdm_display_finish (display); + } + + static void + gdm_manager_dispose (GObject *object) + { + GdmManager *manager; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_MANAGER (object)); + + manager = GDM_MANAGER (object); + + g_return_if_fail (manager->priv != NULL); + ++ gdm_manager_stop (manager); ++ + g_clear_weak_pointer (&manager->priv->automatic_login_display); + + #ifdef HAVE_LIBXDMCP + g_clear_object (&manager->priv->xdmcp_factory); + #endif + g_clear_object (&manager->priv->local_factory); + g_clear_pointer (&manager->priv->open_reauthentication_requests, + g_hash_table_unref); + g_clear_pointer (&manager->priv->transient_sessions, + g_hash_table_unref); + + g_list_foreach (manager->priv->user_sessions, + (GFunc) gdm_session_close, + NULL); + g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref); + manager->priv->user_sessions = NULL; + + g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store), + G_CALLBACK (on_display_added), + manager); + g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store), + G_CALLBACK (on_display_removed), + manager); + + if (!g_dbus_connection_is_closed (manager->priv->connection)) { + gdm_display_store_foreach (manager->priv->display_store, + (GdmDisplayStoreFunc)unexport_display, + manager); + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager)); + } +-- +2.32.0 + diff --git a/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch b/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch new file mode 100644 index 0000000..13b39da --- /dev/null +++ b/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch @@ -0,0 +1,344 @@ +From 2e7965beae81e0e93d3f475f2ea29a7af6c23f29 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 20 Dec 2018 14:51:38 -0500 +Subject: [PATCH 1/3] manager: allow multiple xdmcp logins for the same user + +--- + common/gdm-settings-keys.h | 1 + + daemon/gdm-manager.c | 71 ++++++++++++++++++++++++++++---------- + data/gdm.schemas.in | 5 +++ + 3 files changed, 59 insertions(+), 18 deletions(-) + +diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h +index 87685d3c..4b3a1ffe 100644 +--- a/common/gdm-settings-keys.h ++++ b/common/gdm-settings-keys.h +@@ -30,37 +30,38 @@ G_BEGIN_DECLS + #define GDM_KEY_AUTO_LOGIN_ENABLE "daemon/AutomaticLoginEnable" + #define GDM_KEY_AUTO_LOGIN_USER "daemon/AutomaticLogin" + #define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable" + #define GDM_KEY_TIMED_LOGIN_USER "daemon/TimedLogin" + #define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay" + #define GDM_KEY_INITIAL_SETUP_ENABLE "daemon/InitialSetupEnable" + #define GDM_KEY_PREFERRED_DISPLAY_SERVER "daemon/PreferredDisplayServer" + #define GDM_KEY_WAYLAND_ENABLE "daemon/WaylandEnable" + #define GDM_KEY_XORG_ENABLE "daemon/XorgEnable" + + #define GDM_KEY_DEBUG "debug/Enable" + + #define GDM_KEY_INCLUDE "greeter/Include" + #define GDM_KEY_EXCLUDE "greeter/Exclude" + #define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll" + + #define GDM_KEY_DISALLOW_TCP "security/DisallowTCP" + #define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin" + + #define GDM_KEY_XDMCP_ENABLE "xdmcp/Enable" + #define GDM_KEY_SHOW_LOCAL_GREETER "xdmcp/ShowLocalGreeter" + #define GDM_KEY_MAX_PENDING "xdmcp/MaxPending" + #define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions" + #define GDM_KEY_MAX_WAIT "xdmcp/MaxWait" + #define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost" + #define GDM_KEY_UDP_PORT "xdmcp/Port" + #define GDM_KEY_INDIRECT "xdmcp/HonorIndirect" + #define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect" + #define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds" + #define GDM_KEY_WILLING "xdmcp/Willing" ++#define GDM_KEY_ALLOW_MULTIPLE_SESSIONS_PER_USER "xdmcp/AllowMultipleSessionsPerUser" + + #define GDM_KEY_MULTICAST "chooser/Multicast" + #define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr" + + G_END_DECLS + + #endif /* _GDM_SETTINGS_KEYS_H */ +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index cc61efc9..dc839aeb 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -566,93 +566,106 @@ get_display_and_details_for_bus_sender (GdmManager *self, + *out_tty = get_tty_for_session_id (session_id, &error); + + if (error != NULL) { + g_debug ("GdmManager: Error while retrieving tty for session: %s", + error->message); + g_clear_error (&error); + } + } + + display = gdm_display_store_find (self->priv->display_store, + lookup_by_session_id, + (gpointer) session_id); + + out: + if (out_display != NULL) { + *out_display = display; + } + + g_free (session_id); + } + + static gboolean + switch_to_compatible_user_session (GdmManager *manager, + GdmSession *session, + gboolean fail_if_already_switched) + { + gboolean res; + gboolean ret; + const char *username; + const char *seat_id; +- const char *ssid_to_activate; ++ const char *ssid_to_activate = NULL; + GdmSession *existing_session; + + ret = FALSE; + + username = gdm_session_get_username (session); + seat_id = gdm_session_get_display_seat_id (session); + +- if (!fail_if_already_switched) { +- session = NULL; +- } ++ if (!fail_if_already_switched) ++ ssid_to_activate = gdm_session_get_session_id (session); + +- existing_session = find_session_for_user_on_seat (manager, username, seat_id, session); ++ if (ssid_to_activate == NULL) { ++ if (!seat_id || !sd_seat_can_multi_session (seat_id)) { ++ g_debug ("GdmManager: unable to activate existing sessions from login screen unless on seat0"); ++ goto out; ++ } + +- if (existing_session != NULL) { +- ssid_to_activate = gdm_session_get_session_id (existing_session); +- if (seat_id != NULL) { +- res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate); +- if (! res) { +- g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate); +- goto out; +- } ++ if (!fail_if_already_switched) { ++ session = NULL; + } + +- res = session_unlock (manager, ssid_to_activate); +- if (!res) { +- /* this isn't fatal */ +- g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate); ++ existing_session = find_session_for_user_on_seat (manager, username, seat_id, session); ++ ++ if (existing_session != NULL) { ++ ssid_to_activate = gdm_session_get_session_id (existing_session); + } +- } else { ++ } ++ ++ if (ssid_to_activate == NULL) { + goto out; + } + ++ if (seat_id != NULL) { ++ res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate); ++ if (! res) { ++ g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate); ++ goto out; ++ } ++ } ++ ++ res = session_unlock (manager, ssid_to_activate); ++ if (!res) { ++ /* this isn't fatal */ ++ g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate); ++ } ++ + ret = TRUE; + + out: + return ret; + } + + static GdmDisplay * + get_display_for_user_session (GdmSession *session) + { + return g_object_get_data (G_OBJECT (session), "gdm-display"); + } + + static GdmSession * + get_user_session_for_display (GdmDisplay *display) + { + if (display == NULL) { + return NULL; + } + + return g_object_get_data (G_OBJECT (display), "gdm-user-session"); + } + + static gboolean + add_session_record (GdmManager *manager, + GdmSession *session, + GPid pid, + SessionRecord record) + { + const char *username; + char *display_name, *hostname, *display_device; +@@ -1089,92 +1102,114 @@ open_temporary_reauthentication_channel (GdmManager *self, + g_signal_connect (session, + "client-disconnected", + G_CALLBACK (on_reauthentication_client_disconnected), + self); + g_signal_connect (session, + "client-rejected", + G_CALLBACK (on_reauthentication_client_rejected), + self); + g_signal_connect (session, + "cancelled", + G_CALLBACK (on_reauthentication_cancelled), + self); + g_signal_connect (session, + "conversation-started", + G_CALLBACK (on_reauthentication_conversation_started), + self); + g_signal_connect (session, + "conversation-stopped", + G_CALLBACK (on_reauthentication_conversation_stopped), + self); + g_signal_connect (session, + "verification-complete", + G_CALLBACK (on_reauthentication_verification_complete), + self); + + address = gdm_session_get_server_address (session); + + return g_strdup (address); + } + ++static gboolean ++remote_users_can_log_in_more_than_once (GdmManager *manager) ++{ ++ gboolean enabled; ++ ++ enabled = FALSE; ++ ++ gdm_settings_direct_get_boolean (GDM_KEY_ALLOW_MULTIPLE_SESSIONS_PER_USER, &enabled); ++ ++ g_debug ("GdmDisplay: Remote users allowed to log in more than once: %s", enabled? "yes" : "no"); ++ ++ return enabled; ++} ++ + static gboolean + gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager, + GDBusMethodInvocation *invocation, + const char *username) + { + GdmManager *self = GDM_MANAGER (manager); + const char *sender; + GdmDisplay *display = NULL; + GdmSession *session; + GDBusConnection *connection; + char *seat_id = NULL; + char *session_id = NULL; + GPid pid = 0; + uid_t uid = (uid_t) -1; + gboolean is_login_screen = FALSE; + gboolean is_remote = FALSE; + + g_debug ("GdmManager: trying to open reauthentication channel for user %s", username); + + sender = g_dbus_method_invocation_get_sender (invocation); + connection = g_dbus_method_invocation_get_connection (invocation); + get_display_and_details_for_bus_sender (self, connection, sender, &display, &seat_id, &session_id, NULL, &pid, &uid, &is_login_screen, &is_remote); + + if (session_id == NULL || pid == 0 || uid == (uid_t) -1) { + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + _("No session available")); + + return TRUE; + } + ++ if (is_login_screen && is_remote && remote_users_can_log_in_more_than_once (self)) { ++ g_dbus_method_invocation_return_error_literal (invocation, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_ACCESS_DENIED, ++ "Login screen creates new sessions for remote connections"); ++ return TRUE; ++ } ++ + if (is_login_screen) { + g_debug ("GdmManager: looking for login screen session for user %s on seat %s", username, seat_id); + session = find_session_for_user_on_seat (self, + username, + seat_id, + NULL); + } else { + g_debug ("GdmManager: looking for user session on display"); + session = get_user_session_for_display (display); + } + + if (session != NULL && gdm_session_is_running (session)) { + gdm_session_start_reauthentication (session, pid, uid); + g_hash_table_insert (self->priv->open_reauthentication_requests, + GINT_TO_POINTER (pid), + invocation); + } else if (is_login_screen) { + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + "Login screen only allowed to open reauthentication channels for running sessions"); + return TRUE; + } else { + char *address; + address = open_temporary_reauthentication_channel (self, + seat_id, + session_id, + pid, + uid, + is_remote); +diff --git a/data/gdm.schemas.in b/data/gdm.schemas.in +index a1035f95..929d13d9 100644 +--- a/data/gdm.schemas.in ++++ b/data/gdm.schemas.in +@@ -112,33 +112,38 @@ + + xdmcp/DisplaysPerHost + i + 1 + + + xdmcp/Port + i + 177 + + + xdmcp/HonorIndirect + b + true + + + xdmcp/MaxWaitIndirect + i + 30 + + + xdmcp/PingIntervalSeconds + i + 0 + + + xdmcp/Willing + s + @gdmconfdir@/Xwilling + ++ ++ xdmcp/AllowMultipleSessionsPerUser ++ b ++ false ++ + + + +-- +2.32.0 + diff --git a/SOURCES/0001-session-worker-Set-session_vt-0-out-of-pam-uninitial.patch b/SOURCES/0001-session-worker-Set-session_vt-0-out-of-pam-uninitial.patch new file mode 100644 index 0000000..f69ae2b --- /dev/null +++ b/SOURCES/0001-session-worker-Set-session_vt-0-out-of-pam-uninitial.patch @@ -0,0 +1,84 @@ +From 26705ee64f4d3628eaaf45db980c435fa26e112a Mon Sep 17 00:00:00 2001 +From: Chingkai Chu <3013329+chuchingkai@users.noreply.github.com> +Date: Thu, 12 Aug 2021 10:34:01 +0800 +Subject: [PATCH] session-worker: Set session_vt=0 out of pam uninitialization + +MR GNOME/gdm!123 moved jump_to_vt and session_vt reseting to a +separate function, so we don't need to reset session_vt in pam +uninitialization. + +https://gitlab.gnome.org/GNOME/gdm/-/issues/719 +--- + daemon/gdm-session-worker.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index 7d7d2496..3ad94e2a 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -1076,62 +1076,60 @@ gdm_session_worker_set_state (GdmSessionWorker *worker, + + static void + gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker, + int status) + { + g_debug ("GdmSessionWorker: uninitializing PAM"); + + if (worker->priv->pam_handle == NULL) + return; + + gdm_session_worker_get_username (worker, NULL); + + if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) { + pam_close_session (worker->priv->pam_handle, 0); + gdm_session_auditor_report_logout (worker->priv->auditor); + } else { + gdm_session_auditor_report_login_failure (worker->priv->auditor, + status, + pam_strerror (worker->priv->pam_handle, status)); + } + + if (worker->priv->state >= GDM_SESSION_WORKER_STATE_ACCREDITED) { + pam_setcred (worker->priv->pam_handle, PAM_DELETE_CRED); + } + + pam_end (worker->priv->pam_handle, status); + worker->priv->pam_handle = NULL; + + gdm_session_worker_stop_auditor (worker); + +- worker->priv->session_vt = 0; +- + g_debug ("GdmSessionWorker: state NONE"); + gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_NONE); + } + + static char * + _get_tty_for_pam (const char *x11_display_name, + const char *display_device) + { + #ifdef __sun + return g_strdup (display_device); + #else + return g_strdup (x11_display_name); + #endif + } + + #ifdef PAM_XAUTHDATA + static struct pam_xauth_data * + _get_xauth_for_pam (const char *x11_authority_file) + { + FILE *fh; + Xauth *auth = NULL; + struct pam_xauth_data *retval = NULL; + gsize len = sizeof (*retval) + 1; + + fh = fopen (x11_authority_file, "r"); + if (fh) { + auth = XauReadAuth (fh); + fclose (fh); + } + if (auth) { +-- +2.32.0 + 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 new file mode 100644 index 0000000..154622b --- /dev/null +++ b/SOURCES/0001-xdmcp-display-factory-Set-supported-session-types-fo.patch @@ -0,0 +1,122 @@ +From 984690b76527baae0f7da0af00467669b49886ef 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 + XDMCP displays + +The lower levels of GDM now expect the session types supported by a +display to be specified up front. + +This commit makes sure XDMCP displays do that. +--- + daemon/gdm-xdmcp-display-factory.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c +index ce8f026e..abb58fae 100644 +--- a/daemon/gdm-xdmcp-display-factory.c ++++ b/daemon/gdm-xdmcp-display-factory.c +@@ -2104,94 +2104,100 @@ on_display_status_changed (GdmDisplay *display, + break; + case GDM_DISPLAY_MANAGED: + if (session != NULL) { + g_signal_connect_object (G_OBJECT (session), + "client-disconnected", + G_CALLBACK (on_client_disconnected), + display, G_CONNECT_SWAPPED); + g_signal_connect_object (G_OBJECT (session), + "disconnected", + G_CALLBACK (on_client_disconnected), + display, G_CONNECT_SWAPPED); + } + break; + default: + g_assert_not_reached (); + break; + } + + g_clear_object (&launch_environment); + } + + static GdmDisplay * + gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory, + const char *hostname, + GdmAddress *address, + int displaynum) + { + GdmDisplay *display; + GdmDisplayStore *store; + gboolean use_chooser; ++ const char *session_types[] = { "x11", NULL }; + + g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d", + hostname ? hostname : "(null)", displaynum); + + use_chooser = FALSE; + if (factory->honor_indirect) { + IndirectClient *ic; + + ic = indirect_client_lookup (factory, address); + + /* This was an indirect thingie and nothing was yet chosen, + * use a chooser */ + if (ic != NULL && ic->chosen_address == NULL) { + use_chooser = TRUE; + } + } + + if (use_chooser) { + display = gdm_xdmcp_chooser_display_new (hostname, + displaynum, + address, + get_next_session_serial (factory)); + g_signal_connect (display, "hostname-selected", G_CALLBACK (on_hostname_selected), factory); + } else { + display = gdm_xdmcp_display_new (hostname, + displaynum, + address, + get_next_session_serial (factory)); + } + + if (display == NULL) { + goto out; + } + ++ g_object_set (G_OBJECT (display), ++ "session-type", session_types[0], ++ "supported-session-types", session_types, ++ NULL); ++ + if (! gdm_display_prepare (display)) { + gdm_display_unmanage (display); + g_object_unref (display); + display = NULL; + goto out; + } + + g_signal_connect_after (display, + "notify::status", + G_CALLBACK (on_display_status_changed), + factory); + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + gdm_display_store_add (store, display); + + factory->num_pending_sessions++; + out: + + return display; + } + + static void + gdm_xdmcp_send_accept (GdmXdmcpDisplayFactory *factory, + GdmAddress *address, + CARD32 session_id, + ARRAY8Ptr authentication_name, + ARRAY8Ptr authentication_data, + ARRAY8Ptr authorization_name, + ARRAY8Ptr authorization_data) + { +-- +2.31.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 new file mode 100644 index 0000000..eddae95 --- /dev/null +++ b/SOURCES/0002-daemon-Don-t-update-session-type-if-no-saved-session.patch @@ -0,0 +1,109 @@ +From 1e877db3a4a8cb8e4eb4fbdaef3f6a7434e6a57d 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 + +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. + +If they don't, then don't set the session type. + +https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/153 +--- + daemon/gdm-session.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 2b941e5e..b54687d5 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -995,73 +995,76 @@ worker_on_reauthenticated (GdmDBusWorker *worker, + static void + worker_on_saved_language_name_read (GdmDBusWorker *worker, + const char *language_name, + GdmSessionConversation *conversation) + { + GdmSession *self = conversation->session; + + if (strlen (language_name) > 0) { + g_free (self->saved_language); + self->saved_language = g_strdup (language_name); + + if (self->greeter_interface != NULL) { + gdm_dbus_greeter_emit_default_language_name_changed (self->greeter_interface, + language_name); + } + } + } + + static void + worker_on_saved_session_name_read (GdmDBusWorker *worker, + const char *session_name, + GdmSessionConversation *conversation) + { + GdmSession *self = conversation->session; + + if (! get_session_command_for_name (self, session_name, self->saved_session_type, NULL)) { + /* ignore sessions that don't exist */ + g_debug ("GdmSession: not using invalid .dmrc session: %s", session_name); + g_free (self->saved_session); + self->saved_session = NULL; +- } else if (strcmp (session_name, +- get_default_session_name (self)) != 0) { +- g_free (self->saved_session); +- self->saved_session = g_strdup (session_name); +- +- if (self->greeter_interface != NULL) { +- gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface, +- session_name); ++ update_session_type (self); ++ } else { ++ if (strcmp (session_name, ++ get_default_session_name (self)) != 0) { ++ g_free (self->saved_session); ++ self->saved_session = g_strdup (session_name); ++ ++ if (self->greeter_interface != NULL) { ++ gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface, ++ session_name); ++ } + } ++ if (self->saved_session_type != NULL) ++ set_session_type (self, self->saved_session_type); + } + +- update_session_type (self); +- + } + + static void + worker_on_saved_session_type_read (GdmDBusWorker *worker, + const char *session_type, + GdmSessionConversation *conversation) + { + GdmSession *self = conversation->session; + + g_free (self->saved_session_type); + self->saved_session_type = g_strdup (session_type); + } + + static GdmSessionConversation * + find_conversation_by_pid (GdmSession *self, + GPid pid) + { + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, self->conversations); + while (g_hash_table_iter_next (&iter, &key, &value)) { + GdmSessionConversation *conversation; + + conversation = (GdmSessionConversation *) value; + + if (conversation->worker_pid == pid) { + return conversation; + } + } +-- +2.31.1 + diff --git a/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch b/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch new file mode 100644 index 0000000..c195db5 --- /dev/null +++ b/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch @@ -0,0 +1,151 @@ +From 618dfea6563d4f0bad0583b38b63746e44969d5e Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 5 Feb 2020 15:20:48 -0500 +Subject: [PATCH 2/3] gdm-x-session: run session bus on non-seat0 seats + +GNOME doesn't deal very well with multiple sessions +running on a multiple seats at the moment. + +Until that's fixed, ensure sessions run on auxillary +seats get their own session bus. +--- + daemon/gdm-session.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index a65fa0f9..f13b54af 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -2864,119 +2864,128 @@ on_start_program_cb (GdmDBusWorker *worker, + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = conversation->session; + service_name = conversation->service_name; + + if (worked) { + self->session_pid = pid; + self->session_conversation = conversation; + + g_debug ("GdmSession: Emitting 'session-started' signal with pid '%d'", pid); + g_signal_emit (self, signals[SESSION_STARTED], 0, service_name, pid); + } else { + gdm_session_stop_conversation (self, service_name); + + g_debug ("GdmSession: Emitting 'session-start-failed' signal"); + g_signal_emit (self, signals[SESSION_START_FAILED], 0, service_name, error->message); + } + } + + void + gdm_session_start_session (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + GdmSessionDisplayMode display_mode; + gboolean is_x11 = TRUE; + gboolean run_launcher = FALSE; + gboolean allow_remote_connections = FALSE; ++ gboolean run_separate_bus = FALSE; + char *command; + char *program; + gboolean register_session; + + g_return_if_fail (GDM_IS_SESSION (self)); + g_return_if_fail (self->session_conversation == NULL); + + conversation = find_conversation_by_name (self, service_name); + + if (conversation == NULL) { + g_warning ("GdmSession: Tried to start session of " + "nonexistent conversation %s", service_name); + return; + } + + stop_all_other_conversations (self, conversation, FALSE); + + display_mode = gdm_session_get_display_mode (self); + + #ifdef ENABLE_WAYLAND_SUPPORT + is_x11 = g_strcmp0 (self->session_type, "wayland") != 0; + #endif + + if (display_mode == GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED || + display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) { + run_launcher = TRUE; + } + + register_session = !gdm_session_session_registers (self); + ++ if (g_strcmp0 (self->display_seat_id, "seat0") != 0 && !run_launcher) { ++ run_separate_bus = TRUE; ++ } ++ + if (self->selected_program == NULL) { + gboolean run_xsession_script; + + command = get_session_command (self); + + run_xsession_script = !gdm_session_bypasses_xsession (self); + + if (self->display_is_local) { + gboolean disallow_tcp = TRUE; + gdm_settings_direct_get_boolean (GDM_KEY_DISALLOW_TCP, &disallow_tcp); + allow_remote_connections = !disallow_tcp; + } else { + allow_remote_connections = TRUE; + } + + if (run_launcher) { + if (is_x11) { + program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"", + register_session ? "--register-session " : "", + run_xsession_script? "--run-script " : "", + allow_remote_connections? "--allow-remote-connections " : "", + command); + } else { + program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"", + register_session ? "--register-session " : "", + command); + } + } else if (run_xsession_script) { +- program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command); ++ if (run_separate_bus) { ++ program = g_strdup_printf ("dbus-run-session -- " GDMCONFDIR "/Xsession \"%s\"", command); ++ } else { ++ program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command); ++ } + } else { + program = g_strdup (command); + } + + g_free (command); + } else { + /* FIXME: + * Always use a separate DBus bus for each greeter session. + * Firstly, this means that if we run multiple greeter session + * (which we really should not do, but have to currently), then + * each one will get its own DBus session bus. + * But, we also explicitly do this for seat0, because that way + * it cannot make use of systemd to run the GNOME session. This + * prevents the session lookup logic from getting confused. + * This has a similar effect as passing --builtin to gnome-session. + * + * We really should not be doing this. But the fix is to use + * separate dynamically created users and that requires some + * major refactorings. + */ + if (run_launcher) { + if (is_x11) { + program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"dbus-run-session -- %s\"", + register_session ? "--register-session " : "", + self->selected_program); + } else { + program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"dbus-run-session -- %s\"", + register_session ? "--register-session " : "", + self->selected_program); + } +-- +2.32.0 + 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 new file mode 100644 index 0000000..fa2bf13 --- /dev/null +++ b/SOURCES/0003-daemon-Infer-session-type-from-desktop-file-if-user-.patch @@ -0,0 +1,87 @@ +From 3eea287750d63cfe94fe777111e1cd04141eecb3 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 + no saved session type + +The accountsservice user cache file can specify a session type +associated with the saved session. This is optional though. If one +isn't specified GDM needs to figure out the session type based on the +list of preferred session types for the system and the session file +itself. + +It was failing to do the latter, though. This commit fixes that. +--- + daemon/gdm-session.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index b54687d5..a65fa0f9 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -1009,60 +1009,62 @@ worker_on_saved_language_name_read (GdmDBusWorker *worker, + } + } + } + + static void + worker_on_saved_session_name_read (GdmDBusWorker *worker, + const char *session_name, + GdmSessionConversation *conversation) + { + GdmSession *self = conversation->session; + + if (! get_session_command_for_name (self, session_name, self->saved_session_type, NULL)) { + /* ignore sessions that don't exist */ + g_debug ("GdmSession: not using invalid .dmrc session: %s", session_name); + g_free (self->saved_session); + self->saved_session = NULL; + update_session_type (self); + } else { + if (strcmp (session_name, + get_default_session_name (self)) != 0) { + g_free (self->saved_session); + self->saved_session = g_strdup (session_name); + + if (self->greeter_interface != NULL) { + gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface, + session_name); + } + } + if (self->saved_session_type != NULL) + set_session_type (self, self->saved_session_type); ++ else ++ update_session_type (self); + } + + } + + static void + worker_on_saved_session_type_read (GdmDBusWorker *worker, + const char *session_type, + GdmSessionConversation *conversation) + { + GdmSession *self = conversation->session; + + g_free (self->saved_session_type); + self->saved_session_type = g_strdup (session_type); + } + + static GdmSessionConversation * + find_conversation_by_pid (GdmSession *self, + GPid pid) + { + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, self->conversations); + while (g_hash_table_iter_next (&iter, &key, &value)) { + GdmSessionConversation *conversation; + + conversation = (GdmSessionConversation *) value; + + if (conversation->worker_pid == pid) { + return conversation; +-- +2.31.1 + diff --git a/SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch b/SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch new file mode 100644 index 0000000..15bc1ce --- /dev/null +++ b/SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch @@ -0,0 +1,105 @@ +From f30e557a8afcdfe5d571a625b4c99606315ed3b4 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 11 Feb 2019 10:32:55 -0500 +Subject: [PATCH 3/3] session: ensure login screen over XDMCP connects to its + session + +Right now GTK preferentially picks the wayland display over an +X11 display if it finds one. + +That causes a problem for XDMCP sessions, since there may be a +wayland display running on the local console for the GDM user. + +This commit addresses the issue by forcing the X11 backend if +the session is X11. +--- + daemon/gdm-session.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index f13b54af..9f68166e 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -2739,60 +2739,79 @@ set_up_session_environment (GdmSession *self) + } + + static void + send_display_mode (GdmSession *self, + GdmSessionConversation *conversation) + { + GdmSessionDisplayMode mode; + + mode = gdm_session_get_display_mode (self); + gdm_dbus_worker_call_set_session_display_mode (conversation->worker_proxy, + gdm_session_display_mode_to_string (mode), + conversation->worker_cancellable, + NULL, NULL); + } + + static void + send_session_type (GdmSession *self, + GdmSessionConversation *conversation) + { + const char *session_type = "x11"; + + if (self->session_type != NULL) { + session_type = self->session_type; + } + + gdm_dbus_worker_call_set_environment_variable (conversation->worker_proxy, + "XDG_SESSION_TYPE", + session_type, + conversation->worker_cancellable, + NULL, NULL); ++ ++ /* If the session type is x11, then set GDK_BACKEND to x11 as well. ++ * This is so gnome-session-check-accelerated from an XDMCP connection doesn't ++ * try to use the wayland display running on the local console for the gdm ++ * user login screen session. ++ * ++ * That's the only case where we let a user log in more than once, so it's ++ * the only situation that matters. ++ * ++ * We can drop this code if we ever switch the login screen to use systemd's ++ * DynamicUser feature. ++ */ ++ if (g_strcmp0 (session_type, "x11") == 0) { ++ gdm_dbus_worker_call_set_environment_variable (conversation->worker_proxy, ++ "GDK_BACKEND", ++ "x11", ++ conversation->worker_cancellable, ++ NULL, NULL); ++ } + } + + void + gdm_session_open_session (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + + g_return_if_fail (GDM_IS_SESSION (self)); + + conversation = find_conversation_by_name (self, service_name); + + if (conversation != NULL) { + send_display_mode (self, conversation); + send_session_type (self, conversation); + + gdm_dbus_worker_call_open (conversation->worker_proxy, + conversation->worker_cancellable, + (GAsyncReadyCallback) on_opened, conversation); + } + } + + static void + stop_all_other_conversations (GdmSession *self, + GdmSessionConversation *conversation_to_keep, + gboolean now) + { + GHashTableIter iter; + gpointer key, value; + +-- +2.32.0 + diff --git a/SOURCES/default.pa-for-gdm b/SOURCES/default.pa-for-gdm index d633aee..145bd31 100644 --- a/SOURCES/default.pa-for-gdm +++ b/SOURCES/default.pa-for-gdm @@ -3,7 +3,6 @@ load-module module-card-restore load-module module-udev-detect load-module module-native-protocol-unix load-module module-default-device-restore -load-module module-rescue-streams load-module module-always-sink load-module module-intended-roles load-module module-suspend-on-idle diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index 08b5fc7..8ab5bb5 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -11,7 +11,7 @@ Name: gdm Epoch: 1 Version: 40.1 -Release: 7%{?dist} +Release: 11%{?dist} Summary: The GNOME Display Manager License: GPLv2+ @@ -25,10 +25,31 @@ Source5: default.pa-for-gdm # Upstream backports Patch10001: 0001-local-display-factory-Provide-more-flexibility-for-c.patch -# Downstream patches -Patch70001: 0001-data-disable-wayland-on-certain-hardware.patch -Patch80001: 0001-Honor-initial-setup-being-disabled-by-distro-install.patch -Patch90001: 0001-data-add-system-dconf-databases-to-gdm-profile.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 + +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 + +# Non-upstreamable workarounds +Patch66610001: 0001-data-reap-gdm-sessions-on-shutdown.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 + BuildRequires: accountsservice-devel BuildRequires: audit-libs-devel >= %{libauditver} @@ -280,10 +301,11 @@ dconf update || : %{_datadir}/gdm/locale.alias %{_datadir}/gdm/gdb-cmd %{_datadir}/gnome-session/sessions/gnome-login.session +%{_datadir}/polkit-1/rules.d/org.gnome.gdm.rules %{_libdir}/girepository-1.0/Gdm-1.0.typelib %{_libdir}/security/pam_gdm.so %{_libdir}/libgdm*.so* -%dir %{_localstatedir}/log/gdm +%attr(0711, root, gdm) %dir %{_localstatedir}/log/gdm %attr(1770, gdm, gdm) %dir %{_localstatedir}/lib/gdm %attr(0700, gdm, gdm) %dir %{_localstatedir}/lib/gdm/.config %attr(0700, gdm, gdm) %dir %{_localstatedir}/lib/gdm/.config/pulse @@ -311,6 +333,23 @@ dconf update || : %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Wed Oct 27 2021 Ray Strode - 40.1-11 +- Pull in RHEL 8 patches and drop unused patches + Related: #2017859 + +* Mon Oct 25 2021 Ray Strode - 40.1-10 +- Remove module-rescue-stream from default.pa + Resolves: #2017439 + +* Mon Oct 25 2021 Ray Strode - 40.1-9 +- Synchronize permission and group ownership for log dir between + rpm file manifest and daemon expectations. + Resolves: #1999586 + +* Wed Oct 13 2021 Ray Strode - 40.1-8 +- Add latest session type propagation fixes from upstream + Related: #2009044 + * Mon Aug 23 2021 Ray Strode - 40.1-7 - Don't use gdm-disable-wayland binary in udev rules. It doesn't exist anymore.