From 4dd5a856c29a1d7e5afc25c90b124fe9614f9b82 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 28 2020 09:35:31 +0000 Subject: import gdm-3.28.3-29.el8 --- diff --git a/SOURCES/0001-daemon-fix-wayland-detection-when-deciding-to-bypass.patch b/SOURCES/0001-daemon-fix-wayland-detection-when-deciding-to-bypass.patch new file mode 100644 index 0000000..c442a45 --- /dev/null +++ b/SOURCES/0001-daemon-fix-wayland-detection-when-deciding-to-bypass.patch @@ -0,0 +1,135 @@ +From b9f38b65417923624bf97a18daf1c2ede5e8651e Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 15 Dec 2019 14:51:44 -0500 +Subject: [PATCH] daemon: fix wayland detection when deciding to bypass + Xsession + +At the moment if there's a session file with the same name in +both /usr/share/xsessions and /usr/share/wayland-sessions, GDM +will think the wayland is getting used when deciding whether or +not to bypass the /etc/gdm/Xsession script, even if wayland is +explicitly being ignored. + +This commit fixes the check. +--- + daemon/gdm-session.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index a8263ba11..ecb2b3cac 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -3145,96 +3145,96 @@ gdm_session_get_session_id (GdmSession *self) + return conversation->session_id; + } + + const char * + gdm_session_get_conversation_session_id (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + + g_return_val_if_fail (GDM_IS_SESSION (self), NULL); + + conversation = find_conversation_by_name (self, service_name); + + if (conversation == NULL) { + return NULL; + } + + return conversation->session_id; + } + + static char * + get_session_filename (GdmSession *self) + { + return g_strdup_printf ("%s.desktop", get_session_name (self)); + } + + #ifdef ENABLE_WAYLAND_SUPPORT + static gboolean + gdm_session_is_wayland_session (GdmSession *self) + { +- GKeyFile *key_file; ++ g_autoptr (GKeyFile) key_file = NULL; + gboolean is_wayland_session = FALSE; +- char *filename; +- char *full_path = NULL; ++ g_autofree char *filename = NULL; ++ g_autofree char *full_path = NULL; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + filename = get_session_filename (self); + +- key_file = load_key_file_for_file (self, filename, "wayland", &full_path); ++ if (!self->priv->ignore_wayland) { ++ key_file = load_key_file_for_file (self, filename, "wayland", &full_path); + +- if (key_file == NULL) { +- goto out; +- } ++ if (key_file == NULL) { ++ goto out; ++ } + +- if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) { +- is_wayland_session = TRUE; ++ if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) { ++ is_wayland_session = TRUE; ++ } + } +- g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no"); + + out: +- g_clear_pointer (&key_file, (GDestroyNotify) g_key_file_free); +- g_free (filename); ++ g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no"); ++ + return is_wayland_session; + } + #endif + + static void + update_session_type (GdmSession *self) + { + #ifdef ENABLE_WAYLAND_SUPPORT + gboolean is_wayland_session = FALSE; + +- if (!self->priv->ignore_wayland) +- is_wayland_session = gdm_session_is_wayland_session (self); ++ is_wayland_session = gdm_session_is_wayland_session (self); + + if (is_wayland_session) { + set_session_type (self, "wayland"); + } else { + set_session_type (self, NULL); + } + #endif + } + + gboolean + gdm_session_bypasses_xsession (GdmSession *self) + { + GError *error; + GKeyFile *key_file; + gboolean res; + gboolean bypasses_xsession = FALSE; + char *filename = NULL; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + #ifdef ENABLE_WAYLAND_SUPPORT + if (gdm_session_is_wayland_session (self)) { + bypasses_xsession = TRUE; + goto out; + } + #endif + + filename = get_session_filename (self); + +-- +2.18.1 + diff --git a/SOURCES/0001-data-disable-wayland-for-legacy-QXL-VMs.patch b/SOURCES/0001-data-disable-wayland-for-legacy-QXL-VMs.patch deleted file mode 100644 index f55d5f2..0000000 --- a/SOURCES/0001-data-disable-wayland-for-legacy-QXL-VMs.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 84eac5437175efc3804e8a6133c06484d6016b26 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 4 Jan 2019 16:40:07 -0500 -Subject: [PATCH] data: disable wayland for legacy QXL VMs - -There are a number of issues right now with the QXL driver that -prevent it from working well with wayland. - -These days QXL is deprecated in favor of virtio anyway. - -This commit forces Xorg fallback for QXL VMs. ---- - data/61-gdm.rules.in | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in -index 26cf9cf51..ec19aa447 100644 ---- a/data/61-gdm.rules.in -+++ b/data/61-gdm.rules.in -@@ -1,5 +1,8 @@ - # disable Wayland on Cirrus chipsets - ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="@libexecdir@/gdm-disable-wayland" - -+# disable Wayland on legacy QXL virtual machines -+ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", RUN+="@libexecdir@/gdm-disable-wayland" -+ - # disable Wayland when using the proprietary nvidia driver - DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland" --- -2.17.1 - diff --git a/SOURCES/0001-data-disable-wayland-on-server-chips-and-dual-gpu-se.patch b/SOURCES/0001-data-disable-wayland-on-server-chips-and-dual-gpu-se.patch index 3cd8a00..67f27fd 100644 --- a/SOURCES/0001-data-disable-wayland-on-server-chips-and-dual-gpu-se.patch +++ b/SOURCES/0001-data-disable-wayland-on-server-chips-and-dual-gpu-se.patch @@ -1,4 +1,4 @@ -From 21be64e1ba86bd57a4257a7526c9b4ee430bfdaa Mon Sep 17 00:00:00 2001 +From 13a617e15cca421962be888b5607a9900bbfef51 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 11 Feb 2019 18:14:07 -0500 Subject: [PATCH] data: disable wayland on server chips and dual gpu setups @@ -12,10 +12,10 @@ This commit forces Xorg for those cases. 1 file changed, 18 insertions(+) diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in -index ec19aa447..1c308d511 100644 +index 26cf9cf51..e3631740d 100644 --- a/data/61-gdm.rules.in +++ b/data/61-gdm.rules.in -@@ -1,8 +1,26 @@ +@@ -1,5 +1,23 @@ # disable Wayland on Cirrus chipsets ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="@libexecdir@/gdm-disable-wayland" @@ -33,9 +33,6 @@ index ec19aa447..1c308d511 100644 +ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland" +ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland" + - # disable Wayland on legacy QXL virtual machines - ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", RUN+="@libexecdir@/gdm-disable-wayland" - # disable Wayland when using the proprietary nvidia driver DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland" + @@ -43,5 +40,5 @@ index ec19aa447..1c308d511 100644 +SUBSYSTEM=="drm", KERNEL=="card[1-9]*", RUN+="@libexecdir@/gdm-disable-wayland" + -- -2.18.1 +2.21.0 diff --git a/SOURCES/0001-data-enable-wayland-on-cirrus.patch b/SOURCES/0001-data-enable-wayland-on-cirrus.patch new file mode 100644 index 0000000..7442200 --- /dev/null +++ b/SOURCES/0001-data-enable-wayland-on-cirrus.patch @@ -0,0 +1,44 @@ +From 7d9b41f1d82589999f8c89ed3bcc4eec6cee4978 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 6 Dec 2019 13:59:43 -0500 +Subject: [PATCH] data: enable wayland on cirrus + +cirrus in the 5.2 kernel was substantially rewritten and is more wayland +ready. + +This commit reenables wayland on cirrus. +--- + data/61-gdm.rules.in | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in +index e3631740d..fc2e3315c 100644 +--- a/data/61-gdm.rules.in ++++ b/data/61-gdm.rules.in +@@ -1,23 +1,20 @@ +-# disable Wayland on Cirrus chipsets +-ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="@libexecdir@/gdm-disable-wayland" +- + # disable Wayland on Matrox chipsets + ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-disable-wayland" + + # disable Wayland on aspeed chipsets + ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland" + + # disable Wayland when using the proprietary nvidia driver + DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland" + + # disable Wayland on hybrid graphics setups for now + SUBSYSTEM=="drm", KERNEL=="card[1-9]*", RUN+="@libexecdir@/gdm-disable-wayland" + +-- +2.21.0 + diff --git a/SOURCES/0001-data-only-disable-wayland-on-passthrough-virt-setups.patch b/SOURCES/0001-data-only-disable-wayland-on-passthrough-virt-setups.patch new file mode 100644 index 0000000..24a222f --- /dev/null +++ b/SOURCES/0001-data-only-disable-wayland-on-passthrough-virt-setups.patch @@ -0,0 +1,55 @@ +From ab9510df0b5f7bc29662804991729c6d6ee38b70 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 12 Dec 2019 16:56:16 -0500 +Subject: [PATCH] data: only disable wayland on passthrough virt setups + +at the moment we disable wayland on all hybrid graphics setups, +but most hybrid graphics setups work fine. + +The case we really care about is passthrough virt. in that case, +wayland is a bad idea because: +1) kernel crashes +2) mutter provides no way to disable one of the cards, and will +always use one as a secondary gpu + +This commit forces xorg in passthrough setups so the user can use +an xorg.conf to turn one of the cards off. +--- + data/61-gdm.rules.in | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in +index fc2e3315c..f971224cf 100644 +--- a/data/61-gdm.rules.in ++++ b/data/61-gdm.rules.in +@@ -1,20 +1,25 @@ + # disable Wayland on Matrox chipsets + ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-disable-wayland" + + # disable Wayland on aspeed chipsets + ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland" + ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland" + + # disable Wayland when using the proprietary nvidia driver + DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland" + +-# disable Wayland on hybrid graphics setups for now +-SUBSYSTEM=="drm", KERNEL=="card[1-9]*", RUN+="@libexecdir@/gdm-disable-wayland" ++# disable Wayland on passthrough graphics setups for now (assumes passthrough if ++# there is more than one card, and one of the cards is virt: cirrus, bochs, qxl) ++ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", ENV{GDM_HAS_VIRTUAL_GPU}="1" ++ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", ENV{GDM_HAS_VIRTUAL_GPU}="1" ++ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", ENV{GDM_HAS_VIRTUAL_GPU}="1" ++ ++SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_VIRTUAL_GPU}=="1", RUN+="@libexecdir@/gdm-disable-wayland" + +-- +2.21.0 + diff --git a/SOURCES/0001-display-ask-accountservice-if-there-are-users-rather.patch b/SOURCES/0001-display-ask-accountservice-if-there-are-users-rather.patch new file mode 100644 index 0000000..cd35a63 --- /dev/null +++ b/SOURCES/0001-display-ask-accountservice-if-there-are-users-rather.patch @@ -0,0 +1,269 @@ +From 781e865705b0c134271c9ec21655cd5d8ce37fec Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sat, 14 Dec 2019 13:50:53 -0500 +Subject: [PATCH] display: ask accountservice if there are users rather than + enumerate users + +At the moment we ask accountsservice to give us the list of users just +to find out if there is a list of users. + +That's rather inefficient and might be wrong for directory server users +that have never logged in before. + +This commit changes gdm to ask accountsservice the question we really +want to know the answer to; whether or not there are users. +--- + daemon/gdm-display.c | 55 ++++++++++++++++++-------------------------- + 1 file changed, 22 insertions(+), 33 deletions(-) + +diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c +index 878be88da..875534272 100644 +--- a/daemon/gdm-display.c ++++ b/daemon/gdm-display.c +@@ -57,62 +57,60 @@ + struct GdmDisplayPrivate + { + char *id; + char *seat_id; + char *session_id; + char *session_class; + char *session_type; + + char *remote_hostname; + int x11_display_number; + char *x11_display_name; + int status; + time_t creation_time; + GTimer *server_timer; + + 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; + }; + + 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, +@@ -512,96 +510,88 @@ queue_finish (GdmDisplay *self) + if (self->priv->finish_idle_id == 0) { + self->priv->finish_idle_id = g_idle_add ((GSourceFunc)finish_idle, self); + } + } + + static void + _gdm_display_set_status (GdmDisplay *self, + int status) + { + if (status != self->priv->status) { + self->priv->status = status; + g_object_notify (G_OBJECT (self), "status"); + } + } + + static gboolean + gdm_display_real_prepare (GdmDisplay *self) + { + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + g_debug ("GdmDisplay: prepare display"); + + _gdm_display_set_status (self, GDM_DISPLAY_PREPARED); + + return TRUE; + } + + static void + look_for_existing_users_sync (GdmDisplay *self) + { +- GError *error = NULL; +- GVariant *call_result; +- GVariant *user_list; +- +- self->priv->accountsservice_proxy = g_dbus_proxy_new_sync (self->priv->connection, +- 0, NULL, +- "org.freedesktop.Accounts", +- "/org/freedesktop/Accounts", +- "org.freedesktop.Accounts", +- NULL, +- &error); +- +- if (!self->priv->accountsservice_proxy) { +- g_warning ("Failed to contact accountsservice: %s", error->message); +- goto out; +- } +- +- call_result = g_dbus_proxy_call_sync (self->priv->accountsservice_proxy, +- "ListCachedUsers", +- NULL, +- 0, ++ g_autoptr (GVariant) result = NULL; ++ g_autoptr (GVariant) result_child = NULL; ++ g_autoptr (GError) error = NULL; ++ gboolean has_no_users = FALSE; ++ ++ result = g_dbus_connection_call_sync (self->priv->connection, ++ "org.freedesktop.Accounts", ++ "/org/freedesktop/Accounts", ++ "org.freedesktop.DBus.Properties", ++ "Get", ++ g_variant_new ("(ss)", "org.freedesktop.Accounts", "HasNoUsers"), ++ G_VARIANT_TYPE ("(v)"), ++ G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + +- if (!call_result) { +- g_warning ("Failed to list cached users: %s", error->message); +- goto out; ++ if (result == NULL) { ++ g_warning ("Failed to contact accountsservice: %s", error->message); ++ return; + } + +- g_variant_get (call_result, "(@ao)", &user_list); +- self->priv->have_existing_user_accounts = g_variant_n_children (user_list) > 0; +- g_variant_unref (user_list); +- g_variant_unref (call_result); +-out: +- g_clear_error (&error); ++ g_variant_get (result, "(v)", &result_child); ++ has_no_users = g_variant_get_boolean (result_child); ++ self->priv->have_existing_user_accounts = !has_no_users; ++ ++ g_debug ("GdmDisplay: machine does %shave existing user accounts", ++ has_no_users? "not " : ""); + } + + gboolean + gdm_display_prepare (GdmDisplay *self) + { + gboolean ret; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); + + g_debug ("GdmDisplay: Preparing display: %s", self->priv->id); + + /* FIXME: we should probably do this in a more global place, + * asynchronously + */ + look_for_existing_users_sync (self); + + self->priv->doing_initial_setup = wants_initial_setup (self); + + g_object_ref (self); + ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self); + g_object_unref (self); + + return ret; + } + + gboolean + gdm_display_manage (GdmDisplay *self) + { + gboolean res; + +@@ -1332,61 +1322,60 @@ gdm_display_init (GdmDisplay *self) + + self->priv = GDM_DISPLAY_GET_PRIVATE (self); + + self->priv->creation_time = time (NULL); + self->priv->server_timer = g_timer_new (); + } + + static void + gdm_display_finalize (GObject *object) + { + GdmDisplay *self; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_DISPLAY (object)); + + self = GDM_DISPLAY (object); + + g_return_if_fail (self->priv != NULL); + + g_debug ("GdmDisplay: Finalizing display: %s", self->priv->id); + g_free (self->priv->id); + g_free (self->priv->seat_id); + g_free (self->priv->session_class); + g_free (self->priv->remote_hostname); + g_free (self->priv->x11_display_name); + g_free (self->priv->x11_cookie); + + g_clear_object (&self->priv->display_skeleton); + g_clear_object (&self->priv->object_skeleton); + g_clear_object (&self->priv->connection); +- g_clear_object (&self->priv->accountsservice_proxy); + + if (self->priv->access_file != NULL) { + g_object_unref (self->priv->access_file); + } + + if (self->priv->user_access_file != NULL) { + g_object_unref (self->priv->user_access_file); + } + + if (self->priv->server_timer != NULL) { + g_timer_destroy (self->priv->server_timer); + } + + G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object); + } + + GDBusObjectSkeleton * + gdm_display_get_object_skeleton (GdmDisplay *self) + { + return self->priv->object_skeleton; + } + + static void + on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment, + GdmDisplay *self) + { + char *session_id; + + g_debug ("GdmDisplay: Greeter session opened"); + session_id = gdm_launch_environment_get_session_id (launch_environment); +-- +2.21.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..0b1d1a2 --- /dev/null +++ b/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch @@ -0,0 +1,343 @@ +From bb58b5762272840a414f2bfe3ab59d733099a06c Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Thu, 20 Dec 2018 14:51:38 -0500 +Subject: [PATCH 1/2] manager: allow multiple xdmcp logins for the same user + +--- + common/gdm-settings-keys.h | 1 + + daemon/gdm-manager.c | 71 ++++++++++++++++++++++++++++---------- + data/gdm.schemas.in.in | 5 +++ + 3 files changed, 59 insertions(+), 18 deletions(-) + +diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h +index f0059b5cf..33676a851 100644 +--- a/common/gdm-settings-keys.h ++++ b/common/gdm-settings-keys.h +@@ -28,37 +28,38 @@ G_BEGIN_DECLS + #define GDM_KEY_USER "daemon/User" + #define GDM_KEY_GROUP "daemon/Group" + #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_WAYLAND_ENABLE "daemon/WaylandEnable" + + #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 056560b20..de7357ad5 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -594,93 +594,106 @@ get_display_and_details_for_bus_sender (GdmManager *self, + if (out_tty != NULL) { + *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); + + if (out_display != NULL) { + *out_display = display; + } + out: + 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 = activate_session_id (manager, 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 = activate_session_id (manager, 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; +@@ -1088,92 +1101,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.in b/data/gdm.schemas.in.in +index 8ad203101..003f92c63 100644 +--- a/data/gdm.schemas.in.in ++++ b/data/gdm.schemas.in.in +@@ -102,32 +102,37 @@ + + 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.21.1 + diff --git a/SOURCES/0001-manager-don-t-kill-timed-login-session-immediately-a.patch b/SOURCES/0001-manager-don-t-kill-timed-login-session-immediately-a.patch new file mode 100644 index 0000000..6a4f22b --- /dev/null +++ b/SOURCES/0001-manager-don-t-kill-timed-login-session-immediately-a.patch @@ -0,0 +1,87 @@ +From ecd37ba6d56a49dd896613f68d1e1754633b9f0c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 6 Feb 2019 16:14:52 -0500 +Subject: [PATCH 1/4] manager: don't kill timed login session immediately after + it starts + +At the moment GDM is misidentifying timed login sessions as if +they are automatic login sessions. That leads to their displays +getting killed sometimes shortly after log in. + +This commit corrects the check, so that timed login sessions aren't +treated as autologin sessions. +--- + daemon/gdm-manager.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 2118c5834..b2d0578f5 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -1841,61 +1841,62 @@ on_start_user_session (StartUserSessionOperation *operation) + NULL); + } else { + uid_t allowed_uid; + + g_object_ref (display); + if (doing_initial_setup) { + g_debug ("GdmManager: closing down initial setup display"); + gdm_display_stop_greeter_session (display); + gdm_display_unmanage (display); + gdm_display_finish (display); + + /* We can't start the user session until the finished display + * starts to respawn (since starting an X server and bringing + * one down at the same time is a no go) + */ + g_assert (self->priv->initial_login_operation == NULL); + self->priv->initial_login_operation = operation; + starting_user_session_right_away = FALSE; + } else { + g_debug ("GdmManager: session has its display server, reusing our server for another login screen"); + } + + /* The user session is going to follow the session worker + * into the new display. Untie it from this display and + * create a new session for a future user login. */ + allowed_uid = gdm_session_get_allowed_user (operation->session); + g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL); + g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL); + create_user_session_for_display (operation->manager, display, allowed_uid); + +- if (g_strcmp0 (operation->service_name, "gdm-autologin") == 0) { ++ if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) && ++ !gdm_session_client_is_connected (operation->session)) { + gboolean was_initial = FALSE; + + g_object_get (G_OBJECT (display), "is-initial", &was_initial, NULL); + + /* remove the unused prepared greeter display since we're not going + * to have a greeter */ + gdm_display_store_remove (self->priv->display_store, display); + g_object_unref (display); + + should_be_initial = was_initial; + } + + /* Give the user session a new display object for bookkeeping purposes */ + create_display_for_user_session (operation->manager, + operation->session, + session_id, + should_be_initial); + } + + if (starting_user_session_right_away) { + start_user_session (operation->manager, operation); + } + + out: + return G_SOURCE_REMOVE; + } + + static void + queue_start_user_session (GdmManager *manager, + GdmSession *session, +-- +2.21.0 + 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..df3c8bb --- /dev/null +++ b/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch @@ -0,0 +1,165 @@ +From 84b823187c8e0b23274cd1a93f4e47a2c585c75b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 5 Feb 2020 15:20:48 -0500 +Subject: [PATCH 2/2] 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 | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index a8263ba11..55637b378 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -2846,130 +2846,139 @@ 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->priv->session_pid = pid; + self->priv->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; + + g_return_if_fail (GDM_IS_SESSION (self)); + g_return_if_fail (self->priv->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->priv->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; + } + ++ if (g_strcmp0 (self->priv->display_seat_id, "seat0") != 0 && !run_launcher) { ++ run_separate_bus = TRUE; ++ } ++ + if (self->priv->selected_program == NULL) { + gboolean run_xsession_script; + + command = get_session_command (self); + + run_xsession_script = !gdm_session_bypasses_xsession (self); + + if (self->priv->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\"", + run_xsession_script? "--run-script " : "", + allow_remote_connections? "--allow-remote-connections " : "", + command); + } else { + program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"", + 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 { + if (run_launcher) { + if (is_x11) { +- program = g_strdup_printf (LIBEXECDIR "/gdm-x-session \"%s\"", +- self->priv->selected_program); ++ program = g_strdup_printf (LIBEXECDIR "/gdm-x-session \"%s\"", ++ self->priv->selected_program); + } else { + program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"", + self->priv->selected_program); + } + } else { +- if (g_strcmp0 (self->priv->display_seat_id, "seat0") != 0) { ++ if (run_separate_bus) { + program = g_strdup_printf ("dbus-run-session -- %s", + self->priv->selected_program); + } else { + program = g_strdup (self->priv->selected_program); + } + } + } + + set_up_session_environment (self); + send_environment (self, conversation); + + gdm_dbus_worker_call_start_program (conversation->worker_proxy, + program, + conversation->worker_cancellable, + (GAsyncReadyCallback) on_start_program_cb, + conversation); + g_free (program); + } + + static void + stop_all_conversations (GdmSession *self) + { + stop_all_other_conversations (self, NULL, TRUE); + } + + static void + do_reset (GdmSession *self) + { + stop_all_conversations (self); + +-- +2.21.1 + diff --git a/SOURCES/0002-manager-session-Add-some-debugging-around-starting-r.patch b/SOURCES/0002-manager-session-Add-some-debugging-around-starting-r.patch new file mode 100644 index 0000000..bb217a4 --- /dev/null +++ b/SOURCES/0002-manager-session-Add-some-debugging-around-starting-r.patch @@ -0,0 +1,1015 @@ +From d3b60b5211d804e23c663d053c5b511dede22a28 Mon Sep 17 00:00:00 2001 +From: Iain Lane +Date: Thu, 31 Jan 2019 10:52:35 +0000 +Subject: [PATCH 2/4] manager,session: Add some debugging around starting + reauthentication + +There's a bug right now dealing with timed login and reauthentication, +but it's not clear what's going on by looking at the logs. + +This commit sprinkles some more logging throughout the code, to make +the bug easier to track. +--- + daemon/gdm-manager.c | 46 ++++++++++++++++++++++++++++++++++++++------ + daemon/gdm-session.c | 25 ++++++++++++++++++++---- + 2 files changed, 61 insertions(+), 10 deletions(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index b2d0578f5..0cc06a978 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -340,77 +340,94 @@ session_unlock (GdmManager *manager, + "org.freedesktop.login1.Manager", + "UnlockSession", + g_variant_new ("(s)", ssid), + NULL, /* expected reply */ + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (reply == NULL) { + g_debug ("GdmManager: logind 'UnlockSession' %s raised:\n %s\n\n", + g_dbus_error_get_remote_error (error), error->message); + g_error_free (error); + return FALSE; + } + + g_variant_unref (reply); + + return TRUE; + } + + static GdmSession * + find_session_for_user_on_seat (GdmManager *manager, + const char *username, + const char *seat_id, + GdmSession *dont_count_session) + { + GList *node; + + for (node = manager->priv->user_sessions; node != NULL; node = node->next) { + GdmSession *candidate_session = node->data; +- const char *candidate_username, *candidate_seat_id; ++ const char *candidate_username, *candidate_seat_id, *candidate_session_id; + +- if (candidate_session == dont_count_session) ++ candidate_session_id = gdm_session_get_session_id (candidate_session); ++ ++ if (candidate_session == dont_count_session) { ++ g_debug ("GdmSession: Ignoring session %s as requested", ++ candidate_session_id); + continue; ++ } + +- if (!gdm_session_is_running (candidate_session)) ++ if (!gdm_session_is_running (candidate_session)) { ++ g_debug ("GdmSession: Ignoring session %s as it isn't running", ++ candidate_session_id); + continue; ++ } + + candidate_username = gdm_session_get_username (candidate_session); + candidate_seat_id = gdm_session_get_display_seat_id (candidate_session); + ++ g_debug ("GdmManager: Considering session %s on seat %s belonging to user %s", ++ candidate_session_id, ++ candidate_seat_id, ++ candidate_username); ++ + if (g_strcmp0 (candidate_username, username) == 0 && + g_strcmp0 (candidate_seat_id, seat_id) == 0) { ++ g_debug ("GdmManager: yes, found session %s", candidate_session_id); + return candidate_session; + } ++ ++ g_debug ("GdmManager: no, will not use session %s", candidate_session_id); + } + ++ g_debug ("GdmManager: no matching sessions found"); + return NULL; + } + + static gboolean + is_remote_session (GdmManager *self, + const char *session_id, + GError **error) + { + char *seat; + int ret; + gboolean is_remote; + + /* FIXME: The next release of logind is going to have explicit api for + * checking remoteness. + */ + seat = NULL; + ret = sd_session_get_seat (session_id, &seat); + + if (ret < 0 && ret != -ENOENT) { + g_debug ("GdmManager: Error while retrieving seat for session %s: %s", + session_id, strerror (-ret)); + } + + if (seat != NULL) { + is_remote = FALSE; + free (seat); + } else { + is_remote = TRUE; + } + +@@ -840,62 +857,66 @@ gdm_manager_handle_open_session (GdmDBusManager *manager, + if (display == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + _("No session available")); + + return TRUE; + } + + #ifdef HAVE_LIBXDMCP + if (GDM_IS_XDMCP_CHOOSER_DISPLAY (display)) { + GdmLaunchEnvironment *launch_environment; + + g_object_get (display, "launch-environment", &launch_environment, NULL); + + if (launch_environment != NULL) { + session = gdm_launch_environment_get_session (launch_environment); + } + + if (session == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + _("Chooser session unavailable")); + return TRUE; + } + } + #endif + if (session == NULL) { + session = get_user_session_for_display (display); ++ g_debug ("GdmSession: Considering session %s for username %s", ++ gdm_session_get_session_id (session), ++ gdm_session_get_username (session)); + + if (gdm_session_is_running (session)) { ++ g_debug ("GdmSession: the session is running, and therefore can't be used"); + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + _("Can only be called before user is logged in")); + return TRUE; + } + } + + allowed_user = gdm_session_get_allowed_user (session); + + if (uid != allowed_user) { + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + _("Caller not GDM")); + return TRUE; + } + + address = gdm_session_get_server_address (session); + + if (address == NULL) { + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + _("Unable to open private communication channel")); + return TRUE; + } + + gdm_dbus_manager_complete_open_session (GDM_DBUS_MANAGER (manager), + invocation, +@@ -1017,60 +1038,64 @@ open_temporary_reauthentication_channel (GdmManager *self, + char *seat_id, + char *session_id, + GPid pid, + uid_t uid, + gboolean is_remote) + { + GdmSession *session; + char **environment; + const char *display, *auth_file; + const char *address; + + /* Note we're just using a minimal environment here rather than the + * session's environment because the caller is unprivileged and the + * associated worker will be privileged */ + environment = g_get_environ (); + display = ""; + auth_file = "/dev/null"; + + session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE, + uid, + display, + NULL, + NULL, + seat_id, + auth_file, + is_remote == FALSE, + (const char * const *) + environment); + g_strfreev (environment); + ++ g_debug ("GdmSession: Created session for temporary reauthentication channel for user %d (seat %s)", ++ (int) uid, ++ seat_id); ++ + g_object_set_data_full (G_OBJECT (session), + "caller-session-id", + g_strdup (session_id), + (GDestroyNotify) + g_free); + g_object_set_data (G_OBJECT (session), + "caller-pid", + GUINT_TO_POINTER (pid)); + g_hash_table_insert (self->priv->transient_sessions, + GINT_TO_POINTER (pid), + session); + + g_signal_connect (session, + "client-connected", + G_CALLBACK (on_reauthentication_client_connected), + 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", +@@ -1096,65 +1121,67 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager + 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) { ++ 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); + gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager), + invocation, + address); + g_free (address); + } + + return TRUE; + } +@@ -2087,107 +2114,107 @@ on_session_client_ready_for_session_to_start (GdmSession *session, + if (client_is_ready) { + g_debug ("GdmManager: Will start session when ready"); + } else { + g_debug ("GdmManager: Will start session when ready and told"); + } + + waiting_to_start_user_session = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), + "waiting-to-start")); + + g_object_set_data (G_OBJECT (session), + "start-when-ready", + GINT_TO_POINTER (client_is_ready)); + + if (client_is_ready && waiting_to_start_user_session) { + start_user_session_if_ready (manager, session, service_name); + } + } + + static void + on_session_client_connected (GdmSession *session, + GCredentials *credentials, + GPid pid_of_client, + GdmManager *manager) + { + GdmDisplay *display; + char *username; + int delay; + gboolean enabled; + gboolean allow_timed_login = FALSE; + +- g_debug ("GdmManager: client connected"); ++ g_debug ("GdmManager: client with pid %d connected", (int) pid_of_client); + + display = get_display_for_user_session (session); + + if (display == NULL) { + return; + } + + if (!display_is_on_seat0 (display)) { + return; + } + + #ifdef WITH_PLYMOUTH + if (manager->priv->plymouth_is_running) { + plymouth_quit_with_transition (); + manager->priv->plymouth_is_running = FALSE; + } + #endif + + g_object_get (G_OBJECT (display), "allow-timed-login", &allow_timed_login, NULL); + + if (!allow_timed_login) { + return; + } + + enabled = get_timed_login_details (manager, &username, &delay); + + if (! enabled) { + return; + } + + gdm_session_set_timed_login_details (session, username, delay); + + g_debug ("GdmManager: Starting automatic login conversation (for timed login)"); + gdm_session_start_conversation (session, "gdm-autologin"); + + g_free (username); + + } + + static void + on_session_client_disconnected (GdmSession *session, + GCredentials *credentials, + GPid pid_of_client, + GdmManager *manager) + { +- g_debug ("GdmManager: client disconnected"); ++ g_debug ("GdmManager: client with pid %d disconnected", (int) pid_of_client); + } + + typedef struct + { + GdmManager *manager; + GdmSession *session; + guint idle_id; + } ResetSessionOperation; + + static void + destroy_reset_session_operation (ResetSessionOperation *operation) + { + g_object_set_data (G_OBJECT (operation->session), + "reset-session-operation", + NULL); + g_object_unref (operation->session); + g_slice_free (ResetSessionOperation, operation); + } + + static gboolean + on_reset_session (ResetSessionOperation *operation) + { + gdm_session_reset (operation->session); + + destroy_reset_session_operation (operation); + + return G_SOURCE_REMOVE; + } + + static void +@@ -2200,63 +2227,64 @@ queue_session_reset (GdmManager *manager, + + if (operation != NULL) { + return; + } + + operation = g_slice_new0 (ResetSessionOperation); + operation->manager = manager; + operation->session = g_object_ref (session); + operation->idle_id = g_idle_add ((GSourceFunc) on_reset_session, operation); + + g_object_set_data (G_OBJECT (session), "reset-session-operation", operation); + } + + static void + on_session_cancelled (GdmSession *session, + GdmManager *manager) + { + g_debug ("GdmManager: Session was cancelled"); + queue_session_reset (manager, session); + } + + static void + on_session_conversation_started (GdmSession *session, + const char *service_name, + GdmManager *manager) + { + GdmDisplay *display; + gboolean enabled; + char *username; + +- g_debug ("GdmManager: session conversation started for service %s", service_name); ++ g_debug ("GdmManager: session conversation started for service %s on session", service_name); + + if (g_strcmp0 (service_name, "gdm-autologin") != 0) { ++ g_debug ("GdmManager: ignoring session conversation since its not automatic login conversation"); + return; + } + + display = get_display_for_user_session (session); + + if (display == NULL) { + g_debug ("GdmManager: conversation has no associated display"); + return; + } + + if (!display_is_on_seat0 (display)) { + return; + } + + enabled = get_automatic_login_details (manager, &username); + + if (! enabled) { + return; + } + + g_debug ("GdmManager: begin auto login for user '%s'", username); + + /* service_name will be "gdm-autologin" + */ + gdm_session_setup_for_user (session, service_name, username); + + g_free (username); + } + + static void +@@ -2312,60 +2340,66 @@ create_user_session_for_display (GdmManager *manager, + char *display_auth_file = NULL; + char *display_seat_id = NULL; + char *display_id = NULL; + #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER) + char *display_session_type = NULL; + gboolean greeter_is_wayland; + #endif + + g_object_get (G_OBJECT (display), + "id", &display_id, + "x11-display-name", &display_name, + "is-local", &display_is_local, + "remote-hostname", &remote_hostname, + "x11-authority-file", &display_auth_file, + "seat-id", &display_seat_id, + #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER) + "session-type", &display_session_type, + #endif + NULL); + display_device = get_display_device (manager, display); + + session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_LOGIN, + allowed_user, + display_name, + remote_hostname, + display_device, + display_seat_id, + display_auth_file, + display_is_local, + NULL); ++ ++ g_debug ("GdmSession: Created user session for user %d on display %s (seat %s)", ++ (int) allowed_user, ++ display_id, ++ display_seat_id); ++ + g_free (display_name); + g_free (remote_hostname); + g_free (display_auth_file); + g_free (display_seat_id); + + g_signal_connect (session, + "reauthentication-started", + G_CALLBACK (on_session_reauthentication_started), + manager); + g_signal_connect (session, + "reauthenticated", + G_CALLBACK (on_session_reauthenticated), + manager); + g_signal_connect (session, + "client-ready-for-session-to-start", + G_CALLBACK (on_session_client_ready_for_session_to_start), + manager); + g_signal_connect (session, + "client-connected", + G_CALLBACK (on_session_client_connected), + manager); + g_signal_connect (session, + "client-disconnected", + G_CALLBACK (on_session_client_disconnected), + manager); + g_signal_connect (session, + "cancelled", + G_CALLBACK (on_session_cancelled), + manager); + g_signal_connect (session, +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 0f821e390..f23a83c5e 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -624,61 +624,64 @@ get_fallback_session_name (GdmSession *self) + + static const char * + get_default_session_name (GdmSession *self) + { + if (self->priv->saved_session != NULL) { + return self->priv->saved_session; + } + + return get_fallback_session_name (self); + } + + static void + gdm_session_defaults_changed (GdmSession *self) + { + + update_session_type (self); + + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_emit_default_language_name_changed (self->priv->greeter_interface, + get_default_language_name (self)); + gdm_dbus_greeter_emit_default_session_name_changed (self->priv->greeter_interface, + get_default_session_name (self)); + } + } + + void + gdm_session_select_user (GdmSession *self, + const char *text) + { + +- g_debug ("GdmSession: Setting user: '%s'", text); ++ g_debug ("GdmSession: selecting user '%s' for session '%s' (%p)", ++ text, ++ gdm_session_get_session_id (self), ++ self); + + g_free (self->priv->selected_user); + self->priv->selected_user = g_strdup (text); + + g_free (self->priv->saved_session); + self->priv->saved_session = NULL; + + g_free (self->priv->saved_session_type); + self->priv->saved_session_type = NULL; + + g_free (self->priv->saved_language); + self->priv->saved_language = NULL; + } + + static void + cancel_pending_query (GdmSessionConversation *conversation) + { + if (conversation->pending_invocation == NULL) { + return; + } + + g_debug ("GdmSession: Cancelling pending query"); + + g_dbus_method_invocation_return_dbus_error (conversation->pending_invocation, + GDM_SESSION_DBUS_ERROR_CANCEL, + "Operation cancelled"); + conversation->pending_invocation = NULL; + } + + static void +@@ -1416,117 +1419,121 @@ gdm_session_handle_client_cancel (GdmDBusUserVerifier *user_verifier_interfac + gdm_dbus_user_verifier_complete_cancel (user_verifier_interface, + invocation); + gdm_session_cancel (self); + return TRUE; + } + + static gboolean + gdm_session_handle_client_select_session (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *session, + GdmSession *self) + { + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_select_session (greeter_interface, + invocation); + } + gdm_session_select_session (self, session); + return TRUE; + } + + static gboolean + gdm_session_handle_client_select_user (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *username, + GdmSession *self) + { + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_select_user (greeter_interface, + invocation); + } ++ g_debug ("GdmSession: client selected user '%s' on session (%p)", username, self); + gdm_session_select_user (self, username); + return TRUE; + } + + static gboolean + gdm_session_handle_client_start_session_when_ready (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *service_name, + gboolean client_is_ready, + GdmSession *self) + { + + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_start_session_when_ready (greeter_interface, + invocation); + } + g_signal_emit (G_OBJECT (self), + signals [CLIENT_READY_FOR_SESSION_TO_START], + 0, + service_name, + client_is_ready); + return TRUE; + } + + static gboolean + gdm_session_handle_get_timed_login_details (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + GdmSession *self) + { + + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_get_timed_login_details (greeter_interface, + invocation, + self->priv->timed_login_username != NULL, + self->priv->timed_login_username != NULL? self->priv->timed_login_username : "", + self->priv->timed_login_delay); + if (self->priv->timed_login_username != NULL) { + gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface, + self->priv->timed_login_username, + self->priv->timed_login_delay); + } + } + return TRUE; + } + + static gboolean + gdm_session_handle_client_begin_auto_login (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *username, + GdmSession *self) + { + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_begin_auto_login (greeter_interface, + invocation); + } + +- g_debug ("GdmSession: begin auto login for user '%s'", username); ++ g_debug ("GdmSession: client requesting automatic login for user '%s' on session '%s' (%p)", ++ username, ++ gdm_session_get_session_id (self), ++ self); + + gdm_session_setup_for_user (self, "gdm-autologin", username); + + return TRUE; + } + + static void + export_user_verifier_interface (GdmSession *self, + GDBusConnection *connection) + { + GdmDBusUserVerifier *user_verifier_interface; + user_verifier_interface = GDM_DBUS_USER_VERIFIER (gdm_dbus_user_verifier_skeleton_new ()); + + g_object_set_data (G_OBJECT (connection), "gdm-session", self); + + g_signal_connect (user_verifier_interface, + "handle-enable-extensions", + G_CALLBACK (gdm_session_handle_client_enable_extensions), + connection); + g_signal_connect (user_verifier_interface, + "handle-begin-verification", + G_CALLBACK (gdm_session_handle_client_begin_verification), + self); + g_signal_connect (user_verifier_interface, + "handle-begin-verification-for-user", + G_CALLBACK (gdm_session_handle_client_begin_verification_for_user), + self); + g_signal_connect (user_verifier_interface, + "handle-answer-query", + G_CALLBACK (gdm_session_handle_client_answer_query), +@@ -1775,61 +1782,63 @@ allow_user_function (GDBusAuthObserver *observer, + { + uid_t client_uid; + GPid pid_of_client; + + client_uid = g_credentials_get_unix_user (credentials, NULL); + if (client_uid == self->priv->allowed_user) { + return TRUE; + } + + g_debug ("GdmSession: User not allowed"); + + pid_of_client = g_credentials_get_unix_pid (credentials, NULL); + g_signal_emit (G_OBJECT (self), + signals [CLIENT_REJECTED], + 0, + credentials, + (guint) + pid_of_client); + + + return FALSE; + } + + static void + setup_outside_server (GdmSession *self) + { + GDBusAuthObserver *observer; + GDBusServer *server; + GError *error = NULL; + +- g_debug ("GdmSession: Creating D-Bus server for greeters and such"); ++ g_debug ("GdmSession: Creating D-Bus server for greeters and such for session %s (%p)", ++ gdm_session_get_session_id (self), ++ self); + + observer = g_dbus_auth_observer_new (); + g_signal_connect_object (observer, + "authorize-authenticated-peer", + G_CALLBACK (allow_user_function), + self, + 0); + + server = gdm_dbus_setup_private_server (observer, &error); + g_object_unref (observer); + + if (server == NULL) { + g_warning ("Cannot create greeter D-Bus server for the session: %s", + error->message); + return; + } + + g_signal_connect_object (server, + "new-connection", + G_CALLBACK (handle_connection_from_outside), + self, + 0); + self->priv->outside_server = server; + + g_dbus_server_start (server); + + g_debug ("GdmSession: D-Bus server for greeters listening on %s", + g_dbus_server_get_client_address (self->priv->outside_server)); + } + +@@ -2160,61 +2169,61 @@ stop_conversation_now (GdmSessionConversation *conversation) + void + gdm_session_set_ignore_wayland (GdmSession *self, + gboolean ignore_wayland) + { + self->priv->ignore_wayland = ignore_wayland; + } + #endif + + gboolean + gdm_session_start_conversation (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + conversation = g_hash_table_lookup (self->priv->conversations, + service_name); + + if (conversation != NULL) { + if (!conversation->is_stopping) { + g_warning ("GdmSession: conversation %s started more than once", service_name); + return FALSE; + } + g_debug ("GdmSession: stopping old conversation %s", service_name); + gdm_session_worker_job_stop_now (conversation->job); + g_object_unref (conversation->job); + conversation->job = NULL; + } + +- g_debug ("GdmSession: starting conversation %s", service_name); ++ g_debug ("GdmSession: starting conversation %s for session (%p)", service_name, self); + + conversation = start_conversation (self, service_name); + + g_hash_table_insert (self->priv->conversations, + g_strdup (service_name), conversation); + return TRUE; + } + + void + gdm_session_stop_conversation (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + + g_return_if_fail (GDM_IS_SESSION (self)); + + g_debug ("GdmSession: stopping conversation %s", service_name); + + conversation = find_conversation_by_name (self, service_name); + + if (conversation != NULL) { + stop_conversation (conversation); + } + } + + static void + on_initialization_complete_cb (GdmDBusWorker *proxy, + GAsyncResult *res, + gpointer user_data) + { +@@ -2319,60 +2328,64 @@ initialize (GdmSession *self, + } + + g_free (extensions); + } + + void + gdm_session_setup (GdmSession *self, + const char *service_name) + { + + g_return_if_fail (GDM_IS_SESSION (self)); + + update_session_type (self); + + initialize (self, service_name, NULL, NULL); + gdm_session_defaults_changed (self); + } + + + void + gdm_session_setup_for_user (GdmSession *self, + const char *service_name, + const char *username) + { + + g_return_if_fail (GDM_IS_SESSION (self)); + g_return_if_fail (username != NULL); + + update_session_type (self); + ++ g_debug ("GdmSession: Set up service %s for username %s on session (%p)", ++ service_name, ++ username, ++ self); + gdm_session_select_user (self, username); + + self->priv->is_program_session = FALSE; + initialize (self, service_name, self->priv->selected_user, NULL); + gdm_session_defaults_changed (self); + } + + void + gdm_session_setup_for_program (GdmSession *self, + const char *service_name, + const char *username, + const char *log_file) + { + + g_return_if_fail (GDM_IS_SESSION (self)); + + self->priv->is_program_session = TRUE; + initialize (self, service_name, username, log_file); + } + + void + gdm_session_authenticate (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) { +@@ -2968,60 +2981,64 @@ gdm_session_set_timed_login_details (GdmSession *self, + + gboolean + gdm_session_is_running (GdmSession *self) + { + return self->priv->session_pid > 0; + } + + gboolean + gdm_session_client_is_connected (GdmSession *self) + { + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + return self->priv->outside_connections != NULL; + } + + uid_t + gdm_session_get_allowed_user (GdmSession *self) + { + return self->priv->allowed_user; + } + + void + gdm_session_start_reauthentication (GdmSession *session, + GPid pid_of_caller, + uid_t uid_of_caller) + { + GdmSessionConversation *conversation = session->priv->session_conversation; + + g_return_if_fail (conversation != NULL); + ++ g_debug ("GdmSession: starting reauthentication for session %s for client with pid %d", ++ conversation->session_id, ++ (int) uid_of_caller); ++ + conversation->reauth_pid_of_caller = pid_of_caller; + + gdm_dbus_worker_call_start_reauthentication (conversation->worker_proxy, + (int) pid_of_caller, + (int) uid_of_caller, + conversation->worker_cancellable, + (GAsyncReadyCallback) on_reauthentication_started_cb, + conversation); + } + + const char * + gdm_session_get_server_address (GdmSession *self) + { + g_return_val_if_fail (GDM_IS_SESSION (self), NULL); + + return g_dbus_server_get_client_address (self->priv->outside_server); + } + + const char * + gdm_session_get_username (GdmSession *self) + { + g_return_val_if_fail (GDM_IS_SESSION (self), NULL); + + return self->priv->selected_user; + } + + const char * + gdm_session_get_display_device (GdmSession *self) + { + g_return_val_if_fail (GDM_IS_SESSION (self), NULL); +-- +2.21.0 + diff --git a/SOURCES/0003-session-Don-t-allow-greeter-operations-on-an-running.patch b/SOURCES/0003-session-Don-t-allow-greeter-operations-on-an-running.patch new file mode 100644 index 0000000..cc60c6f --- /dev/null +++ b/SOURCES/0003-session-Don-t-allow-greeter-operations-on-an-running.patch @@ -0,0 +1,227 @@ +From 7b83c1dc9645cabadfeb253d7eca427f6a26d10f Mon Sep 17 00:00:00 2001 +From: Iain Lane +Date: Thu, 31 Jan 2019 17:51:52 +0000 +Subject: [PATCH 3/4] session: Don't allow greeter operations on an running + session + +If a client has a reference to a session that starts running, +refuse to allow further operations on the session. + +CVE-2019-3825 +--- + daemon/gdm-session.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 75 insertions(+) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index f23a83c5e..a8263ba11 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -1401,130 +1401,205 @@ gdm_session_handle_client_begin_verification_for_user (GdmDBusUserVerifier *u + static gboolean + gdm_session_handle_client_answer_query (GdmDBusUserVerifier *user_verifier_interface, + GDBusMethodInvocation *invocation, + const char *service_name, + const char *answer, + GdmSession *self) + { + gdm_dbus_user_verifier_complete_answer_query (user_verifier_interface, + invocation); + gdm_session_answer_query (self, service_name, answer); + return TRUE; + } + + static gboolean + gdm_session_handle_client_cancel (GdmDBusUserVerifier *user_verifier_interface, + GDBusMethodInvocation *invocation, + GdmSession *self) + { + gdm_dbus_user_verifier_complete_cancel (user_verifier_interface, + invocation); + gdm_session_cancel (self); + return TRUE; + } + + static gboolean + gdm_session_handle_client_select_session (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *session, + GdmSession *self) + { ++ if (gdm_session_is_running (self)) { ++ const char *username; ++ ++ username = gdm_session_get_username (self); ++ g_debug ("GdmSession: refusing to select session %s since it's already running (for user %s)", ++ session, ++ username); ++ g_dbus_method_invocation_return_error (invocation, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "Session already running for user %s", ++ username); ++ return TRUE; ++ } ++ + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_select_session (greeter_interface, + invocation); + } + gdm_session_select_session (self, session); + return TRUE; + } + + static gboolean + gdm_session_handle_client_select_user (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *username, + GdmSession *self) + { ++ if (gdm_session_is_running (self)) { ++ const char *session_username; ++ ++ session_username = gdm_session_get_username (self); ++ g_debug ("GdmSession: refusing to select user %s, since session (%p) already running (for user %s)", ++ username, ++ self, ++ session_username); ++ g_dbus_method_invocation_return_error (invocation, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "Session already running for user %s", ++ session_username); ++ return TRUE; ++ } ++ + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_select_user (greeter_interface, + invocation); + } + g_debug ("GdmSession: client selected user '%s' on session (%p)", username, self); + gdm_session_select_user (self, username); + return TRUE; + } + + static gboolean + gdm_session_handle_client_start_session_when_ready (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *service_name, + gboolean client_is_ready, + GdmSession *self) + { ++ if (gdm_session_is_running (self)) { ++ const char *username; ++ ++ username = gdm_session_get_username (self); ++ g_debug ("GdmSession: refusing to start session (%p), since it's already running (for user %s)", ++ self, ++ username); ++ g_dbus_method_invocation_return_error (invocation, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "Session already running for user %s", ++ username); ++ return TRUE; ++ } + + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_start_session_when_ready (greeter_interface, + invocation); + } + g_signal_emit (G_OBJECT (self), + signals [CLIENT_READY_FOR_SESSION_TO_START], + 0, + service_name, + client_is_ready); + return TRUE; + } + + static gboolean + gdm_session_handle_get_timed_login_details (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + GdmSession *self) + { ++ if (gdm_session_is_running (self)) { ++ const char *username; ++ ++ username = gdm_session_get_username (self); ++ g_debug ("GdmSession: refusing to give timed login details, session (%p) already running (for user %s)", ++ self, ++ username); ++ g_dbus_method_invocation_return_error (invocation, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "Session already running for user %s", ++ username); ++ return TRUE; ++ } + + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_get_timed_login_details (greeter_interface, + invocation, + self->priv->timed_login_username != NULL, + self->priv->timed_login_username != NULL? self->priv->timed_login_username : "", + self->priv->timed_login_delay); + if (self->priv->timed_login_username != NULL) { + gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface, + self->priv->timed_login_username, + self->priv->timed_login_delay); + } + } + return TRUE; + } + + static gboolean + gdm_session_handle_client_begin_auto_login (GdmDBusGreeter *greeter_interface, + GDBusMethodInvocation *invocation, + const char *username, + GdmSession *self) + { ++ const char *session_username; ++ ++ if (gdm_session_is_running (self)) { ++ session_username = gdm_session_get_username (self); ++ g_debug ("GdmSession: refusing auto login operation, session (%p) already running for user %s (%s requested)", ++ self, ++ session_username, ++ username); ++ g_dbus_method_invocation_return_error (invocation, ++ G_DBUS_ERROR, ++ G_DBUS_ERROR_INVALID_ARGS, ++ "Session already owned by user %s", ++ session_username); ++ return TRUE; ++ } ++ + if (self->priv->greeter_interface != NULL) { + gdm_dbus_greeter_complete_begin_auto_login (greeter_interface, + invocation); + } + + g_debug ("GdmSession: client requesting automatic login for user '%s' on session '%s' (%p)", + username, + gdm_session_get_session_id (self), + self); + + gdm_session_setup_for_user (self, "gdm-autologin", username); + + return TRUE; + } + + static void + export_user_verifier_interface (GdmSession *self, + GDBusConnection *connection) + { + GdmDBusUserVerifier *user_verifier_interface; + user_verifier_interface = GDM_DBUS_USER_VERIFIER (gdm_dbus_user_verifier_skeleton_new ()); + + g_object_set_data (G_OBJECT (connection), "gdm-session", self); + + g_signal_connect (user_verifier_interface, + "handle-enable-extensions", + G_CALLBACK (gdm_session_handle_client_enable_extensions), + connection); + g_signal_connect (user_verifier_interface, + "handle-begin-verification", +-- +2.21.0 + diff --git a/SOURCES/0004-GdmManager-Don-t-perform-timed-login-if-session-gets.patch b/SOURCES/0004-GdmManager-Don-t-perform-timed-login-if-session-gets.patch new file mode 100644 index 0000000..158e15a --- /dev/null +++ b/SOURCES/0004-GdmManager-Don-t-perform-timed-login-if-session-gets.patch @@ -0,0 +1,105 @@ +From 15a19ac7856c539aa9cfbf76997d18b0275aae35 Mon Sep 17 00:00:00 2001 +From: Iain Lane +Date: Mon, 4 Feb 2019 15:12:38 +0000 +Subject: [PATCH 4/4] GdmManager: Don't perform timed login if session gets + started + +At the moment it's possible for the login screen to initiate +a timed login operation shortly after a user successfully starts +their session. + +GDM won't complete the timed login operation, since a session is +already running, but will erroneously overwrite the username +associated with the session, misattributing the users session +to the timed login user. + +Later, attempts to log in as the timed user will instead unlock the +session for the other user, since that session is now associated +with the timed login user. + +This commit refuses timed login requests on sessions that are +already running, so the username doesn't get corrupted. + +CVE-2019-3825 + +Closes https://gitlab.gnome.org/GNOME/gdm/issues/460 +--- + daemon/gdm-manager.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 0cc06a978..056560b20 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -2116,60 +2116,68 @@ on_session_client_ready_for_session_to_start (GdmSession *session, + } else { + g_debug ("GdmManager: Will start session when ready and told"); + } + + waiting_to_start_user_session = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), + "waiting-to-start")); + + g_object_set_data (G_OBJECT (session), + "start-when-ready", + GINT_TO_POINTER (client_is_ready)); + + if (client_is_ready && waiting_to_start_user_session) { + start_user_session_if_ready (manager, session, service_name); + } + } + + static void + on_session_client_connected (GdmSession *session, + GCredentials *credentials, + GPid pid_of_client, + GdmManager *manager) + { + GdmDisplay *display; + char *username; + int delay; + gboolean enabled; + gboolean allow_timed_login = FALSE; + + g_debug ("GdmManager: client with pid %d connected", (int) pid_of_client); + ++ if (gdm_session_is_running (session)) { ++ const char *session_username; ++ session_username = gdm_session_get_username (session); ++ g_debug ("GdmManager: ignoring connection, since session already running (for user %s)", ++ session_username); ++ return; ++ } ++ + display = get_display_for_user_session (session); + + if (display == NULL) { + return; + } + + if (!display_is_on_seat0 (display)) { + return; + } + + #ifdef WITH_PLYMOUTH + if (manager->priv->plymouth_is_running) { + plymouth_quit_with_transition (); + manager->priv->plymouth_is_running = FALSE; + } + #endif + + g_object_get (G_OBJECT (display), "allow-timed-login", &allow_timed_login, NULL); + + if (!allow_timed_login) { + return; + } + + enabled = get_timed_login_details (manager, &username, &delay); + + if (! enabled) { + return; + } + + gdm_session_set_timed_login_details (session, username, delay); +-- +2.21.0 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index af6fae0..eda8f91 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -10,40 +10,54 @@ Name: gdm Epoch: 1 Version: 3.28.3 -Release: 22%{?dist} +Release: 29%{?dist} Summary: The GNOME Display Manager License: GPLv2+ URL: https://wiki.gnome.org/Projects/GDM Source0: http://download.gnome.org/sources/gdm/3.28/gdm-%{version}.tar.xz Source1: org.gnome.login-screen.gschema.override -Patch0: 0001-Honor-initial-setup-being-disabled-by-distro-install.patch +Patch00001: 0001-Honor-initial-setup-being-disabled-by-distro-install.patch -Patch11: 0001-utils-add-new-gdm-disable-wayland-binary.patch +Patch10001: 0001-utils-add-new-gdm-disable-wayland-binary.patch -Patch31: 0001-display-access-file-drop-unused-function.patch +Patch20001: 0001-display-access-file-drop-unused-function.patch -Patch41: 0001-data-disable-wayland-for-proprietary-nvidia-machines.patch -Patch42: 0001-data-disable-wayland-for-legacy-QXL-VMs.patch -Patch43: 0001-data-disable-wayland-on-server-chips-and-dual-gpu-se.patch +Patch30001: 0001-data-disable-wayland-for-proprietary-nvidia-machines.patch +Patch30002: 0001-data-disable-wayland-on-server-chips-and-dual-gpu-se.patch +Patch30003: 0001-data-enable-wayland-on-cirrus.patch +Patch30004: 0001-data-only-disable-wayland-on-passthrough-virt-setups.patch -Patch51: 0001-local-display-factory-pause-for-a-few-seconds-before.patch +Patch40001: 0001-local-display-factory-pause-for-a-few-seconds-before.patch -Patch61: 0001-manager-ensure-is-initial-is-transfered-to-autologin.patch +Patch50001: 0001-manager-ensure-is-initial-is-transfered-to-autologin.patch -Patch71: 0001-session-ensure-login-screen-over-XDMCP-connects-to-i.patch +Patch60001: 0001-session-ensure-login-screen-over-XDMCP-connects-to-i.patch -Patch81: 0001-worker-don-t-load-user-settings-for-program-sessions.patch -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 +Patch70001: 0001-worker-don-t-load-user-settings-for-program-sessions.patch +Patch70002: 0002-session-support-new-accountsservice-Session-and-Sess.patch +Patch70003: 0003-daemon-save-os-release-in-accountsservice.patch +Patch70004: 0004-daemon-handle-upgrades-from-RHEL-7.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 +Patch80001: 0001-session-worker-expose-worker-state-enum-to-type-syst.patch +Patch80002: 0002-session-worker-kill-user-sessions-when-stop-gdm-serv.patch +Patch80003: 0003-session-worker-uninitialize-pam-if-worker-is-killed.patch +Patch80004: 0004-data-reap-gdm-sessions-on-shutdown.patch -Patch9999: system-dconf.patch +# CVE-2019-3825 +Patch90001: 0001-manager-don-t-kill-timed-login-session-immediately-a.patch +Patch90002: 0002-manager-session-Add-some-debugging-around-starting-r.patch +Patch90003: 0003-session-Don-t-allow-greeter-operations-on-an-running.patch +Patch90004: 0004-GdmManager-Don-t-perform-timed-login-if-session-gets.patch + +Patch100001: 0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch +Patch100002: 0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch + +Patch110001: 0001-display-ask-accountservice-if-there-are-users-rather.patch + +Patch120001: 0001-daemon-fix-wayland-detection-when-deciding-to-bypass.patch + +Patch999999: system-dconf.patch BuildRequires: pam-devel >= 0:%{pam_version} BuildRequires: desktop-file-utils >= %{desktop_file_utils_version} @@ -343,6 +357,38 @@ fi %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Wed Feb 05 2020 Ray Strode - 3.28.3-29 +- Make GNOME work slightly better in the multiple logins case. + Related: #1710882 + +* Sun Dec 15 2019 Ray Strode - 3.28.3-28 +- Correct wayland session detection logic when deciding + whether or not to run Xsession script + Resolves: #1728330 + +* Sun Dec 15 2019 Ray Strode - 3.28.3-27 +- Don't run initial-setup for machines enrolled in IPA setup. + Resolves: #1750516 + +* Fri Dec 13 2019 Ray Strode - 3.28.3-26 +- Forward port RHEL 7 patch to allow multiple logins for the + same user with XDMCP connections. + Resolves: #1710882 + +* Thu Dec 12 2019 Ray Strode - 3.28.3-25 +- Reenable wayland on hybrid setups (except virt pass through) + Resolves: #1749960 +- Reenable wayland on qxl + Resolves: #1744452 + +* Fri Dec 06 2019 Ray Strode - 3.28.3-24 +- Reenable wayland on cirrus + Resolves: #1744527 + +* Thu Nov 21 2019 Ray Strode - 3.28.3-23 +- Correct timedlogin based screenlock bypass + Resolves: #1672829 + * 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