Bug#1031494: gdm3: Support Wayland session for all seats in multiseat setups
Tino Mettler
tino.mettler+debbugs at tikei.de
Fri Feb 17 08:20:03 GMT 2023
Package: gdm3
Version: 43.0-3
Severity: normal
Tags: patch upstream
Dear Maintainer,
in multiseat setups, gdm3 is limited to only support Wayland sessions on seat0.
There are patches for gdm3 and gnome-shell to enable Wayland sessions for all
seats in a multiseat environment. I use these patches on top of the current
Debian sid packages for some months now without any glitches. I also tested
fast user-switching as requested by the author of these patches.
The original source of the patches is here:
https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/174/commits
I'll open a separate bug for the gnome-shell part of this issue.
Regards,
Tino
-- System Information:
Debian Release: bookworm/sid
APT prefers unstable
APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386
Kernel: Linux 6.1.7 (SMP w/12 CPU threads; PREEMPT)
Kernel taint flags: TAINT_UNSIGNED_MODULE
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
Versions of packages gdm3 depends on:
ii accountsservice 22.08.8-5
ii adduser 3.131
ii dbus [default-dbus-system-bus] 1.14.6-1
ii dbus-bin 1.14.6-1
ii dbus-daemon 1.14.6-1
ii dconf-cli 0.40.0-4
ii dconf-gsettings-backend 0.40.0-4
ii debconf [debconf-2.0] 1.5.82
ii fluxbox [x-window-manager] 1.3.5-2.1
ii gir1.2-gdm-1.0 43.0-1.1
ii gnome-session [x-session-manager] 43.0-1
ii gnome-session-bin 43.0-1
ii gnome-session-common 43.0-1
ii gnome-settings-daemon 43.0-4
hi gnome-shell 43.2-1.1
ii gnome-terminal [x-terminal-emulator] 3.46.7-1
ii gsettings-desktop-schemas 43.0-1
ii libaccountsservice0 22.08.8-5
ii libaudit1 1:3.0.9-1
ii libc6 2.36-8
ii libcanberra-gtk3-0 0.30-10
ii libcanberra0 0.30-10
ii libgdk-pixbuf-2.0-0 2.42.10+dfsg-1+b1
ii libgdm1 43.0-1.1
ii libglib2.0-0 2.74.5-1
ii libglib2.0-bin 2.74.5-1
ii libgtk-3-0 3.24.36-3
ii libgudev-1.0-0 237-2
ii libkeyutils1 1.6.3-2
ii libpam-modules 1.5.2-6
ii libpam-runtime 1.5.2-6
ii libpam-systemd [logind] 252.5-2
ii libpam0g 1.5.2-6
ii librsvg2-common 2.54.5+dfsg-1
ii libselinux1 3.4-1+b5
ii libsystemd0 252.5-2
ii libx11-6 2:1.8.3-3
ii libxau6 1:1.0.9-1
ii libxcb1 1.15-1
ii libxdmcp6 1:1.1.2-3
ii lsb-base 11.6
ii mutter [x-window-manager] 43.2-6
ii polkitd 122-3
ii procps 2:4.0.2-3
ii systemd-sysv 252.5-2
ii sysvinit-utils [lsb-base] 3.06-2
ii ucf 3.0043+nmu1
ii x11-common 1:7.7+23
ii x11-xserver-utils 7.7+9+b1
ii xterm [x-terminal-emulator] 378-1
Versions of packages gdm3 recommends:
ii at-spi2-core 2.46.0-5
ii desktop-base 12.0.2
ii gnome-session [x-session-manager] 43.0-1
ii x11-xkb-utils 7.7+7
pn xserver-xephyr <none>
ii xserver-xorg 1:7.7+23
ii zenity 3.44.0-1
Versions of packages gdm3 suggests:
pn libpam-fprintd <none>
ii libpam-gnome-keyring 42.1-1+b1
pn libpam-pkcs11 <none>
pn libpam-sss <none>
pn orca <none>
-- Configuration Files:
/etc/gdm3/daemon.conf changed:
[daemon]
WaylandEnable=true
[security]
[xdmcp]
[chooser]
[debug]
Enable=true
-- debconf information:
gdm3/daemon_name: /usr/sbin/gdm3
* shared/default-x-display-manager: gdm3
-------------- next part --------------
>From 4135ba952ecb75bd53dac14ef10e6bfe1e5c1952 Mon Sep 17 00:00:00 2001
From: msizanoen1 <msizanoen at qtmlabs.xyz>
Date: Mon, 7 Mar 2022 11:34:18 +0700
Subject: [PATCH 1/7] local-display-factory: Acquire seat name properly
systemd-logind escapes the seat name prior to exposing as a DBus object.
As a result, seat names like "seat-name" may be escaped to
"seat_x2dname" when exposed as a DBus object.
Use DBus to acquire the seat name instead of using the last component of
the object path.
---
daemon/gdm-local-display-factory.c | 32 ++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 8c912cc6..8d4be1be 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -1026,19 +1026,39 @@ on_seat_properties_changed (GDBusConnection *connection,
const gchar *seat = NULL;
g_autoptr(GVariant) changed_props = NULL;
g_autoptr(GVariant) changed_prop = NULL;
+ g_autoptr(GVariant) reply = NULL;
+ g_autoptr(GVariant) reply_value = NULL;
+ g_autoptr(GError) error = NULL;
g_autofree const gchar **invalidated_props = NULL;
gboolean changed = FALSE;
int ret;
- /* Extract seat id, i.e. the last element of the object path. */
- seat = strrchr (object_path, '/');
- if (seat == NULL)
+ /* Acquire seat name */
+ reply = g_dbus_connection_call_sync (connection,
+ sender_name,
+ object_path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.login1.Seat",
+ "Id"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+
+ if (reply == NULL) {
+ g_debug ("could not acquire seat name: %s", error->message);
return;
- seat += 1;
+ }
+
+ g_variant_get (reply, "(v)", &reply_value);
- /* Valid seat IDs must start with seat, i.e. ignore "auto" */
- if (!g_str_has_prefix (seat, "seat"))
+ seat = g_variant_get_string (reply_value, NULL);
+
+ if (seat == NULL) {
+ g_debug ("seat name is not string");
return;
+ }
g_variant_get (parameters, "(s at a{sv}^a&s)", NULL, &changed_props, &invalidated_props);
-------------- next part --------------
>From 43491f85100ef7f76f1557164d92b1321cf4db97 Mon Sep 17 00:00:00 2001
From: msizanoen1 <msizanoen at qtmlabs.xyz>
Date: Mon, 7 Mar 2022 12:03:15 +0700
Subject: [PATCH 2/7] daemon: Allow Wayland sessions on non-primary seats
---
daemon/gdm-local-display-factory.c | 38 ++++++++++++------------------
daemon/gdm-manager.c | 3 +--
daemon/gdm-session.c | 5 +---
3 files changed, 17 insertions(+), 29 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 8d4be1be..369ad4ef 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -785,26 +785,20 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
seat_supports_graphics = FALSE;
}
- if (g_strcmp0 (seat_id, "seat0") == 0) {
+ if (g_strcmp0 (seat_id, "seat0") == 0)
is_seat0 = TRUE;
+ else
+ is_seat0 = FALSE;
- falling_back = factory->num_failures > 0;
- session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
+ falling_back = factory->num_failures > 0;
+ session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
- if (session_types == NULL) {
- g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable");
- seat_supports_graphics = FALSE;
- } else {
- g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
- session_types[0], falling_back? " fallback" : "");
- }
+ if (session_types == NULL) {
+ g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable");
+ seat_supports_graphics = FALSE;
} else {
- is_seat0 = FALSE;
-
- g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
- /* Force legacy X11 for all auxiliary seats */
- seat_supports_graphics = TRUE;
- session_types = g_strdupv ((char **) legacy_session_types);
+ g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
+ session_types[0], falling_back? " fallback" : "");
}
/* For seat0, we have a fallback logic to still try starting it after
@@ -896,13 +890,11 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
g_strcmp0 (preferred_display_server, "xorg") == 0) {
- if (is_seat0) {
- display = gdm_local_display_new ();
- g_object_set (G_OBJECT (display),
- "session-type", session_types[0],
- "supported-session-types", session_types,
- NULL);
- }
+ display = gdm_local_display_new ();
+ g_object_set (G_OBJECT (display),
+ "session-type", session_types[0],
+ "supported-session-types", session_types,
+ NULL);
}
#endif
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index cc61efc9..7e4b0274 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1640,8 +1640,7 @@ create_display_for_user_session (GdmManager *self,
const char *session_id)
{
GdmDisplay *display;
- /* at the moment we only create GdmLocalDisplay objects on seat0 */
- const char *seat_id = "seat0";
+ g_autofree const char *seat_id = gdm_session_get_display_seat_id (session);
display = gdm_local_display_new ();
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 4b709731..0b6f9e91 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -3336,11 +3336,8 @@ gdm_session_get_display_mode (GdmSession *self)
self->is_program_session? "yes" : "no",
self->display_seat_id);
- /* Non-seat0 sessions share their X server with their login screen
- * for now.
- */
if (g_strcmp0 (self->display_seat_id, "seat0") != 0) {
- return GDM_SESSION_DISPLAY_MODE_REUSE_VT;
+ return GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED;
}
#ifdef ENABLE_USER_DISPLAY_SERVER
-------------- next part --------------
>From 20f0a6ff9e02c952792519ffc694b864b5bee11a Mon Sep 17 00:00:00 2001
From: msizanoen1 <msizanoen at qtmlabs.xyz>
Date: Mon, 7 Mar 2022 12:05:07 +0700
Subject: [PATCH 3/7] gdm-session-worker: Do not set PAM_TTY on non-primary
seats
pam_systemd complains and refuse to create the login session
when PAM_TTY or XDG_VTNR is configured on non-primary seats.
---
daemon/gdm-session-worker.c | 43 +++++++++++++++++++++----------------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index a264ea1d..c3b8374a 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -1237,10 +1237,13 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
- /* Temporarily set PAM_TTY with the login VT,
- PAM_TTY will be reset with the users VT right before the user session is opened */
- g_snprintf (tty_string, 256, "/dev/tty%d", GDM_INITIAL_VT);
- pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
+ if (strcmp (seat_id, "seat0") == 0) {
+ /* Temporarily set PAM_TTY with the login VT,
+ PAM_TTY will be reset with the users VT right before the user session is opened */
+ g_snprintf (tty_string, 256, "/dev/tty%d", GDM_INITIAL_VT);
+ pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
+ }
+
if (!display_is_local)
worker->priv->password_is_required = TRUE;
@@ -2376,22 +2379,24 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
g_assert (geteuid () == 0);
- switch (worker->priv->display_mode) {
- case GDM_SESSION_DISPLAY_MODE_REUSE_VT:
- if (!set_up_for_current_vt (worker, error)) {
- return FALSE;
- }
- 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;
+ if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
+ switch (worker->priv->display_mode) {
+ case GDM_SESSION_DISPLAY_MODE_REUSE_VT:
+ if (!set_up_for_current_vt (worker, error)) {
+ return FALSE;
+ }
+ 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;
}
- break;
}
flags = 0;
-------------- next part --------------
>From 0403c5288e14349b735c8e9c97efe80478782c35 Mon Sep 17 00:00:00 2001
From: msizanoen1 <msizanoen at qtmlabs.xyz>
Date: Mon, 7 Mar 2022 12:24:51 +0700
Subject: [PATCH 4/7] local-display-factory: Search for greeter sessions from
logind before looking up the display from display store
On non-primary seats, GDM will look up the display from display store
and abort ensuring a display for seat. This causes the seat to have no
active session when a user logs out, instead of the login screen.
Fix this by searching for greeter sessions from logind before looking up
the display from display store.
---
daemon/gdm-local-display-factory.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 369ad4ef..5407c682 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -856,17 +856,6 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
- if (is_seat0)
- display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
- else
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
-
- /* Ensure we don't create the same display more than once */
- if (display != NULL) {
- g_debug ("GdmLocalDisplayFactory: display already created");
- return;
- }
-
/* If we already have a login window, switch to it */
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
GdmDisplay *display;
@@ -885,6 +874,17 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
}
}
+ if (is_seat0)
+ display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
+ else
+ display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
+
+ /* Ensure we don't create the same display more than once */
+ if (display != NULL) {
+ g_debug ("GdmLocalDisplayFactory: display already created");
+ return;
+ }
+
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
-------------- next part --------------
>From 64d5d6c3124e96ca5b12fd9cb7a16c1f841a97f5 Mon Sep 17 00:00:00 2001
From: msizanoen1 <msizanoen at qtmlabs.xyz>
Date: Mon, 7 Mar 2022 12:29:57 +0700
Subject: [PATCH 5/7] local-display-factory: Only ensure display for the
session's seat on logout instead of all seats
An user logging out from another seat shouldn't affect other users on
other seats. Limit ensuring a greeter session to the seat that have just
been logged out.
---
daemon/gdm-local-display-factory.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 5407c682..6e0e7701 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -546,17 +546,15 @@ on_display_status_changed (GdmDisplay *display,
}
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
- /* if this is a local display, do a full resync. Only
- * seats without displays will get created anyway. This
- * ensures we get a new login screen when the user logs out,
- * if there isn't one.
+ /* if this is a local display, ensure that we get a login
+ * screen when the user logs out.
*/
if (is_local &&
(g_strcmp0 (session_class, "greeter") != 0 || factory->active_vt == GDM_INITIAL_VT)) {
/* reset num failures */
factory->num_failures = 0;
- gdm_local_display_factory_sync_seats (factory);
+ ensure_display_for_seat (factory, seat_id);
}
break;
case GDM_DISPLAY_FAILED:
-------------- next part --------------
>From 073f58051db50a169bb5f25ecbff66d20c40fd2c Mon Sep 17 00:00:00 2001
From: msizanoen1 <msizanoen at qtmlabs.xyz>
Date: Mon, 7 Mar 2022 12:35:20 +0700
Subject: [PATCH 6/7] local-display-factory: Ensure greeter sessions on
non-primary seats are respawned on termination
Trigger ensuring a greeter session for a non-primary seat when it
terminates and only looking for displays with state of
GDM_DISPLAY_MANAGED when checking for duplicates in
ensure_display_for_seat on non-primary seats.
---
daemon/gdm-local-display-factory.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 6e0e7701..b9522e5a 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -550,7 +550,8 @@ on_display_status_changed (GdmDisplay *display,
* screen when the user logs out.
*/
if (is_local &&
- (g_strcmp0 (session_class, "greeter") != 0 || factory->active_vt == GDM_INITIAL_VT)) {
+ (g_strcmp0 (session_class, "greeter") != 0 || factory->active_vt == GDM_INITIAL_VT ||
+ g_strcmp0 (seat_id, "seat0") != 0)) {
/* reset num failures */
factory->num_failures = 0;
@@ -632,6 +633,21 @@ lookup_prepared_display_by_seat_id (const char *id,
return lookup_by_seat_id (id, display, user_data);
}
+static gboolean
+lookup_managed_display_by_seat_id (const char *id,
+ GdmDisplay *display,
+ gpointer user_data)
+{
+ int status;
+
+ status = gdm_display_get_status (display);
+
+ if (status != GDM_DISPLAY_MANAGED)
+ return FALSE;
+
+ return lookup_by_seat_id (id, display, user_data);
+}
+
#ifdef HAVE_UDEV
static gboolean
udev_is_settled (GdmLocalDisplayFactory *factory)
@@ -875,7 +891,7 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
if (is_seat0)
display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
else
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
+ display = gdm_display_store_find (store, lookup_managed_display_by_seat_id, (gpointer) seat_id);
/* Ensure we don't create the same display more than once */
if (display != NULL) {
-------------- next part --------------
>From 23a936d1471f091193814e89b8fdca849f48d498 Mon Sep 17 00:00:00 2001
From: msizanoen1 <msizanoen at qtmlabs.xyz>
Date: Sat, 30 Apr 2022 10:08:16 +0700
Subject: [PATCH 7/7] local-display-factory: Do not ensure login screen when a
background user session terminates
---
daemon/gdm-local-display-factory.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index b9522e5a..cf6c0bbd 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -514,8 +514,10 @@ on_display_status_changed (GdmDisplay *display,
int status;
int num;
char *seat_id = NULL;
+ char *seat_active_session = NULL;
char *session_type = NULL;
char *session_class = NULL;
+ char *session_id = NULL;
gboolean is_initial = TRUE;
gboolean is_local = TRUE;
@@ -532,8 +534,11 @@ on_display_status_changed (GdmDisplay *display,
"is-local", &is_local,
"session-type", &session_type,
"session-class", &session_class,
+ "session-id", &session_id,
NULL);
+ sd_seat_get_active(seat_id, &seat_active_session, NULL);
+
status = gdm_display_get_status (display);
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
@@ -550,7 +555,9 @@ on_display_status_changed (GdmDisplay *display,
* screen when the user logs out.
*/
if (is_local &&
- (g_strcmp0 (session_class, "greeter") != 0 || factory->active_vt == GDM_INITIAL_VT ||
+ ((g_strcmp0 (session_class, "greeter") != 0 &&
+ (!seat_active_session || g_strcmp0(session_id, seat_active_session) == 0)) ||
+ factory->active_vt == GDM_INITIAL_VT ||
g_strcmp0 (seat_id, "seat0") != 0)) {
/* reset num failures */
factory->num_failures = 0;
@@ -596,8 +603,10 @@ on_display_status_changed (GdmDisplay *display,
}
g_free (seat_id);
+ g_free (seat_active_session);
g_free (session_type);
g_free (session_class);
+ g_free (session_id);
}
static gboolean
More information about the pkg-gnome-maintainers
mailing list