[gdm/benzea/fix-multiple-greeter-sessions] manager: Try looking up session based on PID first



commit 7ee634509b9522b0f4fa6e54fec7b3d1a0ec4795
Author: Benjamin Berg <bberg redhat com>
Date:   Thu Jan 23 14:32:38 2020 +0100

    manager: Try looking up session based on PID first
    
    Unfortunately, GDM may be running multiple greeters, and each greeter is
    currently using the same user. So while in a lot of setups each user
    should only have one graphical session and also only one DBus session
    bus, this is not true for the gdm greeter.
    
    Lacking another solution (e.g. separate users), we need to be able to
    correctly lookup the session information for all greeter instances. We
    can do so by using sd_pid_get_session and using this information is safe
    if it does return something.
    
    See: #526

 common/gdm-common.c         | 31 +++++++++++++++++++++++++++----
 common/gdm-common.h         |  7 ++++---
 daemon/gdm-manager.c        |  2 +-
 libgdm/gdm-user-switching.c |  2 +-
 4 files changed, 33 insertions(+), 9 deletions(-)
---
diff --git a/common/gdm-common.c b/common/gdm-common.c
index 41bdb389..0cfddd06 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -497,7 +497,7 @@ goto_login_session (GDBusConnection  *connection,
          * since the data allocated is from libsystemd-logind, which
          * does not use GLib's g_malloc (). */
 
-        if (!gdm_find_display_session_for_uid (getuid (), &our_session, &local_error)) {
+        if (!gdm_find_display_session (0, getuid (), &our_session, &local_error)) {
                 g_propagate_prefixed_error (error, local_error, _("Could not identify the current session: 
"));
 
                 return FALSE;
@@ -898,16 +898,39 @@ _systemd_session_is_active (const char *session_id)
 }
 
 gboolean
-gdm_find_display_session_for_uid (const uid_t uid,
-                                  char      **out_session_id,
-                                  GError    **error)
+gdm_find_display_session (int         pid,
+                          const uid_t uid,
+                          char      **out_session_id,
+                          GError    **error)
 {
         char *local_session_id = NULL;
         g_auto(GStrv) sessions = NULL;
         int n_sessions;
+        int res;
 
         g_return_val_if_fail (out_session_id != NULL, FALSE);
 
+        /* First try to look up the session using the pid. We need this
+         * at least for the greeter, because it currently runs multiple
+         * sessions under the same user.
+         * See also commit 2b52d8933c8ab38e7ee83318da2363d00d8c5581
+         * which added an explicit dbus-run-session for all but seat0.
+         */
+        res = sd_pid_get_session (pid, &local_session_id);
+        if (res >= 0) {
+                g_debug ("Found session for PID %d, using it", pid);
+                g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current session."));
+
+                *out_session_id = g_strdup (local_session_id);
+                g_free (local_session_id);
+
+                return TRUE;
+        } else {
+                if (res != -ENODATA)
+                        g_warning ("Failed to retrieve session information for pid %d: %s",
+                                   pid, strerror (-res));
+        }
+
         g_debug ("Finding a graphical session for user %d", uid);
 
         n_sessions = sd_uid_get_sessions (uid,
diff --git a/common/gdm-common.h b/common/gdm-common.h
index 5c3fe137..3d037d68 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -51,9 +51,10 @@ int            gdm_wait_on_and_disown_pid (int pid,
 int            gdm_signal_pid            (int pid,
                                           int signal);
 
-gboolean       gdm_find_display_session_for_uid (const uid_t uid,
-                                                 char      **out_session_id,
-                                                 GError    **error);
+gboolean       gdm_find_display_session (int         pid,
+                                         const uid_t uid,
+                                         char      **out_session_id,
+                                         GError    **error);
 
 gboolean       gdm_get_pwent_for_name    (const char     *name,
                                           struct passwd **pwentp);
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 907eca37..d8dfa843 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -501,7 +501,7 @@ get_display_and_details_for_bus_sender (GdmManager       *self,
                 goto out;
         }
 
-        ret = gdm_find_display_session_for_uid (caller_uid, &session_id, &error);
+        ret = gdm_find_display_session (pid, caller_uid, &session_id, &error);
 
         if (!ret) {
                 g_debug ("GdmManager: Unable to find display session for uid %d: %s",
diff --git a/libgdm/gdm-user-switching.c b/libgdm/gdm-user-switching.c
index 3a33fcbb..20235fd8 100644
--- a/libgdm/gdm-user-switching.c
+++ b/libgdm/gdm-user-switching.c
@@ -203,7 +203,7 @@ goto_login_session (GDBusConnection  *connection,
         /* Note that we mostly use free () here, instead of g_free ()
          * since the data allocated is from libsystemd-logind, which
          * does not use GLib's g_malloc (). */
-        if (!gdm_find_display_session_for_uid (getuid (), &our_session, &local_error)) {
+        if (!gdm_find_display_session (0, getuid (), &our_session, &local_error)) {
                 g_propagate_prefixed_error (error, local_error, _("Could not identify the current session: 
"));
 
                 return FALSE;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]