diff --git a/SOURCES/0001-build-Support-keyutils-1.5.11-and-older.patch b/SOURCES/0001-build-Support-keyutils-1.5.11-and-older.patch new file mode 100644 index 0000000..9a6fcdd --- /dev/null +++ b/SOURCES/0001-build-Support-keyutils-1.5.11-and-older.patch @@ -0,0 +1,86 @@ +From 2fc7d94280a82e079129468d9b0db312725e5926 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 12 Dec 2022 15:37:38 -0500 +Subject: [PATCH 1/2] build: Support keyutils 1.5.11 and older + +keyutils didn't get a pkgconfig file until 1.6. + +This commit looks for the library directly if it can't find +the pkgconfig file. +--- + meson.build | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/meson.build b/meson.build +index 4a286f97..1a557e9a 100644 +--- a/meson.build ++++ b/meson.build +@@ -26,60 +26,65 @@ lang_config_file = (get_option('lang-file') != '')? get_option('lang-file') : gd + 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') + + 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) ++ ++if not keyutils_dep.found() ++ keyutils_dep = cc.find_library('libkeyutils') ++endif ++ + 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_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 +-- +2.35.1 + diff --git a/SOURCES/0001-daemon-Don-t-error-on-shutdown.patch b/SOURCES/0001-daemon-Don-t-error-on-shutdown.patch new file mode 100644 index 0000000..1949713 --- /dev/null +++ b/SOURCES/0001-daemon-Don-t-error-on-shutdown.patch @@ -0,0 +1,570 @@ +From fbdb5fdfc5f4c5569643239cae1d6fe5fac13717 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 12 Dec 2022 10:52:58 -0500 +Subject: [PATCH] daemon: Don't error on shutdown + +Right now we complain if shutdown happens while the display is +comming up. + +This commit detects that case and avoids the error in that case. +--- + daemon/gdm-display.c | 28 +++++++++++++++++++++++++++- + daemon/gdm-manager.c | 11 +++++++---- + 2 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c +index 9438fe72..a93857e9 100644 +--- a/daemon/gdm-display.c ++++ b/daemon/gdm-display.c +@@ -66,86 +66,88 @@ typedef struct _GdmDisplayPrivate + char *x11_display_name; + int status; + time_t creation_time; + + char *x11_cookie; + gsize x11_cookie_size; + GdmDisplayAccessFile *access_file; + + guint finish_idle_id; + + xcb_connection_t *xcb_connection; + int xcb_screen_number; + + GDBusConnection *connection; + GdmDisplayAccessFile *user_access_file; + + GdmDBusDisplay *display_skeleton; + GDBusObjectSkeleton *object_skeleton; + + GDBusProxy *accountsservice_proxy; + + /* this spawns and controls the greeter session */ + GdmLaunchEnvironment *launch_environment; + + guint is_local : 1; + guint is_initial : 1; + guint allow_timed_login : 1; + guint have_existing_user_accounts : 1; + guint doing_initial_setup : 1; + guint session_registered : 1; ++ guint shutting_down : 1; + + GStrv supported_session_types; + } GdmDisplayPrivate; + + enum { + PROP_0, + PROP_ID, + PROP_STATUS, + PROP_SEAT_ID, + PROP_SESSION_ID, + PROP_SESSION_CLASS, + PROP_SESSION_TYPE, + PROP_REMOTE_HOSTNAME, + PROP_X11_DISPLAY_NUMBER, + PROP_X11_DISPLAY_NAME, + PROP_X11_COOKIE, + PROP_X11_AUTHORITY_FILE, + PROP_IS_CONNECTED, + PROP_IS_LOCAL, + PROP_LAUNCH_ENVIRONMENT, + PROP_IS_INITIAL, + PROP_ALLOW_TIMED_LOGIN, + PROP_HAVE_EXISTING_USER_ACCOUNTS, + PROP_DOING_INITIAL_SETUP, + PROP_SESSION_REGISTERED, + PROP_SUPPORTED_SESSION_TYPES, ++ PROP_SHUTTING_DOWN, + }; + + static void gdm_display_class_init (GdmDisplayClass *klass); + static void gdm_display_init (GdmDisplay *self); + static void gdm_display_finalize (GObject *object); + static void queue_finish (GdmDisplay *self); + static void _gdm_display_set_status (GdmDisplay *self, + int status); + static gboolean wants_initial_setup (GdmDisplay *self); + G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdmDisplay, gdm_display, G_TYPE_OBJECT) + + GQuark + gdm_display_error_quark (void) + { + static GQuark ret = 0; + if (ret == 0) { + ret = g_quark_from_static_string ("gdm_display_error"); + } + + return ret; + } + + time_t + gdm_display_get_creation_time (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), 0); + + priv = gdm_display_get_instance_private (self); +@@ -665,61 +667,61 @@ gdm_display_disconnect (GdmDisplay *self) + } + + xcb_flush (priv->xcb_connection); + + g_clear_pointer (&priv->xcb_connection, xcb_disconnect); + } + + gboolean + gdm_display_unmanage (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + priv = gdm_display_get_instance_private (self); + + gdm_display_disconnect (self); + + if (priv->user_access_file != NULL) { + gdm_display_access_file_close (priv->user_access_file); + g_object_unref (priv->user_access_file); + priv->user_access_file = NULL; + } + + if (priv->access_file != NULL) { + gdm_display_access_file_close (priv->access_file); + g_object_unref (priv->access_file); + priv->access_file = NULL; + } + +- if (!priv->session_registered) { ++ if (!priv->session_registered && !priv->shutting_down) { + g_warning ("GdmDisplay: Session never registered, failing"); + _gdm_display_set_status (self, GDM_DISPLAY_FAILED); + } else { + _gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED); + } + + return TRUE; + } + + gboolean + gdm_display_get_id (GdmDisplay *self, + char **id, + GError **error) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + priv = gdm_display_get_instance_private (self); + if (id != NULL) { + *id = g_strdup (priv->id); + } + + return TRUE; + } + + gboolean + gdm_display_get_x11_display_name (GdmDisplay *self, + char **x11_display, + GError **error) +@@ -851,60 +853,70 @@ _gdm_display_set_x11_cookie (GdmDisplay *self, + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + g_free (priv->x11_cookie); + priv->x11_cookie = g_strdup (x11_cookie); + } + + static void + _gdm_display_set_is_local (GdmDisplay *self, + gboolean is_local) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + g_debug ("GdmDisplay: local: %s", is_local? "yes" : "no"); + priv->is_local = is_local; + } + + static void + _gdm_display_set_session_registered (GdmDisplay *self, + gboolean registered) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + g_debug ("GdmDisplay: session registered: %s", registered? "yes" : "no"); + priv->session_registered = registered; + } + ++static void ++_gdm_display_set_shutting_down (GdmDisplay *self, ++ gboolean shutting_down) ++{ ++ GdmDisplayPrivate *priv; ++ ++ priv = gdm_display_get_instance_private (self); ++ priv->shutting_down = shutting_down; ++} ++ + static void + _gdm_display_set_launch_environment (GdmDisplay *self, + GdmLaunchEnvironment *launch_environment) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + + g_clear_object (&priv->launch_environment); + + priv->launch_environment = g_object_ref (launch_environment); + } + + static void + _gdm_display_set_is_initial (GdmDisplay *self, + gboolean initial) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + g_debug ("GdmDisplay: initial: %s", initial? "yes" : "no"); + priv->is_initial = initial; + } + + static void + _gdm_display_set_allow_timed_login (GdmDisplay *self, + gboolean allow_timed_login) + { + GdmDisplayPrivate *priv; + +@@ -962,60 +974,63 @@ gdm_display_set_property (GObject *object, + case PROP_REMOTE_HOSTNAME: + _gdm_display_set_remote_hostname (self, g_value_get_string (value)); + break; + case PROP_X11_DISPLAY_NUMBER: + _gdm_display_set_x11_display_number (self, g_value_get_int (value)); + break; + case PROP_X11_DISPLAY_NAME: + _gdm_display_set_x11_display_name (self, g_value_get_string (value)); + break; + case PROP_X11_COOKIE: + _gdm_display_set_x11_cookie (self, g_value_get_string (value)); + break; + case PROP_IS_LOCAL: + _gdm_display_set_is_local (self, g_value_get_boolean (value)); + break; + case PROP_ALLOW_TIMED_LOGIN: + _gdm_display_set_allow_timed_login (self, g_value_get_boolean (value)); + break; + case PROP_LAUNCH_ENVIRONMENT: + _gdm_display_set_launch_environment (self, g_value_get_object (value)); + break; + case PROP_IS_INITIAL: + _gdm_display_set_is_initial (self, g_value_get_boolean (value)); + break; + case PROP_SESSION_REGISTERED: + _gdm_display_set_session_registered (self, g_value_get_boolean (value)); + break; + case PROP_SUPPORTED_SESSION_TYPES: + _gdm_display_set_supported_session_types (self, g_value_get_boxed (value)); + break; ++ case PROP_SHUTTING_DOWN: ++ _gdm_display_set_shutting_down (self, g_value_get_boolean (value)); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static void + gdm_display_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + GdmDisplay *self; + GdmDisplayPrivate *priv; + + self = GDM_DISPLAY (object); + priv = gdm_display_get_instance_private (self); + + switch (prop_id) { + case PROP_ID: + g_value_set_string (value, priv->id); + break; + case PROP_STATUS: + g_value_set_int (value, priv->status); + break; + case PROP_SEAT_ID: + g_value_set_string (value, priv->seat_id); + break; + case PROP_SESSION_ID: + g_value_set_string (value, priv->session_id); +@@ -1043,60 +1058,63 @@ gdm_display_get_property (GObject *object, + priv->access_file? + gdm_display_access_file_get_path (priv->access_file) : NULL); + break; + case PROP_IS_LOCAL: + g_value_set_boolean (value, priv->is_local); + break; + case PROP_IS_CONNECTED: + g_value_set_boolean (value, priv->xcb_connection != NULL); + break; + case PROP_LAUNCH_ENVIRONMENT: + g_value_set_object (value, priv->launch_environment); + break; + case PROP_IS_INITIAL: + g_value_set_boolean (value, priv->is_initial); + break; + case PROP_HAVE_EXISTING_USER_ACCOUNTS: + g_value_set_boolean (value, priv->have_existing_user_accounts); + break; + case PROP_DOING_INITIAL_SETUP: + g_value_set_boolean (value, priv->doing_initial_setup); + break; + case PROP_SESSION_REGISTERED: + g_value_set_boolean (value, priv->session_registered); + break; + case PROP_ALLOW_TIMED_LOGIN: + g_value_set_boolean (value, priv->allow_timed_login); + break; + case PROP_SUPPORTED_SESSION_TYPES: + g_value_set_boxed (value, priv->supported_session_types); + break; ++ case PROP_SHUTTING_DOWN: ++ g_value_set_boolean (value, priv->shutting_down); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static gboolean + handle_get_id (GdmDBusDisplay *skeleton, + GDBusMethodInvocation *invocation, + GdmDisplay *self) + { + char *id; + + gdm_display_get_id (self, &id, NULL); + + gdm_dbus_display_complete_get_id (skeleton, invocation, id); + + g_free (id); + return TRUE; + } + + static gboolean + handle_get_remote_hostname (GdmDBusDisplay *skeleton, + GDBusMethodInvocation *invocation, + GdmDisplay *self) + { + char *hostname; + + gdm_display_get_remote_hostname (self, &hostname, NULL); + +@@ -1397,60 +1415,68 @@ gdm_display_class_init (GdmDisplayClass *klass) + g_param_spec_boolean ("session-registered", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_LAUNCH_ENVIRONMENT, + g_param_spec_object ("launch-environment", + NULL, + NULL, + GDM_TYPE_LAUNCH_ENVIRONMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_STATUS, + g_param_spec_int ("status", + "status", + "status", + -1, + G_MAXINT, + GDM_DISPLAY_UNMANAGED, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_SUPPORTED_SESSION_TYPES, + g_param_spec_boxed ("supported-session-types", + "supported session types", + "supported session types", + G_TYPE_STRV, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (object_class, ++ PROP_SHUTTING_DOWN, ++ g_param_spec_boolean ("shutting-down", ++ NULL, ++ NULL, ++ FALSE, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } + + static void + gdm_display_init (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + + priv->creation_time = time (NULL); + } + + static void + gdm_display_finalize (GObject *object) + { + GdmDisplay *self; + GdmDisplayPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_DISPLAY (object)); + + self = GDM_DISPLAY (object); + priv = gdm_display_get_instance_private (self); + + g_return_if_fail (priv != NULL); + + g_debug ("GdmDisplay: Finalizing display: %s", priv->id); + g_free (priv->id); + g_free (priv->seat_id); + g_free (priv->session_class); +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index c70248f3..05851001 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -2759,117 +2759,120 @@ gdm_manager_init (GdmManager *manager) + NULL, + (GDestroyNotify) + g_object_unref); + manager->priv->transient_sessions = g_hash_table_new_full (NULL, + NULL, + (GDestroyNotify) + NULL, + (GDestroyNotify) + g_object_unref); + g_signal_connect (G_OBJECT (manager->priv->display_store), + "display-added", + G_CALLBACK (on_display_added), + manager); + + g_signal_connect (G_OBJECT (manager->priv->display_store), + "display-removed", + G_CALLBACK (on_display_removed), + manager); + } + + static void + 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) ++shut_down_display (const char *id, ++ GdmDisplay *display, ++ GdmManager *manager) + { + gdm_display_stop_greeter_session (display); ++ ++ g_object_set (G_OBJECT (display), "shutting-down", TRUE, NULL); ++ + 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)); + } + + gdm_display_store_foreach (manager->priv->display_store, +- (GdmDisplayStoreFunc) finish_display, ++ (GdmDisplayStoreFunc) shut_down_display, + manager); + + gdm_display_store_clear (manager->priv->display_store); + + g_dbus_object_manager_server_set_connection (manager->priv->object_manager, NULL); + + g_clear_object (&manager->priv->connection); + g_clear_object (&manager->priv->object_manager); + g_clear_object (&manager->priv->display_store); + + G_OBJECT_CLASS (gdm_manager_parent_class)->dispose (object); + } + + GdmManager * + gdm_manager_new (void) + { + if (manager_object != NULL) { + g_object_ref (manager_object); + } else { + gboolean res; + + manager_object = g_object_new (GDM_TYPE_MANAGER, NULL); + g_object_add_weak_pointer (manager_object, + (gpointer *) &manager_object); + res = register_manager (manager_object); + if (! res) { + g_object_unref (manager_object); + return NULL; + } + } +-- +2.37.0.rc1 + diff --git a/SOURCES/0001-meson-set-D_GNU_SOURCE-for-updwtmpx.patch b/SOURCES/0001-meson-set-D_GNU_SOURCE-for-updwtmpx.patch new file mode 100644 index 0000000..4c5be7a --- /dev/null +++ b/SOURCES/0001-meson-set-D_GNU_SOURCE-for-updwtmpx.patch @@ -0,0 +1,81 @@ +From 5a2d5dbdf8c6f6d3c896082a5a07b4292f5fb410 Mon Sep 17 00:00:00 2001 +From: Sam James +Date: Tue, 5 Jul 2022 01:47:35 +0100 +Subject: [PATCH 1/2] meson: set -D_GNU_SOURCE for updwtmpx +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Without setting GNU_SOURCE, we end up getting: +``` +../gdm-42.0/daemon/gdm-session-record.c:200:9: error: implicit declaration of function ‘updwtmpx’; did you mean ‘updwtmp’? [-Werror=implicit-function-declaration] +updwtmpx (GDM_NEW_SESSION_RECORDS_FILE, &session_record); +``` + +This ended up exposing a bug in updwtmp(3) (which is now fixed +thanks to the man-pages maintainers!) as it didn't mention that updwtmpx +is a GNU extension (and hence needs GNU_SOURCE in order to be available). + +Alternatively, we could just #define _GNU_SOURCE in gdm-session-record.c +for updwtmpx. + +Bug: https://bugzilla.kernel.org/show_bug.cgi?id=216168 +--- + meson.build | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/meson.build b/meson.build +index 8328dd97..4a286f97 100644 +--- a/meson.build ++++ b/meson.build +@@ -1,44 +1,47 @@ + project('gdm', 'c', + version: '40.0', + license: 'GPL2+', + meson_version: '>= 0.50', + ) + + # Modules + gnome = import('gnome') + pkgconfig = import('pkgconfig') + i18n = import('i18n') + + # Compiler + cc = meson.get_compiler('c') + ++# Use GNU extensions if available ++add_project_arguments('-D_GNU_SOURCE', language: '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') + + glib_min_version = '2.56.0' + + glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version) +-- +2.31.1 + diff --git a/SOURCES/0002-manager-Fix-btmp-record-accounting.patch b/SOURCES/0002-manager-Fix-btmp-record-accounting.patch new file mode 100644 index 0000000..2c69b53 --- /dev/null +++ b/SOURCES/0002-manager-Fix-btmp-record-accounting.patch @@ -0,0 +1,227 @@ +From 20725e4c65555178ed64a3cb77ee979ec98998f8 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 19 Oct 2022 14:50:33 -0400 +Subject: [PATCH 2/2] manager: Fix btmp record accounting + +Before a user logs in they don't have a display. + +btmp records currently need a display though, and they +get written when the user can't log in. + +Furthermore, the display from X11 point of view is +somewhat archaic. We use wayland by default now. + +In lieu of a display, this commit gives the btmp record +the seat id instead. +--- + daemon/gdm-manager.c | 11 +++++++++-- + daemon/gdm-session-record.c | 8 ++++++-- + 2 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 4b62b8b1..c70248f3 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -641,113 +641,120 @@ switch_to_compatible_user_session (GdmManager *manager, + + 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; ++ char *display_name, *hostname, *display_device, *display_seat_id; + gboolean recorded = FALSE; + + display_name = NULL; + username = NULL; + hostname = NULL; + display_device = NULL; ++ display_seat_id = NULL; + + username = gdm_session_get_username (session); + + if (username == NULL) { + goto out; + } + + g_object_get (G_OBJECT (session), + "display-name", &display_name, + "display-hostname", &hostname, + "display-device", &display_device, ++ "display-seat-id", &display_seat_id, + NULL); + + if (display_name == NULL && display_device == NULL) { +- goto out; ++ if (display_seat_id == NULL) ++ goto out; ++ ++ display_name = g_strdup ("login screen"); ++ display_device = g_strdup (display_seat_id); + } + + switch (record) { + case SESSION_RECORD_LOGIN: + gdm_session_record_login (pid, + username, + hostname, + display_name, + display_device); + break; + case SESSION_RECORD_LOGOUT: + gdm_session_record_logout (pid, + username, + hostname, + display_name, + display_device); + break; + case SESSION_RECORD_FAILED: + gdm_session_record_failed (pid, + username, + hostname, + display_name, + display_device); + break; + } + + recorded = TRUE; + out: + g_free (display_name); + g_free (hostname); + g_free (display_device); ++ g_free (display_seat_id); + + return recorded; + } + + static GdmSession * + find_user_session_for_display (GdmManager *self, + GdmDisplay *display) + { + + GList *node = self->priv->user_sessions; + + while (node != NULL) { + GdmSession *session = node->data; + GdmDisplay *candidate_display; + GList *next_node = node->next; + + candidate_display = get_display_for_user_session (session); + + if (candidate_display == display) + return session; + + node = next_node; + } + + return NULL; + } + + static gboolean + gdm_manager_handle_register_display (GdmDBusManager *manager, + GDBusMethodInvocation *invocation, +diff --git a/daemon/gdm-session-record.c b/daemon/gdm-session-record.c +index 7719d0a8..310323b6 100644 +--- a/daemon/gdm-session-record.c ++++ b/daemon/gdm-session-record.c +@@ -125,66 +125,70 @@ record_set_host (UTMP *u, + */ + if (host_name != NULL + && x11_display_name != NULL + && g_str_has_prefix (x11_display_name, ":")) { + hostname = g_strdup_printf ("%s%s", host_name, x11_display_name); + } else { + hostname = g_strdup (x11_display_name); + } + + if (hostname != NULL) { + memccpy (u->ut_host, hostname, '\0', sizeof (u->ut_host)); + g_debug ("using ut_host %.*s", (int) sizeof (u->ut_host), u->ut_host); + #ifdef HAVE_UT_UT_SYSLEN + u->ut_syslen = MIN (strlen (hostname), sizeof (u->ut_host)); + #endif + g_free (hostname); + } + #endif + } + + static void + record_set_line (UTMP *u, + const char *display_device, + const char *x11_display_name) + { + /* + * Set ut_line to the device name associated with this display + * but remove the "/dev/" prefix. If no device, then use the + * $DISPLAY value. + */ +- if (display_device != NULL +- && g_str_has_prefix (display_device, "/dev/")) { ++ if (display_device != NULL && g_str_has_prefix (display_device, "/dev/")) { + memccpy (u->ut_line, + display_device + strlen ("/dev/"), + '\0', + sizeof (u->ut_line)); ++ } else if (display_device != NULL && g_str_has_prefix (display_device, "seat")) { ++ memccpy (u->ut_line, ++ display_device, ++ '\0', ++ sizeof (u->ut_line)); + } else if (x11_display_name != NULL) { + memccpy (u->ut_line, + x11_display_name, + '\0', + sizeof (u->ut_line)); + } + + g_debug ("using ut_line %.*s", (int) sizeof (u->ut_line), u->ut_line); + } + + void + gdm_session_record_login (GPid session_pid, + const char *user_name, + const char *host_name, + const char *x11_display_name, + const char *display_device) + { + UTMP session_record = { 0 }; + + if (x11_display_name == NULL) + x11_display_name = display_device; + + record_set_username (&session_record, user_name); + + g_debug ("Writing login record"); + + #if defined(HAVE_UT_UT_TYPE) + session_record.ut_type = USER_PROCESS; + g_debug ("using ut_type USER_PROCESS"); + #endif +-- +2.31.1 + diff --git a/SOURCES/0002-pam_gdm-Use-the-last-cryptsetup-password-instead-of-.patch b/SOURCES/0002-pam_gdm-Use-the-last-cryptsetup-password-instead-of-.patch new file mode 100644 index 0000000..7da1b75 --- /dev/null +++ b/SOURCES/0002-pam_gdm-Use-the-last-cryptsetup-password-instead-of-.patch @@ -0,0 +1,119 @@ +From 9f4b4ef1b5e1458ca67cff235b655060b27e357b Mon Sep 17 00:00:00 2001 +From: Graham Rogers +Date: Sun, 18 Apr 2021 12:22:14 +0100 +Subject: [PATCH 2/2] pam_gdm: Use the last cryptsetup password instead of the + first + +--- + pam_gdm/pam_gdm.c | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/pam_gdm/pam_gdm.c b/pam_gdm/pam_gdm.c +index 767a6c8c..ef77f161 100644 +--- a/pam_gdm/pam_gdm.c ++++ b/pam_gdm/pam_gdm.c +@@ -11,75 +11,95 @@ + * 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 + + #include + + #include + #include + #include + #include + #include + + #ifdef HAVE_KEYUTILS + #include + #endif + + int + pam_sm_authenticate (pam_handle_t *pamh, + int flags, + int argc, + const char **argv) + { + #ifdef HAVE_KEYUTILS +- int r; +- void *cached_password = NULL; ++ long r; ++ size_t cached_passwords_length; ++ char *cached_passwords = NULL; ++ char *last_cached_password = NULL; + key_serial_t serial; ++ size_t i; + + serial = find_key_by_type_and_desc ("user", "cryptsetup", 0); + if (serial == 0) + return PAM_AUTHINFO_UNAVAIL; + +- r = keyctl_read_alloc (serial, &cached_password); +- if (r < 0 || r != strlen (cached_password)) ++ r = keyctl_read_alloc (serial, &cached_passwords); ++ if (r < 0) + return PAM_AUTHINFO_UNAVAIL; ++ ++ cached_passwords_length = r; ++ ++ /* ++ Find the last password in the NUL-separated list of passwords. ++ Multiple passwords are returned either when the user enters an ++ incorrect password or there are multiple encrypted drives. ++ In the case of an incorrect password the last one is correct. ++ In the case of multiple drives, choosing the last drive is as ++ arbitrary a choice as any other, but choosing the last password at ++ least supports multiple attempts on the last drive. ++ */ ++ last_cached_password = cached_passwords; ++ for (i = 0; i < cached_passwords_length; i++) { ++ last_cached_password = cached_passwords + i; ++ i += strlen (last_cached_password); ++ } + +- r = pam_set_item (pamh, PAM_AUTHTOK, cached_password); ++ r = pam_set_item (pamh, PAM_AUTHTOK, last_cached_password); + +- free (cached_password); ++ free (cached_passwords); + + if (r < 0) + return PAM_AUTH_ERR; + else + return PAM_SUCCESS; + #endif + + return PAM_AUTHINFO_UNAVAIL; + } + + int + pam_sm_setcred (pam_handle_t *pamh, + int flags, + int argc, + const char **argv) + { + return PAM_SUCCESS; + } + + int + pam_sm_acct_mgmt (pam_handle_t *pamh, + int flags, + int argc, + const char **argv) + { + return PAM_SUCCESS; + } + + int + pam_sm_chauthtok (pam_handle_t *pamh, +-- +2.35.1 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index a984959..6113bef 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -12,7 +12,7 @@ Name: gdm Epoch: 1 Version: 40.0 -Release: 24%{?dist} +Release: 27%{?dist} Summary: The GNOME Display Manager License: GPLv2+ @@ -53,6 +53,17 @@ Patch100001: 0001-daemon-Infer-session-type-from-desktop-file-if-user-.patch Patch110001: 0001-meson-Fix-detection-of-Xorg-versions-that-need-liste.patch Patch110002: 0002-daemon-Support-X-servers-built-with-Dlisten_tcp-true.patch +# Fix btmp accounting +Patch120001: 0001-meson-set-D_GNU_SOURCE-for-updwtmpx.patch +Patch120002: 0002-manager-Fix-btmp-record-accounting.patch + +# Fix status error when stoppping gdm quickly after starting it +Patch130001: 0001-daemon-Don-t-error-on-shutdown.patch + +# Fix LUKS password propagation +Patch140001: 0001-build-Support-keyutils-1.5.11-and-older.patch +Patch140002: 0002-pam_gdm-Use-the-last-cryptsetup-password-instead-of-.patch + # Non-upstreamable workarounds Patch66620001: 0001-data-reap-gdm-sessions-on-shutdown.patch @@ -375,6 +386,18 @@ fi %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Mon Dec 12 2022 Ray Strode - 40.0-27 +- Fix LUKs password handling + Resolves: #2150649 + +* Mon Dec 12 2022 Ray Strode - 40.0-26 +- Fix error in service status log + Resolves: #1924079 + +* Wed Oct 19 2022 Ray Strode - 40.0-25 +- Fix btmp accounting + Resolves: #2030043 + * Mon May 16 2022 Ray Strode - 40.0-24 - Fix typo that prevents the correct session type from being used when user switching.