diff --git a/SOURCES/0001-session-worker-expose-worker-state-enum-to-type-syst.patch b/SOURCES/0001-session-worker-expose-worker-state-enum-to-type-syst.patch new file mode 100644 index 0000000..3de78e9 --- /dev/null +++ b/SOURCES/0001-session-worker-expose-worker-state-enum-to-type-syst.patch @@ -0,0 +1,470 @@ +From 521ff70fe447558461dd38cdec62a7c0a5a74f7a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 24 Jun 2019 14:48:23 -0400 +Subject: [PATCH 1/3] session-worker: expose worker state enum to type system + +We're going to need to access the worker state as a property on +the worker object. + +This commit hooks it up to glib-mkenums so the requisite goo can +get generated +--- + daemon/Makefile.am | 8 +++++ + daemon/gdm-session-worker-enum-types.c.in | 42 +++++++++++++++++++++++ + daemon/gdm-session-worker-enum-types.h.in | 24 +++++++++++++ + daemon/gdm-session-worker.c | 16 +++------ + daemon/gdm-session-worker.h | 12 +++++++ + 5 files changed, 90 insertions(+), 12 deletions(-) + create mode 100644 daemon/gdm-session-worker-enum-types.c.in + create mode 100644 daemon/gdm-session-worker-enum-types.h.in + +diff --git a/daemon/Makefile.am b/daemon/Makefile.am +index b77c9276e..86a8ee32f 100644 +--- a/daemon/Makefile.am ++++ b/daemon/Makefile.am +@@ -14,69 +14,76 @@ AM_CPPFLAGS = \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DLOCALSTATEDIR=\"$(localstatedir)\" \ + -DLOGDIR=\"$(logdir)\" \ + -DSBINDIR=\"$(sbindir)\" \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + -DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \ + -DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \ + -DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \ + -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \ + -DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \ + $(DISABLE_DEPRECATED_CFLAGS) \ + $(DAEMON_CFLAGS) \ + $(XLIB_CFLAGS) \ + $(WARN_CFLAGS) \ + $(DEBUG_CFLAGS) \ + $(SYSTEMD_CFLAGS) \ + $(JOURNALD_CFLAGS) \ + $(LIBSELINUX_CFLAGS) \ + -DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\" \ + $(NULL) + + BUILT_SOURCES = \ + gdm-display-glue.h \ + gdm-manager-glue.h \ + gdm-local-display-glue.h \ + gdm-local-display-factory-glue.h \ + gdm-session-glue.h \ + gdm-session-worker-glue.h \ + gdm-session-enum-types.h \ ++ gdm-session-worker-enum-types.h \ + com.redhat.AccountsServiceUser.System.h \ + $(NULL) + + gdm-session-enum-types.h: gdm-session-enum-types.h.in gdm-session.h + $(AM_V_GEN) glib-mkenums --template $^ > $@ + + gdm-session-enum-types.c: gdm-session-enum-types.c.in gdm-session.h + $(AM_V_GEN) glib-mkenums --template $^ > $@ + ++gdm-session-worker-enum-types.h: gdm-session-worker-enum-types.h.in gdm-session-worker.h ++ $(AM_V_GEN) glib-mkenums --template $^ > $@ ++ ++gdm-session-worker-enum-types.c: gdm-session-worker-enum-types.c.in gdm-session-worker.h ++ $(AM_V_GEN) glib-mkenums --template $^ > $@ ++ + gdm-display-glue.c gdm-display-glue.h: gdm-display.xml Makefile.am + $(AM_V_GEN)gdbus-codegen \ + --c-namespace=GdmDBus \ + --interface-prefix=org.gnome.DisplayManager \ + --generate-c-code=gdm-display-glue \ + $(srcdir)/gdm-display.xml + + gdm-local-display-glue.c gdm-local-display-glue.h: gdm-local-display.xml Makefile.am + $(AM_V_GEN)gdbus-codegen \ + --c-namespace=GdmDBus \ + --interface-prefix=org.gnome.DisplayManager \ + --generate-c-code=gdm-local-display-glue \ + $(srcdir)/gdm-local-display.xml + + gdm-local-display-factory-glue.c gdm-local-display-factory-glue.h : gdm-local-display-factory.xml Makefile.am + $(AM_V_GEN)gdbus-codegen \ + --c-namespace=GdmDBus \ + --interface-prefix=org.gnome.DisplayManager \ + --generate-c-code=gdm-local-display-factory-glue \ + $(srcdir)/gdm-local-display-factory.xml + + gdm-manager-glue.c gdm-manager-glue.h : gdm-manager.xml Makefile.am + $(AM_V_GEN)gdbus-codegen \ + --c-namespace=GdmDBus \ + --interface-prefix=org.gnome.DisplayManager \ + --generate-c-code=gdm-manager-glue \ + $(srcdir)/gdm-manager.xml + + gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am + $(AM_V_GEN)gdbus-codegen \ +@@ -128,60 +135,61 @@ gdm_session_worker_SOURCES = \ + session-worker-main.c \ + com.redhat.AccountsServiceUser.System.h \ + com.redhat.AccountsServiceUser.System.c \ + gdm-session.c \ + gdm-session.h \ + gdm-session-settings.h \ + gdm-session-settings.c \ + gdm-session-auditor.h \ + gdm-session-auditor.c \ + gdm-session-record.c \ + gdm-session-record.h \ + gdm-session-worker.h \ + gdm-session-worker.c \ + gdm-session-worker-job.c \ + gdm-session-worker-common.c \ + gdm-session-worker-common.h \ + gdm-dbus-util.c \ + gdm-dbus-util.h \ + $(NULL) + + if SUPPORTS_PAM_EXTENSIONS + gdm_session_worker_SOURCES += $(top_srcdir)/pam-extensions/gdm-pam-extensions.h + endif + + nodist_gdm_session_worker_SOURCES = \ + gdm-session-glue.h \ + gdm-session-glue.c \ + gdm-session-worker-glue.c \ + gdm-session-worker-glue.h \ + gdm-session-enum-types.c \ ++ gdm-session-worker-enum-types.c \ + gdm-session-enum-types.h \ + $(NULL) + + gdm_wayland_session_LDADD = \ + $(top_builddir)/common/libgdmcommon.la \ + $(GTK_LIBS) \ + $(COMMON_LIBS) \ + $(SYSTEMD_LIBS) \ + $(NULL) + + gdm_wayland_session_SOURCES = \ + gdm-manager-glue.h \ + gdm-manager-glue.c \ + gdm-wayland-session.c \ + $(NULL) + + gdm_x_session_LDADD = \ + $(top_builddir)/common/libgdmcommon.la \ + $(GTK_LIBS) \ + $(COMMON_LIBS) \ + $(SYSTEMD_LIBS) \ + $(XLIB_LIBS) \ + $(NULL) + + gdm_x_session_SOURCES = \ + gdm-manager-glue.h \ + gdm-manager-glue.c \ + gdm-x-session.c \ + $(NULL) + +diff --git a/daemon/gdm-session-worker-enum-types.c.in b/daemon/gdm-session-worker-enum-types.c.in +new file mode 100644 +index 000000000..c02869076 +--- /dev/null ++++ b/daemon/gdm-session-worker-enum-types.c.in +@@ -0,0 +1,42 @@ ++/*** BEGIN file-header ***/ ++ ++#include ++ ++/*** END file-header ***/ ++ ++/*** BEGIN file-production ***/ ++#include "@filename@" ++/* enumerations from "@filename@" */ ++/*** END file-production ***/ ++ ++/*** BEGIN value-header ***/ ++GType @enum_name@_get_type (void) G_GNUC_CONST; ++ ++GType ++@enum_name@_get_type (void) ++{ ++ static GType etype = 0; ++ ++ if (G_UNLIKELY(etype == 0)) { ++ static const G@Type@Value values[] = { ++/*** END value-header ***/ ++ ++/*** BEGIN value-production ***/ ++ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, ++/*** END value-production ***/ ++ ++/*** BEGIN value-tail ***/ ++ { 0, NULL, NULL } ++ }; ++ ++ etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); ++ } ++ ++ return etype; ++} ++ ++/*** END value-tail ***/ ++ ++/*** BEGIN file-tail ***/ ++ /**/ ++/*** END file-tail ***/ +diff --git a/daemon/gdm-session-worker-enum-types.h.in b/daemon/gdm-session-worker-enum-types.h.in +new file mode 100644 +index 000000000..64f4b4bb6 +--- /dev/null ++++ b/daemon/gdm-session-worker-enum-types.h.in +@@ -0,0 +1,24 @@ ++/*** BEGIN file-header ***/ ++#ifndef GDM_SESSION_WORKER_ENUM_TYPES_H ++#define GDM_SESSION_WORKER_ENUM_TYPES_H ++ ++#include ++ ++G_BEGIN_DECLS ++/*** END file-header ***/ ++ ++/*** BEGIN file-production ***/ ++ ++/* enumerations from "@filename@" */ ++/*** END file-production ***/ ++ ++/*** BEGIN value-header ***/ ++GType @enum_name@_get_type (void) G_GNUC_CONST; ++#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ()) ++/*** END value-header ***/ ++ ++/*** BEGIN file-tail ***/ ++G_END_DECLS ++ ++#endif /* GDM_SESSION_WORKER_ENUM_TYPES_H */ ++/*** END file-tail ***/ +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index ae86d28ac..f6935ab1d 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -83,83 +83,72 @@ + #define GDM_SESSION_WORKER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerPrivate)) + + #define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session" + #define GDM_SESSION_DBUS_NAME "org.gnome.DisplayManager.Session" + #define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel" + + #define GDM_WORKER_DBUS_PATH "/org/gnome/DisplayManager/Worker" + + #ifndef GDM_PASSWD_AUXILLARY_BUFFER_SIZE + #define GDM_PASSWD_AUXILLARY_BUFFER_SIZE 1024 + #endif + + #ifndef GDM_SESSION_DEFAULT_PATH + #define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin" + #endif + + #ifndef GDM_SESSION_ROOT_UID + #define GDM_SESSION_ROOT_UID 0 + #endif + + #ifndef GDM_SESSION_LOG_FILENAME + #define GDM_SESSION_LOG_FILENAME "session.log" + #endif + + #define MAX_FILE_SIZE 65536 + #define MAX_LOGS 5 + + #define RELEASE_DISPLAY_SIGNAL (SIGRTMAX) + #define ACQUIRE_DISPLAY_SIGNAL (SIGRTMAX - 1) + +-enum { +- GDM_SESSION_WORKER_STATE_NONE = 0, +- GDM_SESSION_WORKER_STATE_SETUP_COMPLETE, +- GDM_SESSION_WORKER_STATE_AUTHENTICATED, +- GDM_SESSION_WORKER_STATE_AUTHORIZED, +- GDM_SESSION_WORKER_STATE_ACCREDITED, +- GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED, +- GDM_SESSION_WORKER_STATE_SESSION_OPENED, +- GDM_SESSION_WORKER_STATE_SESSION_STARTED +-}; +- + typedef struct + { + GdmSessionWorker *worker; + GdmSession *session; + GPid pid_of_caller; + uid_t uid_of_caller; + + } ReauthenticationRequest; + + struct GdmSessionWorkerPrivate + { +- int state; ++ GdmSessionWorkerState state; + + int exit_code; + + pam_handle_t *pam_handle; + + GPid child_pid; + guint child_watch_id; + + /* from Setup */ + char *service; + char *x11_display_name; + char *x11_authority_file; + char *display_device; + char *display_seat_id; + char *hostname; + char *username; + char *log_file; + char *session_id; + uid_t uid; + gid_t gid; + gboolean password_is_required; + char **extensions; + + int cred_flags; + int login_vt; + int session_vt; + int session_tty_fd; + + char **arguments; + guint32 cancelled : 1; +@@ -2455,60 +2444,63 @@ gdm_session_worker_set_property (GObject *object, + switch (prop_id) { + case PROP_SERVER_ADDRESS: + gdm_session_worker_set_server_address (self, g_value_get_string (value)); + break; + case PROP_IS_REAUTH_SESSION: + gdm_session_worker_set_is_reauth_session (self, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static void + gdm_session_worker_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + GdmSessionWorker *self; + + self = GDM_SESSION_WORKER (object); + + switch (prop_id) { + case PROP_SERVER_ADDRESS: + g_value_set_string (value, self->priv->server_address); + break; + case PROP_IS_REAUTH_SESSION: + g_value_set_boolean (value, self->priv->is_reauth_session); + break; ++ case PROP_STATE: ++ g_value_set_int (value, self->priv->state); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static gboolean + gdm_session_worker_handle_set_environment_variable (GdmDBusWorker *object, + GDBusMethodInvocation *invocation, + const char *key, + const char *value) + { + GdmSessionWorker *worker = GDM_SESSION_WORKER (object); + gdm_session_worker_set_environment_variable (worker, key, value); + gdm_dbus_worker_complete_set_environment_variable (object, invocation); + return TRUE; + } + + static gboolean + gdm_session_worker_handle_set_session_name (GdmDBusWorker *object, + GDBusMethodInvocation *invocation, + const char *session_name) + { + GdmSessionWorker *worker = GDM_SESSION_WORKER (object); + g_debug ("GdmSessionWorker: session name set to %s", session_name); + if (worker->priv->user_settings != NULL) + gdm_session_settings_set_session_name (worker->priv->user_settings, + session_name); + gdm_dbus_worker_complete_set_session_name (object, invocation); + return TRUE; +diff --git a/daemon/gdm-session-worker.h b/daemon/gdm-session-worker.h +index 5603e80e0..2814eab4d 100644 +--- a/daemon/gdm-session-worker.h ++++ b/daemon/gdm-session-worker.h +@@ -1,56 +1,68 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2006 Ray Strode + * + * 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, 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_SESSION_WORKER_H + #define __GDM_SESSION_WORKER_H + + #include + + #include "gdm-session-worker-glue.h" + #include "gdm-session-worker-common.h" ++#include "gdm-session-worker-enum-types.h" + + G_BEGIN_DECLS + + #define GDM_TYPE_SESSION_WORKER (gdm_session_worker_get_type ()) + #define GDM_SESSION_WORKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SESSION_WORKER, GdmSessionWorker)) + #define GDM_SESSION_WORKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerClass)) + #define GDM_IS_SESSION_WORKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SESSION_WORKER)) + #define GDM_IS_SESSION_WORKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SESSION_WORKER)) + #define GDM_SESSION_WORKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerClass)) + ++typedef enum { ++ GDM_SESSION_WORKER_STATE_NONE = 0, ++ GDM_SESSION_WORKER_STATE_SETUP_COMPLETE, ++ GDM_SESSION_WORKER_STATE_AUTHENTICATED, ++ GDM_SESSION_WORKER_STATE_AUTHORIZED, ++ GDM_SESSION_WORKER_STATE_ACCREDITED, ++ GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED, ++ GDM_SESSION_WORKER_STATE_SESSION_OPENED, ++ GDM_SESSION_WORKER_STATE_SESSION_STARTED ++} GdmSessionWorkerState; ++ + typedef struct GdmSessionWorkerPrivate GdmSessionWorkerPrivate; + + typedef struct + { + GdmDBusWorkerSkeleton parent; + GdmSessionWorkerPrivate *priv; + } GdmSessionWorker; + + typedef struct + { + GdmDBusWorkerSkeletonClass parent_class; + } GdmSessionWorkerClass; + + GType gdm_session_worker_get_type (void); + + GdmSessionWorker * gdm_session_worker_new (const char *server_address, + gboolean is_for_reauth) G_GNUC_MALLOC; + G_END_DECLS + #endif /* GDM_SESSION_WORKER_H */ +-- +2.18.1 + diff --git a/SOURCES/0002-session-worker-kill-user-sessions-when-stop-gdm-serv.patch b/SOURCES/0002-session-worker-kill-user-sessions-when-stop-gdm-serv.patch new file mode 100644 index 0000000..85175ea --- /dev/null +++ b/SOURCES/0002-session-worker-kill-user-sessions-when-stop-gdm-serv.patch @@ -0,0 +1,922 @@ +From 4db5bf628396a7191f2392e7d09ab9bbd7c2b533 Mon Sep 17 00:00:00 2001 +From: Xiaoguang Wang +Date: Thu, 16 May 2019 13:26:16 +0800 +Subject: [PATCH 2/3] session-worker: kill user sessions when stop gdm service + +At the moment the session worker exits as soon as it gets SIGTERM. +That means it may fail to stop the user session (which only happens +in the orderly shutdown path). + +This commit sets up a SIGTERM handler that integrates with and +quits the main loop after the session is started. + +It still retains the _exit-on-SIGTERM behavior before the session +is started, to ensure a stuck pam module doesn't prevent the +process from dying. + +Some small changes to commit by Ray Strode. + +Closes #400 +--- + daemon/gdm-session-worker.c | 39 +++++++++++++++++++++++++++--------- + daemon/session-worker-main.c | 33 ++++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+), 9 deletions(-) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index f6935ab1d..aa288ac8e 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -159,60 +159,61 @@ struct GdmSessionWorkerPrivate + guint32 display_is_initial : 1; + guint state_change_idle_id; + GdmSessionDisplayMode display_mode; + + char *server_address; + GDBusConnection *connection; + GdmDBusWorkerManager *manager; + + GHashTable *reauthentication_requests; + + GdmSessionAuditor *auditor; + GdmSessionSettings *user_settings; + + GDBusMethodInvocation *pending_invocation; + }; + + #ifdef SUPPORTS_PAM_EXTENSIONS + static char gdm_pam_extension_environment_block[_POSIX_ARG_MAX]; + + static const char * const + gdm_supported_pam_extensions[] = { + GDM_PAM_EXTENSION_CHOICE_LIST, + NULL + }; + #endif + + enum { + PROP_0, + PROP_SERVER_ADDRESS, + PROP_IS_REAUTH_SESSION, ++ PROP_STATE, + }; + + static void gdm_session_worker_class_init (GdmSessionWorkerClass *klass); + static void gdm_session_worker_init (GdmSessionWorker *session_worker); + static void gdm_session_worker_finalize (GObject *object); + + static void gdm_session_worker_set_environment_variable (GdmSessionWorker *worker, + const char *key, + const char *value); + + static void queue_state_change (GdmSessionWorker *worker); + + static void worker_interface_init (GdmDBusWorkerIface *iface); + + + typedef int (* GdmSessionWorkerPamNewMessagesFunc) (int, + const struct pam_message **, + struct pam_response **, + gpointer); + + G_DEFINE_TYPE_WITH_CODE (GdmSessionWorker, + gdm_session_worker, + GDM_DBUS_TYPE_WORKER_SKELETON, + G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_WORKER, + worker_interface_init)) + + /* adapted from glib script_execute */ + static void + script_execute (const gchar *file, + char **argv, +@@ -971,100 +972,111 @@ jump_to_vt (GdmSessionWorker *worker, + + g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker"); + if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) { + g_debug ("GdmSessionWorker: couldn't set graphics mode: %m"); + } + + /* It's possible that the current VT was left in a broken + * combination of states (KD_GRAPHICS with VT_AUTO), that + * can't be switched away from. This call makes sure things + * are set in a way that VT_ACTIVATE should work and + * VT_WAITACTIVE shouldn't hang. + */ + fix_terminal_vt_mode (worker, active_vt_tty_fd); + } else { + fd = active_vt_tty_fd; + } + + handle_terminal_vt_switches (worker, fd); + + if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) { + g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m", + vt_number); + } else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) { + g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m", + vt_number); + } + + close (active_vt_tty_fd); + } + ++static void ++gdm_session_worker_set_state (GdmSessionWorker *worker, ++ GdmSessionWorkerState state) ++{ ++ if (worker->priv->state == state) ++ return; ++ ++ worker->priv->state = state; ++ g_object_notify (G_OBJECT (worker), "state"); ++} ++ + 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); + + if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) { + if (worker->priv->login_vt != worker->priv->session_vt) { + jump_to_vt (worker, worker->priv->login_vt); + } + } + + worker->priv->login_vt = 0; + worker->priv->session_vt = 0; + + g_debug ("GdmSessionWorker: state NONE"); +- worker->priv->state = GDM_SESSION_WORKER_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) { + len += auth->name_length + auth->data_length; + retval = g_malloc0 (len); +@@ -1173,61 +1185,61 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker, + goto out; + } + } + + /* set RHOST */ + if (hostname != NULL && hostname[0] != '\0') { + error_code = pam_set_item (worker->priv->pam_handle, PAM_RHOST, hostname); + g_debug ("error informing authentication system of user's hostname %s: %s", + hostname, + pam_strerror (worker->priv->pam_handle, error_code)); + + if (error_code != PAM_SUCCESS) { + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_AUTHENTICATING, + "%s", ""); + goto out; + } + } + + /* set seat ID */ + if (seat_id != NULL && seat_id[0] != '\0') { + gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id); + } + + if (strcmp (service, "gdm-launch-environment") == 0) { + gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter"); + } + + g_debug ("GdmSessionWorker: state SETUP_COMPLETE"); +- worker->priv->state = GDM_SESSION_WORKER_STATE_SETUP_COMPLETE; ++ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE); + + /* Temporarily set PAM_TTY with the currently active VT (login screen) + PAM_TTY will be reset with the users VT right before the user session is opened */ + ensure_login_vt (worker); + g_snprintf (tty_string, 256, "/dev/tty%d", worker->priv->login_vt); + pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string); + if (!display_is_local) + worker->priv->password_is_required = TRUE; + + out: + if (error_code != PAM_SUCCESS) { + gdm_session_worker_uninitialize_pam (worker, error_code); + return FALSE; + } + + return TRUE; + } + + static gboolean + gdm_session_worker_authenticate_user (GdmSessionWorker *worker, + gboolean password_is_required, + GError **error) + { + int error_code; + int authentication_flags; + + g_debug ("GdmSessionWorker: authenticating user %s", worker->priv->username); + + authentication_flags = 0; + +@@ -1238,61 +1250,61 @@ gdm_session_worker_authenticate_user (GdmSessionWorker *worker, + /* blocking call, does the actual conversation */ + error_code = pam_authenticate (worker->priv->pam_handle, authentication_flags); + + if (error_code == PAM_AUTHINFO_UNAVAIL) { + g_debug ("GdmSessionWorker: authentication service unavailable"); + + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE, + "%s", ""); + goto out; + } else if (error_code != PAM_SUCCESS) { + g_debug ("GdmSessionWorker: authentication returned %d: %s", error_code, pam_strerror (worker->priv->pam_handle, error_code)); + + /* + * Do not display a different message for user unknown versus + * a failed password for a valid user. + */ + if (error_code == PAM_USER_UNKNOWN) { + error_code = PAM_AUTH_ERR; + } + + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_AUTHENTICATING, + "%s", get_friendly_error_message (error_code)); + goto out; + } + + g_debug ("GdmSessionWorker: state AUTHENTICATED"); +- worker->priv->state = GDM_SESSION_WORKER_STATE_AUTHENTICATED; ++ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_AUTHENTICATED); + + out: + if (error_code != PAM_SUCCESS) { + gdm_session_worker_uninitialize_pam (worker, error_code); + return FALSE; + } + + return TRUE; + } + + static gboolean + gdm_session_worker_authorize_user (GdmSessionWorker *worker, + gboolean password_is_required, + GError **error) + { + int error_code; + int authentication_flags; + + g_debug ("GdmSessionWorker: determining if authenticated user (password required:%d) is authorized to session", + password_is_required); + + authentication_flags = 0; + + if (password_is_required) { + authentication_flags |= PAM_DISALLOW_NULL_AUTHTOK; + } + + /* check that the account isn't disabled or expired + */ + error_code = pam_acct_mgmt (worker->priv->pam_handle, authentication_flags); +@@ -1303,61 +1315,61 @@ gdm_session_worker_authorize_user (GdmSessionWorker *worker, + g_debug ("GdmSessionWorker: authenticated user requires new auth token"); + error_code = pam_chauthtok (worker->priv->pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK); + + gdm_session_worker_get_username (worker, NULL); + + if (error_code != PAM_SUCCESS) { + gdm_session_auditor_report_password_change_failure (worker->priv->auditor); + } else { + gdm_session_auditor_report_password_changed (worker->priv->auditor); + } + } + + /* If the user is reauthenticating, then authorization isn't required to + * proceed, the user is already logged in after all. + */ + if (worker->priv->is_reauth_session) { + error_code = PAM_SUCCESS; + } + + if (error_code != PAM_SUCCESS) { + g_debug ("GdmSessionWorker: user is not authorized to log in: %s", + pam_strerror (worker->priv->pam_handle, error_code)); + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_AUTHORIZING, + "%s", get_friendly_error_message (error_code)); + goto out; + } + + g_debug ("GdmSessionWorker: state AUTHORIZED"); +- worker->priv->state = GDM_SESSION_WORKER_STATE_AUTHORIZED; ++ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_AUTHORIZED); + + out: + if (error_code != PAM_SUCCESS) { + gdm_session_worker_uninitialize_pam (worker, error_code); + return FALSE; + } + + return TRUE; + } + + static void + gdm_session_worker_set_environment_variable (GdmSessionWorker *worker, + const char *key, + const char *value) + { + int error_code; + char *environment_entry; + + if (value != NULL) { + environment_entry = g_strdup_printf ("%s=%s", key, value); + } else { + /* empty value means "remove from environment" */ + environment_entry = g_strdup (key); + } + + error_code = pam_putenv (worker->priv->pam_handle, + environment_entry); + + if (error_code != PAM_SUCCESS) { + g_warning ("cannot put %s in pam environment: %s\n", +@@ -1716,61 +1728,61 @@ gdm_session_worker_accredit_user (GdmSessionWorker *worker, + + /* If the user is reauthenticating and they've made it this far, then there + * is no reason we should lock them out of their session. They've already + * proved they are they same person who logged in, and that's all we care + * about. + */ + if (worker->priv->is_reauth_session) { + error_code = PAM_SUCCESS; + } + + if (error_code != PAM_SUCCESS) { + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS, + "%s", + pam_strerror (worker->priv->pam_handle, error_code)); + goto out; + } + + ret = TRUE; + + out: + g_free (home); + g_free (shell); + if (ret) { + g_debug ("GdmSessionWorker: state ACCREDITED"); + ret = TRUE; + + gdm_session_worker_get_username (worker, NULL); + gdm_session_auditor_report_user_accredited (worker->priv->auditor); +- worker->priv->state = GDM_SESSION_WORKER_STATE_ACCREDITED; ++ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCREDITED); + } else { + gdm_session_worker_uninitialize_pam (worker, error_code); + } + + return ret; + } + + static const char * const * + gdm_session_worker_get_environment (GdmSessionWorker *worker) + { + return (const char * const *) pam_getenvlist (worker->priv->pam_handle); + } + + static gboolean + run_script (GdmSessionWorker *worker, + const char *dir) + { + /* scripts are for non-program sessions only */ + if (worker->priv->is_program_session) { + return TRUE; + } + + return gdm_run_script (dir, + worker->priv->username, + worker->priv->x11_display_name, + worker->priv->display_is_local? NULL : worker->priv->hostname, + worker->priv->x11_authority_file); + } + + static void +@@ -2145,61 +2157,61 @@ gdm_session_worker_start_session (GdmSessionWorker *worker, + (char **) + environment, + TRUE); + + gdm_log_init (); + g_debug ("GdmSessionWorker: child '%s' could not be started: %s", + worker->priv->arguments[0], + g_strerror (errno)); + + _exit (EXIT_FAILURE); + } + + if (worker->priv->session_tty_fd > 0) { + close (worker->priv->session_tty_fd); + worker->priv->session_tty_fd = -1; + } + + /* If we end up execing again, make sure we don't use the executable context set up + * by pam_selinux durin pam_open_session + */ + #ifdef HAVE_SELINUX + setexeccon (NULL); + #endif + + worker->priv->child_pid = session_pid; + + g_debug ("GdmSessionWorker: session opened creating reply..."); + g_assert (sizeof (GPid) <= sizeof (int)); + + g_debug ("GdmSessionWorker: state SESSION_STARTED"); +- worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_STARTED; ++ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED); + + gdm_session_worker_watch_child (worker); + + out: + if (error_code != PAM_SUCCESS) { + gdm_session_worker_uninitialize_pam (worker, error_code); + return FALSE; + } + + return TRUE; + } + + static gboolean + set_up_for_new_vt (GdmSessionWorker *worker) + { + int fd; + char vt_string[256], tty_string[256]; + int session_vt = 0; + + fd = open ("/dev/tty0", O_RDWR | O_NOCTTY); + + if (fd < 0) { + g_debug ("GdmSessionWorker: couldn't open VT master: %m"); + return FALSE; + } + + if (worker->priv->display_is_initial) { + session_vt = atoi (GDM_INITIAL_VT); + } else { + if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) { +@@ -2368,61 +2380,61 @@ gdm_session_worker_open_session (GdmSessionWorker *worker, + break; + case GDM_SESSION_DISPLAY_MODE_NEW_VT: + case GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED: + if (!set_up_for_new_vt (worker)) { + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_OPENING_SESSION, + "Unable to open VT"); + return FALSE; + } + break; + } + + flags = 0; + + if (worker->priv->is_program_session) { + flags |= PAM_SILENT; + } + + error_code = pam_open_session (worker->priv->pam_handle, flags); + + if (error_code != PAM_SUCCESS) { + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_OPENING_SESSION, + "%s", pam_strerror (worker->priv->pam_handle, error_code)); + goto out; + } + + g_debug ("GdmSessionWorker: state SESSION_OPENED"); +- worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_OPENED; ++ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_OPENED); + + session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID"); + + if (session_id != NULL) { + g_free (worker->priv->session_id); + worker->priv->session_id = session_id; + } + + out: + if (error_code != PAM_SUCCESS) { + gdm_session_worker_uninitialize_pam (worker, error_code); + return FALSE; + } + + gdm_session_worker_get_username (worker, NULL); + gdm_session_auditor_report_login (worker->priv->auditor); + + return TRUE; + } + + static void + gdm_session_worker_set_server_address (GdmSessionWorker *worker, + const char *address) + { + g_free (worker->priv->server_address); + worker->priv->server_address = g_strdup (address); + } + + static void + gdm_session_worker_set_is_reauth_session (GdmSessionWorker *worker, +@@ -2445,61 +2457,61 @@ gdm_session_worker_set_property (GObject *object, + case PROP_SERVER_ADDRESS: + gdm_session_worker_set_server_address (self, g_value_get_string (value)); + break; + case PROP_IS_REAUTH_SESSION: + gdm_session_worker_set_is_reauth_session (self, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static void + gdm_session_worker_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + GdmSessionWorker *self; + + self = GDM_SESSION_WORKER (object); + + switch (prop_id) { + case PROP_SERVER_ADDRESS: + g_value_set_string (value, self->priv->server_address); + break; + case PROP_IS_REAUTH_SESSION: + g_value_set_boolean (value, self->priv->is_reauth_session); + break; + case PROP_STATE: +- g_value_set_int (value, self->priv->state); ++ g_value_set_enum (value, self->priv->state); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static gboolean + gdm_session_worker_handle_set_environment_variable (GdmDBusWorker *object, + GDBusMethodInvocation *invocation, + const char *key, + const char *value) + { + GdmSessionWorker *worker = GDM_SESSION_WORKER (object); + gdm_session_worker_set_environment_variable (worker, key, value); + gdm_dbus_worker_complete_set_environment_variable (object, invocation); + return TRUE; + } + + static gboolean + gdm_session_worker_handle_set_session_name (GdmDBusWorker *object, + GDBusMethodInvocation *invocation, + const char *session_name) + { + GdmSessionWorker *worker = GDM_SESSION_WORKER (object); + g_debug ("GdmSessionWorker: session name set to %s", session_name); + if (worker->priv->user_settings != NULL) + gdm_session_settings_set_session_name (worker->priv->user_settings, + session_name); + gdm_dbus_worker_complete_set_session_name (object, invocation); +@@ -2646,61 +2658,61 @@ do_authorize (GdmSessionWorker *worker) + g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error); + } + worker->priv->pending_invocation = NULL; + } + + static void + do_accredit (GdmSessionWorker *worker) + { + GError *error; + gboolean res; + + /* get kerberos tickets, setup group lists, etc + */ + error = NULL; + res = gdm_session_worker_accredit_user (worker, &error); + + if (res) { + gdm_dbus_worker_complete_establish_credentials (GDM_DBUS_WORKER (worker), worker->priv->pending_invocation); + } else { + g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error); + } + worker->priv->pending_invocation = NULL; + } + + static void + save_account_details_now (GdmSessionWorker *worker) + { + g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCREDITED); + + g_debug ("GdmSessionWorker: saving account details for user %s", worker->priv->username); +- worker->priv->state = GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED; ++ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED); + if (worker->priv->user_settings != NULL) { + if (!gdm_session_settings_save (worker->priv->user_settings, + worker->priv->username)) { + g_warning ("could not save session and language settings"); + } + } + queue_state_change (worker); + } + + static void + on_settings_is_loaded_changed (GdmSessionSettings *user_settings, + GParamSpec *pspec, + GdmSessionWorker *worker) + { + if (!gdm_session_settings_is_loaded (worker->priv->user_settings)) { + return; + } + + /* These signal handlers should be disconnected after the loading, + * so that gdm_session_settings_set_* APIs don't cause the emitting + * of Saved*NameRead D-Bus signals any more. + */ + g_signal_handlers_disconnect_by_func (worker->priv->user_settings, + G_CALLBACK (on_saved_session_name_read), + worker); + + g_signal_handlers_disconnect_by_func (worker->priv->user_settings, + G_CALLBACK (on_saved_language_name_read), + worker); + +@@ -3461,60 +3473,69 @@ worker_interface_init (GdmDBusWorkerIface *interface) + interface->handle_start_reauthentication = gdm_session_worker_handle_start_reauthentication; + } + + static void + gdm_session_worker_class_init (GdmSessionWorkerClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = gdm_session_worker_get_property; + object_class->set_property = gdm_session_worker_set_property; + object_class->constructor = gdm_session_worker_constructor; + object_class->finalize = gdm_session_worker_finalize; + + g_type_class_add_private (klass, sizeof (GdmSessionWorkerPrivate)); + + g_object_class_install_property (object_class, + PROP_SERVER_ADDRESS, + g_param_spec_string ("server-address", + "server address", + "server address", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (object_class, + PROP_IS_REAUTH_SESSION, + g_param_spec_boolean ("is-reauth-session", + "is reauth session", + "is reauth session", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); ++ ++ g_object_class_install_property (object_class, ++ PROP_STATE, ++ g_param_spec_enum ("state", ++ "state", ++ "state", ++ GDM_TYPE_SESSION_WORKER_STATE, ++ GDM_SESSION_WORKER_STATE_NONE, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + } + + static void + reauthentication_request_free (ReauthenticationRequest *request) + { + + g_signal_handlers_disconnect_by_func (request->session, + G_CALLBACK (on_reauthentication_client_connected), + request); + g_signal_handlers_disconnect_by_func (request->session, + G_CALLBACK (on_reauthentication_client_disconnected), + request); + g_signal_handlers_disconnect_by_func (request->session, + G_CALLBACK (on_reauthentication_cancelled), + request); + g_signal_handlers_disconnect_by_func (request->session, + G_CALLBACK (on_reauthentication_conversation_started), + request); + g_signal_handlers_disconnect_by_func (request->session, + G_CALLBACK (on_reauthentication_conversation_stopped), + request); + g_signal_handlers_disconnect_by_func (request->session, + G_CALLBACK (on_reauthentication_verification_complete), + request); + g_clear_object (&request->session); + g_slice_free (ReauthenticationRequest, request); + } + + static void + gdm_session_worker_init (GdmSessionWorker *worker) +diff --git a/daemon/session-worker-main.c b/daemon/session-worker-main.c +index 4a3a8ebbe..d96844d2d 100644 +--- a/daemon/session-worker-main.c ++++ b/daemon/session-worker-main.c +@@ -37,104 +37,137 @@ + #include + + #include "gdm-common.h" + #include "gdm-log.h" + #include "gdm-session-worker.h" + + #include "gdm-settings.h" + #include "gdm-settings-direct.h" + #include "gdm-settings-keys.h" + + static GdmSettings *settings = NULL; + + static gboolean + on_sigusr1_cb (gpointer user_data) + { + g_debug ("Got USR1 signal"); + + gdm_log_toggle_debug (); + + return TRUE; + } + + static gboolean + is_debug_set (void) + { + gboolean debug; + gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug); + return debug; + } + ++static gboolean ++on_shutdown_signal_cb (gpointer user_data) ++{ ++ GMainLoop *mainloop = user_data; ++ ++ g_main_loop_quit (mainloop); ++ ++ return FALSE; ++} ++ ++static void ++on_state_changed (GdmSessionWorker *worker, ++ GParamSpec *pspec, ++ GMainLoop *main_loop) ++{ ++ GdmSessionWorkerState state; ++ ++ g_object_get (G_OBJECT (worker), "state", &state, NULL); ++ ++ if (state != GDM_SESSION_WORKER_STATE_SESSION_STARTED) ++ return; ++ ++ g_unix_signal_add (SIGTERM, on_shutdown_signal_cb, main_loop); ++} ++ + static void + on_sigterm_cb (int signal_number) + { + _exit (EXIT_SUCCESS); + } + + int + main (int argc, + char **argv) + { + GMainLoop *main_loop; + GOptionContext *context; + GdmSessionWorker *worker; + const char *address; + gboolean is_for_reauth; + static GOptionEntry entries [] = { + { NULL } + }; + + signal (SIGTERM, on_sigterm_cb); + + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + textdomain (GETTEXT_PACKAGE); + setlocale (LC_ALL, ""); + + /* Translators: worker is a helper process that does the work + of starting up a session */ + context = g_option_context_new (_("GNOME Display Manager Session Worker")); + g_option_context_add_main_entries (context, entries, NULL); + + g_option_context_parse (context, &argc, &argv, NULL); + g_option_context_free (context); + + gdm_log_init (); + + settings = gdm_settings_new (); + if (settings == NULL) { + g_warning ("Unable to initialize settings"); + exit (EXIT_FAILURE); + } + + if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) { + g_warning ("Unable to initialize settings"); + exit (EXIT_FAILURE); + } + + gdm_log_set_debug (is_debug_set ()); + + address = g_getenv ("GDM_SESSION_DBUS_ADDRESS"); + if (address == NULL) { + g_warning ("GDM_SESSION_DBUS_ADDRESS not set"); + exit (EXIT_FAILURE); + } + + is_for_reauth = g_getenv ("GDM_SESSION_FOR_REAUTH") != NULL; + + worker = gdm_session_worker_new (address, is_for_reauth); + + main_loop = g_main_loop_new (NULL, FALSE); + ++ g_signal_connect (G_OBJECT (worker), ++ "notify::state", ++ G_CALLBACK (on_state_changed), ++ main_loop); ++ + g_unix_signal_add (SIGUSR1, on_sigusr1_cb, NULL); + + g_main_loop_run (main_loop); + + if (worker != NULL) { ++ g_signal_handlers_disconnect_by_func (worker, ++ G_CALLBACK (on_state_changed), ++ main_loop); + g_object_unref (worker); + } + + g_main_loop_unref (main_loop); + + g_debug ("Worker finished"); + + return 0; + } +-- +2.18.1 + diff --git a/SOURCES/0003-session-worker-uninitialize-pam-if-worker-is-killed.patch b/SOURCES/0003-session-worker-uninitialize-pam-if-worker-is-killed.patch new file mode 100644 index 0000000..e79e546 --- /dev/null +++ b/SOURCES/0003-session-worker-uninitialize-pam-if-worker-is-killed.patch @@ -0,0 +1,85 @@ +From 1987a539495f38ade3efc561f65b56316080356e Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 24 Jun 2019 16:21:59 -0400 +Subject: [PATCH 3/3] session-worker: uninitialize pam if worker is killed + +Right nowe don't uninitialize pam or switch back to the +starting VT if the worker is killed before the session. + +This commit fixes that. +--- + daemon/gdm-session-worker.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index aa288ac8e..0322037e0 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -3552,60 +3552,64 @@ gdm_session_worker_init (GdmSessionWorker *worker) + static void + gdm_session_worker_unwatch_child (GdmSessionWorker *worker) + { + if (worker->priv->child_watch_id == 0) + return; + + g_source_remove (worker->priv->child_watch_id); + worker->priv->child_watch_id = 0; + } + + + static void + gdm_session_worker_finalize (GObject *object) + { + GdmSessionWorker *worker; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_SESSION_WORKER (object)); + + worker = GDM_SESSION_WORKER (object); + + g_return_if_fail (worker->priv != NULL); + + gdm_session_worker_unwatch_child (worker); + + if (worker->priv->child_pid > 0) { + gdm_signal_pid (worker->priv->child_pid, SIGTERM); + gdm_wait_on_pid (worker->priv->child_pid); + } + ++ if (worker->priv->pam_handle != NULL) { ++ gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS); ++ } ++ + g_clear_object (&worker->priv->user_settings); + g_free (worker->priv->service); + g_free (worker->priv->x11_display_name); + g_free (worker->priv->x11_authority_file); + g_free (worker->priv->display_device); + g_free (worker->priv->display_seat_id); + g_free (worker->priv->hostname); + g_free (worker->priv->username); + g_free (worker->priv->server_address); + g_strfreev (worker->priv->arguments); + g_strfreev (worker->priv->extensions); + + g_hash_table_unref (worker->priv->reauthentication_requests); + + G_OBJECT_CLASS (gdm_session_worker_parent_class)->finalize (object); + } + + GdmSessionWorker * + gdm_session_worker_new (const char *address, + gboolean is_reauth_session) + { + GObject *object; + + object = g_object_new (GDM_TYPE_SESSION_WORKER, + "server-address", address, + "is-reauth-session", is_reauth_session, + NULL); + + return GDM_SESSION_WORKER (object); + } +-- +2.18.1 + diff --git a/SOURCES/0004-data-reap-gdm-sessions-on-shutdown.patch b/SOURCES/0004-data-reap-gdm-sessions-on-shutdown.patch new file mode 100644 index 0000000..d0c0451 --- /dev/null +++ b/SOURCES/0004-data-reap-gdm-sessions-on-shutdown.patch @@ -0,0 +1,28 @@ +From f32adbe9bf26d502cb055b3a6cb98fc57e06bf13 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 26 Jul 2019 14:06:16 -0400 +Subject: [PATCH 4/4] 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 72201c1fd..202ab6753 100644 +--- a/data/gdm.service.in ++++ b/data/gdm.service.in +@@ -21,6 +21,7 @@ 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 +-- +2.18.1 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index 3197b94..af6fae0 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -10,7 +10,7 @@ Name: gdm Epoch: 1 Version: 3.28.3 -Release: 20%{?dist} +Release: 22%{?dist} Summary: The GNOME Display Manager License: GPLv2+ @@ -38,7 +38,12 @@ Patch82: 0002-session-support-new-accountsservice-Session-and-Sess.patch Patch83: 0003-daemon-save-os-release-in-accountsservice.patch Patch84: 0004-daemon-handle-upgrades-from-RHEL-7.patch -Patch99: system-dconf.patch +Patch91: 0001-session-worker-expose-worker-state-enum-to-type-syst.patch +Patch92: 0002-session-worker-kill-user-sessions-when-stop-gdm-serv.patch +Patch93: 0003-session-worker-uninitialize-pam-if-worker-is-killed.patch +Patch94: 0004-data-reap-gdm-sessions-on-shutdown.patch + +Patch9999: system-dconf.patch BuildRequires: pam-devel >= 0:%{pam_version} BuildRequires: desktop-file-utils >= %{desktop_file_utils_version} @@ -192,6 +197,8 @@ mkdir -p %{buildroot}%{_datadir}/gdm/autostart/LoginWindow mkdir -p %{buildroot}/run/gdm +rm -f %{buildroot}%{_bindir}/gdm-screenshot + find %{buildroot} -name '*.a' -delete find %{buildroot} -name '*.la' -delete @@ -293,7 +300,6 @@ fi %{_libexecdir}/gdm-x-session %{_sbindir}/gdm %{_bindir}/gdmflexiserver -%{_bindir}/gdm-screenshot %dir %{_datadir}/dconf %dir %{_datadir}/dconf/profile %{_datadir}/dconf/profile/gdm @@ -337,6 +343,15 @@ fi %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Mon Jun 24 2019 Ray Strode - 3.28.3-22 +- Ensure user session is killed with its worker and that all + user sessions are cleaned up on shutdown + Resolves: #1690714 + +* Mon Jun 17 2019 Ray Strode - 3.28.3-21 +- Drop gdm-screenshot + Resolves: #1680164 + * Mon Feb 11 2019 Ray Strode - 3.28.3-20 - Disable wayland on hybrid gpu machines, and server machines again