From 8b8f8f05025f91fb76d7669630f7387da1d64772 Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Mon, 7 Mar 2022 11:34:18 +0700 Subject: 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 0b7e8928..5b9baebc 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -1037,19 +1037,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@a{sv}^a&s)", NULL, &changed_props, &invalidated_props); -- cgit v1.2.1 From 6184c8a9a113abc963452dd3fdc91d1597385f56 Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Mon, 7 Mar 2022 12:03:15 +0700 Subject: daemon: Allow Wayland sessions on non-primary seats --- daemon/gdm-local-display-factory.c | 35 +++++++++++++---------------------- daemon/gdm-manager.c | 3 +-- daemon/gdm-session.c | 5 +---- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index 5b9baebc..b54d4042 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -758,6 +758,7 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, { gboolean seat_supports_graphics; gboolean is_seat0; + gboolean falling_back; g_auto (GStrv) session_types = NULL; const char *legacy_session_types[] = { "x11", NULL }; GdmDisplay *display = NULL; @@ -828,24 +829,16 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, } is_seat0 = g_strcmp0 (seat_id, "seat0") == 0; - if (is_seat0) { - gboolean falling_back; - 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 { - 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 @@ -907,13 +900,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 8611e2ed..b08b564a 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -1644,8 +1644,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 0b438651..ebb9213d 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -3363,11 +3363,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 -- cgit v1.2.1 From bbf55e792fbfa1a00e06af873a103f89e90ec71f Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Mon, 7 Mar 2022 12:05:07 +0700 Subject: 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 13e259c3..dd05658d 100644 --- a/daemon/gdm-session-worker.c +++ b/daemon/gdm-session-worker.c @@ -1224,10 +1224,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->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->pam_handle, PAM_TTY, tty_string); + } + if (!display_is_local) worker->password_is_required = TRUE; @@ -2340,22 +2343,24 @@ gdm_session_worker_open_session (GdmSessionWorker *worker, g_assert (worker->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED); g_assert (geteuid () == 0); - switch (worker->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->display_seat_id, "seat0") == 0) { + switch (worker->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; -- cgit v1.2.1 From 6db9468d8489cbe032c90ebcf39b85d0e7aad458 Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Mon, 7 Mar 2022 12:24:51 +0700 Subject: 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 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index b54d4042..3f5af13c 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -768,13 +768,6 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, g_debug ("GdmLocalDisplayFactory: display for seat %s requested", seat_id); - /* Ensure we don't create the same display more than once */ - display = get_display_for_seat (factory, seat_id); - if (display != NULL) { - g_debug ("GdmLocalDisplayFactory: display for %s already created", seat_id); - 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; @@ -895,6 +888,13 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested", session_types[0], seat_id); + /* Ensure we don't create the same display more than once */ + display = get_display_for_seat (factory, seat_id); + if (display != NULL) { + g_debug ("GdmLocalDisplayFactory: display for %s already created", seat_id); + return; + } + g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id); #ifdef ENABLE_USER_DISPLAY_SERVER -- cgit v1.2.1 From c9ab58ba8650881571716efe1e0e0cd2c6da2fe7 Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Mon, 7 Mar 2022 12:29:57 +0700 Subject: 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 3f5af13c..1b1d2e32 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -545,17 +545,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: -- cgit v1.2.1 From 833d4a63440c1e1f05dfabd0dc89764b3783696e Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Mon, 7 Mar 2022 12:35:20 +0700 Subject: 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 1b1d2e32..bf4782d1 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -549,7 +549,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; @@ -631,6 +632,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) @@ -745,7 +761,7 @@ get_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); return display; } -- cgit v1.2.1 From ea2b25c883055f95f027519a2e9f7c46f474fb43 Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Sat, 30 Apr 2022 10:08:16 +0700 Subject: 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 bf4782d1..e8fb4779 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -513,8 +513,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; @@ -531,8 +533,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); @@ -549,7 +554,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; @@ -595,8 +602,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 -- cgit v1.2.1