[gdm/wip/laney/systemd-user] manager: Find user's current graphical session, not session of caller



commit 3c442c2dd2826430d08aec14d78b7d351eb177e0
Author: Iain Lane <iain orangesquash org uk>
Date:   Fri Jan 5 11:53:34 2018 +0000

    manager: Find user's current graphical session, not session of caller
    
    If (e.g.) gnome-shell is started as a systemd --user unit, it won't be
    part of the login session. We should instead look through all of the
    user's sessions until we find the login session, and take that as our
    session.

 common/gdm-common.c         |   54 ++++++++++++++++++++++++++++++++++++++++--
 common/gdm-common.h         |    5 ++++
 daemon/gdm-manager.c        |   18 ++++++++++----
 libgdm/Makefile.am          |    1 +
 libgdm/gdm-user-switching.c |    8 +++---
 5 files changed, 74 insertions(+), 12 deletions(-)
---
diff --git a/common/gdm-common.c b/common/gdm-common.c
index 31fc810..c5d771d 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -450,6 +450,7 @@ goto_login_session (GDBusConnection  *connection,
         char           *our_session;
         char           *session_id;
         char           *seat_id;
+        GError         *local_error = NULL;
 
         ret = FALSE;
         session_id = NULL;
@@ -462,10 +463,10 @@ goto_login_session (GDBusConnection  *connection,
          * since the data allocated is from libsystemd-logind, which
          * does not use GLib's g_malloc (). */
 
-        res = sd_pid_get_session (0, &our_session);
-        if (res < 0) {
-                g_debug ("failed to determine own session: %s", strerror (-res));
+        if (!gdm_find_display_session_for_uid (getuid (), &our_session, &local_error)) {
+                g_debug ("failed to determine own session: %s", local_error->message);
                 g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current session."));
+                g_clear_error (local_error);
 
                 return FALSE;
         }
@@ -797,3 +798,50 @@ gdm_shell_expand (const char *str,
         }
         return g_string_free (s, FALSE);
 }
+
+gboolean
+gdm_find_display_session_for_uid (const uid_t uid,
+                                  char      **out_session_id,
+                                  GError    **error)
+{
+        const gchar * const graphical_session_types[] = { "wayland", "x11", "mir", NULL };
+        g_autofree gchar *local_session_id = NULL;
+        g_autofree gchar *type = NULL;
+        int saved_errno;
+
+        g_return_val_if_fail (out_session_id != NULL, FALSE);
+
+        if ((saved_errno = sd_uid_get_display (uid, &local_session_id)) < 0) {
+                g_set_error (error,
+                             GDM_COMMON_ERROR,
+                             0,
+                             "Couldn't get display: %s (%s)",
+                             g_strerror (-saved_errno),
+                             local_session_id);
+                return FALSE;
+        }
+
+        if ((saved_errno = sd_session_get_type (local_session_id, &type)) < 0) {
+                g_set_error (error,
+                             GDM_COMMON_ERROR,
+                             0,
+                             "Couldn't get type for session '%s': %s",
+                             local_session_id,
+                             g_strerror (-saved_errno));
+                return FALSE;
+        }
+
+        if (!g_strv_contains (graphical_session_types, type)) {
+                g_set_error (error,
+                             GDM_COMMON_ERROR,
+                             0,
+                             "Session '%s' is not a graphical session (type: '%s')",
+                             local_session_id,
+                             type);
+                return FALSE;
+        }
+
+        *out_session_id = g_strdup (local_session_id);
+
+        return TRUE;
+}
diff --git a/common/gdm-common.h b/common/gdm-common.h
index 8d83a12..c568e13 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -44,6 +44,11 @@ int            gdm_wait_on_and_disown_pid (int pid,
                                            int timeout);
 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_get_pwent_for_name    (const char     *name,
                                           struct passwd **pwentp);
 
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 9f06196..585dfb5 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -516,15 +516,23 @@ get_display_and_details_for_bus_sender (GdmManager       *self,
                 goto out;
         }
 
-        session_id = get_session_id_for_pid (pid, &error);
+        ret = gdm_find_display_session_for_uid (caller_uid, &session_id, &error);
 
         if (session_id == NULL) {
-                g_debug ("GdmManager: Error while retrieving session id for sender: %s",
+                g_debug ("GdmManager: Error while retrieving session id for sender: %s, trying fallback.",
                          error->message);
-                g_error_free (error);
-                goto out;
+                g_clear_pointer (&error, g_error_free);
+
+                /* No display session for the user - we're probably the
+                 * greeter; get the session for the PID if we can */
+                session_id = get_session_id_for_pid (pid, &error);
+                if (session_id == NULL) {
+                        g_debug ("GdmManager: Error while retrieving session id for sender: %s, failing.",
+                                 error->message);
+                        goto out;
+                }
         }
- 
+
         if (out_session_id != NULL) {
                 *out_session_id = g_strdup (session_id);
         }
diff --git a/libgdm/Makefile.am b/libgdm/Makefile.am
index 2f7d7b6..ccd739b 100644
--- a/libgdm/Makefile.am
+++ b/libgdm/Makefile.am
@@ -66,6 +66,7 @@ libgdm_la_LDFLAGS =                                                    \
         $(END_OF_LIST)
 
 libgdm_la_LIBADD =                                                     \
+        $(top_builddir)/common/libgdmcommon.la                         \
         $(LIBGDM_LIBS)                                                 \
         $(SYSTEMD_LIBS)                                                \
         $(END_OF_LIST)
diff --git a/libgdm/gdm-user-switching.c b/libgdm/gdm-user-switching.c
index 3d4303e..0512939 100644
--- a/libgdm/gdm-user-switching.c
+++ b/libgdm/gdm-user-switching.c
@@ -191,6 +191,7 @@ goto_login_session (GDBusConnection  *connection,
         char           *our_session;
         char           *session_id;
         char           *seat_id;
+        GError         *local_error = NULL;
 
         ret = FALSE;
         session_id = NULL;
@@ -202,11 +203,10 @@ 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 (). */
-
-        res = sd_pid_get_session (0, &our_session);
-        if (res < 0) {
-                g_debug ("failed to determine own session: %s", strerror (-res));
+        if (!gdm_find_display_session_for_uid (getuid (), &our_session, &local_error)) {
+                g_debug ("failed to determine own session: %s", local_error->message);
                 g_set_error (error, GDM_CLIENT_ERROR, 0, _("Could not identify the current session."));
+                g_clear_error (local_error);
 
                 return FALSE;
         }


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