Blame SOURCES/0039-manager-do-initial-setup-post-work-in-manager-code.patch

a1b388
From c08afca0807d8820030c19a40e7590f72878c788 Mon Sep 17 00:00:00 2001
a1b388
From: Ray Strode <rstrode@redhat.com>
a1b388
Date: Thu, 6 Sep 2018 19:31:50 -0400
a1b388
Subject: [PATCH 39/51] manager: do initial-setup post work in manager code
a1b388
a1b388
Right now we do the initial-setup related post work
a1b388
when stopping the greeter, but the problem is we delay
a1b388
stopping the greeter now until after the user session
a1b388
is started.
a1b388
a1b388
That post-work needs to be done before the user session
a1b388
is started.
a1b388
a1b388
This commit moves the code to a more logical place.
a1b388
---
a1b388
 daemon/gdm-display.c | 132 -------------------------------------------
a1b388
 daemon/gdm-manager.c | 132 +++++++++++++++++++++++++++++++++++++++++++
a1b388
 2 files changed, 132 insertions(+), 132 deletions(-)
a1b388
a1b388
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
a1b388
index 875534272..1cef8c7c1 100644
a1b388
--- a/daemon/gdm-display.c
a1b388
+++ b/daemon/gdm-display.c
a1b388
@@ -22,61 +22,60 @@
a1b388
 
a1b388
 #include <stdlib.h>
a1b388
 #include <stdio.h>
a1b388
 #include <stdint.h>
a1b388
 #include <fcntl.h>
a1b388
 #include <unistd.h>
a1b388
 #include <string.h>
a1b388
 #include <signal.h>
a1b388
 #include <sys/stat.h>
a1b388
 #include <sys/types.h>
a1b388
 
a1b388
 #include <glib.h>
a1b388
 #include <glib/gi18n.h>
a1b388
 #include <glib-object.h>
a1b388
 
a1b388
 #include <xcb/xcb.h>
a1b388
 #include <X11/Xlib.h>
a1b388
 
a1b388
 #include "gdm-common.h"
a1b388
 #include "gdm-display.h"
a1b388
 #include "gdm-display-glue.h"
a1b388
 #include "gdm-display-access-file.h"
a1b388
 #include "gdm-launch-environment.h"
a1b388
 
a1b388
 #include "gdm-settings-direct.h"
a1b388
 #include "gdm-settings-keys.h"
a1b388
 
a1b388
 #include "gdm-launch-environment.h"
a1b388
 #include "gdm-dbus-util.h"
a1b388
 
a1b388
-#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
a1b388
 #define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
a1b388
 
a1b388
 #define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
a1b388
 
a1b388
 struct GdmDisplayPrivate
a1b388
 {
a1b388
         char                 *id;
a1b388
         char                 *seat_id;
a1b388
         char                 *session_id;
a1b388
         char                 *session_class;
a1b388
         char                 *session_type;
a1b388
 
a1b388
         char                 *remote_hostname;
a1b388
         int                   x11_display_number;
a1b388
         char                 *x11_display_name;
a1b388
         int                   status;
a1b388
         time_t                creation_time;
a1b388
         GTimer               *server_timer;
a1b388
 
a1b388
         char                 *x11_cookie;
a1b388
         gsize                 x11_cookie_size;
a1b388
         GdmDisplayAccessFile *access_file;
a1b388
 
a1b388
         guint                 finish_idle_id;
a1b388
 
a1b388
         xcb_connection_t     *xcb_connection;
a1b388
         int                   xcb_screen_number;
a1b388
 
a1b388
         GDBusConnection      *connection;
a1b388
         GdmDisplayAccessFile *user_access_file;
a1b388
@@ -98,131 +97,60 @@ enum {
a1b388
         PROP_0,
a1b388
         PROP_ID,
a1b388
         PROP_STATUS,
a1b388
         PROP_SEAT_ID,
a1b388
         PROP_SESSION_ID,
a1b388
         PROP_SESSION_CLASS,
a1b388
         PROP_SESSION_TYPE,
a1b388
         PROP_REMOTE_HOSTNAME,
a1b388
         PROP_X11_DISPLAY_NUMBER,
a1b388
         PROP_X11_DISPLAY_NAME,
a1b388
         PROP_X11_COOKIE,
a1b388
         PROP_X11_AUTHORITY_FILE,
a1b388
         PROP_IS_CONNECTED,
a1b388
         PROP_IS_LOCAL,
a1b388
         PROP_LAUNCH_ENVIRONMENT,
a1b388
         PROP_IS_INITIAL,
a1b388
         PROP_ALLOW_TIMED_LOGIN,
a1b388
         PROP_HAVE_EXISTING_USER_ACCOUNTS,
a1b388
         PROP_DOING_INITIAL_SETUP,
a1b388
 };
a1b388
 
a1b388
 static void     gdm_display_class_init  (GdmDisplayClass *klass);
a1b388
 static void     gdm_display_init        (GdmDisplay      *self);
a1b388
 static void     gdm_display_finalize    (GObject         *object);
a1b388
 static void     queue_finish            (GdmDisplay      *self);
a1b388
 static void     _gdm_display_set_status (GdmDisplay *self,
a1b388
                                          int         status);
a1b388
 static gboolean wants_initial_setup (GdmDisplay *self);
a1b388
 G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
a1b388
 
a1b388
-static gboolean
a1b388
-chown_file (GFile   *file,
a1b388
-            uid_t    uid,
a1b388
-            gid_t    gid,
a1b388
-            GError **error)
a1b388
-{
a1b388
-        if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
a1b388
-                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
a1b388
-                                          NULL, error)) {
a1b388
-                return FALSE;
a1b388
-        }
a1b388
-        if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
a1b388
-                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
a1b388
-                                          NULL, error)) {
a1b388
-                return FALSE;
a1b388
-        }
a1b388
-        return TRUE;
a1b388
-}
a1b388
-
a1b388
-static gboolean
a1b388
-chown_recursively (GFile   *dir,
a1b388
-                   uid_t    uid,
a1b388
-                   gid_t    gid,
a1b388
-                   GError **error)
a1b388
-{
a1b388
-        GFile *file = NULL;
a1b388
-        GFileInfo *info = NULL;
a1b388
-        GFileEnumerator *enumerator = NULL;
a1b388
-        gboolean retval = FALSE;
a1b388
-
a1b388
-        if (chown_file (dir, uid, gid, error) == FALSE) {
a1b388
-                goto out;
a1b388
-        }
a1b388
-
a1b388
-        enumerator = g_file_enumerate_children (dir,
a1b388
-                                                G_FILE_ATTRIBUTE_STANDARD_TYPE","
a1b388
-                                                G_FILE_ATTRIBUTE_STANDARD_NAME,
a1b388
-                                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
a1b388
-                                                NULL, error);
a1b388
-        if (!enumerator) {
a1b388
-                goto out;
a1b388
-        }
a1b388
-
a1b388
-        while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
a1b388
-                file = g_file_get_child (dir, g_file_info_get_name (info));
a1b388
-
a1b388
-                if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
a1b388
-                        if (chown_recursively (file, uid, gid, error) == FALSE) {
a1b388
-                                goto out;
a1b388
-                        }
a1b388
-                } else if (chown_file (file, uid, gid, error) == FALSE) {
a1b388
-                        goto out;
a1b388
-                }
a1b388
-
a1b388
-                g_clear_object (&file;;
a1b388
-                g_clear_object (&info;;
a1b388
-        }
a1b388
-
a1b388
-        if (*error) {
a1b388
-                goto out;
a1b388
-        }
a1b388
-
a1b388
-        retval = TRUE;
a1b388
-out:
a1b388
-        g_clear_object (&file;;
a1b388
-        g_clear_object (&info;;
a1b388
-        g_clear_object (&enumerator);
a1b388
-
a1b388
-        return retval;
a1b388
-}
a1b388
-
a1b388
 GQuark
a1b388
 gdm_display_error_quark (void)
a1b388
 {
a1b388
         static GQuark ret = 0;
a1b388
         if (ret == 0) {
a1b388
                 ret = g_quark_from_static_string ("gdm_display_error");
a1b388
         }
a1b388
 
a1b388
         return ret;
a1b388
 }
a1b388
 
a1b388
 time_t
a1b388
 gdm_display_get_creation_time (GdmDisplay *self)
a1b388
 {
a1b388
         g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
a1b388
 
a1b388
         return self->priv->creation_time;
a1b388
 }
a1b388
 
a1b388
 int
a1b388
 gdm_display_get_status (GdmDisplay *self)
a1b388
 {
a1b388
         g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
a1b388
 
a1b388
         return self->priv->status;
a1b388
 }
a1b388
 
a1b388
 const char *
a1b388
 gdm_display_get_session_id (GdmDisplay *self)
a1b388
 {
a1b388
@@ -1649,145 +1577,85 @@ gdm_display_start_greeter_session (GdmDisplay *self)
a1b388
                                  G_CALLBACK (on_launch_environment_session_stopped),
a1b388
                                  self, 0);
a1b388
         g_signal_connect_object (self->priv->launch_environment,
a1b388
                                  "exited",
a1b388
                                  G_CALLBACK (on_launch_environment_session_exited),
a1b388
                                  self, 0);
a1b388
         g_signal_connect_object (self->priv->launch_environment,
a1b388
                                  "died",
a1b388
                                  G_CALLBACK (on_launch_environment_session_died),
a1b388
                                  self, 0);
a1b388
 
a1b388
         if (auth_file != NULL) {
a1b388
                 g_object_set (self->priv->launch_environment,
a1b388
                               "x11-authority-file", auth_file,
a1b388
                               NULL);
a1b388
         }
a1b388
 
a1b388
         gdm_launch_environment_start (self->priv->launch_environment);
a1b388
 
a1b388
         session = gdm_launch_environment_get_session (self->priv->launch_environment);
a1b388
         g_object_set (G_OBJECT (session),
a1b388
                       "display-is-initial", self->priv->is_initial,
a1b388
                       NULL);
a1b388
 
a1b388
         g_free (display_name);
a1b388
         g_free (seat_id);
a1b388
         g_free (hostname);
a1b388
         g_free (auth_file);
a1b388
 }
a1b388
 
a1b388
-static void
a1b388
-chown_initial_setup_home_dir (void)
a1b388
-{
a1b388
-        GFile *dir;
a1b388
-        GError *error;
a1b388
-        char *gis_dir_path;
a1b388
-        char *gis_uid_path;
a1b388
-        char *gis_uid_contents;
a1b388
-        struct passwd *pwe;
a1b388
-        uid_t uid;
a1b388
-
a1b388
-        if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
a1b388
-                g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
a1b388
-                return;
a1b388
-        }
a1b388
-
a1b388
-        gis_dir_path = g_strdup (pwe->pw_dir);
a1b388
-
a1b388
-        gis_uid_path = g_build_filename (gis_dir_path,
a1b388
-                                         "gnome-initial-setup-uid",
a1b388
-                                         NULL);
a1b388
-        if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
a1b388
-                g_warning ("Unable to read %s", gis_uid_path);
a1b388
-                goto out;
a1b388
-        }
a1b388
-
a1b388
-        uid = (uid_t) atoi (gis_uid_contents);
a1b388
-        pwe = getpwuid (uid);
a1b388
-        if (uid == 0 || pwe == NULL) {
a1b388
-                g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
a1b388
-                goto out;
a1b388
-        }
a1b388
-
a1b388
-        error = NULL;
a1b388
-        dir = g_file_new_for_path (gis_dir_path);
a1b388
-        if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
a1b388
-                g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
a1b388
-                g_error_free (error);
a1b388
-        }
a1b388
-        g_object_unref (dir);
a1b388
-out:
a1b388
-        g_free (gis_uid_contents);
a1b388
-        g_free (gis_uid_path);
a1b388
-        g_free (gis_dir_path);
a1b388
-}
a1b388
-
a1b388
 void
a1b388
 gdm_display_stop_greeter_session (GdmDisplay *self)
a1b388
 {
a1b388
         GError *error = NULL;
a1b388
 
a1b388
         if (self->priv->launch_environment != NULL) {
a1b388
 
a1b388
                 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
a1b388
                                                       G_CALLBACK (on_launch_environment_session_opened),
a1b388
                                                       self);
a1b388
                 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
a1b388
                                                       G_CALLBACK (on_launch_environment_session_started),
a1b388
                                                       self);
a1b388
                 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
a1b388
                                                       G_CALLBACK (on_launch_environment_session_stopped),
a1b388
                                                       self);
a1b388
                 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
a1b388
                                                       G_CALLBACK (on_launch_environment_session_exited),
a1b388
                                                       self);
a1b388
                 g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
a1b388
                                                       G_CALLBACK (on_launch_environment_session_died),
a1b388
                                                       self);
a1b388
                 gdm_launch_environment_stop (self->priv->launch_environment);
a1b388
                 g_clear_object (&self->priv->launch_environment);
a1b388
         }
a1b388
-
a1b388
-        if (self->priv->doing_initial_setup) {
a1b388
-                chown_initial_setup_home_dir ();
a1b388
-
a1b388
-                if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
a1b388
-                                          "1",
a1b388
-                                          1,
a1b388
-                                          &error)) {
a1b388
-                        g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
a1b388
-                                   ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
a1b388
-                                   error->message);
a1b388
-                        g_clear_error (&error);
a1b388
-                }
a1b388
-        }
a1b388
 }
a1b388
 
a1b388
 static xcb_window_t
a1b388
 get_root_window (xcb_connection_t *connection,
a1b388
                  int               screen_number)
a1b388
 {
a1b388
         xcb_screen_t *screen = NULL;
a1b388
         xcb_screen_iterator_t iter;
a1b388
 
a1b388
         iter = xcb_setup_roots_iterator (xcb_get_setup (connection));
a1b388
         while (iter.rem) {
a1b388
                 if (screen_number == 0)
a1b388
                         screen = iter.data;
a1b388
                 screen_number--;
a1b388
                 xcb_screen_next (&iter);
a1b388
         }
a1b388
 
a1b388
         if (screen != NULL) {
a1b388
                 return screen->root;
a1b388
         }
a1b388
 
a1b388
         return XCB_WINDOW_NONE;
a1b388
 }
a1b388
 
a1b388
 static void
a1b388
 gdm_display_set_windowpath (GdmDisplay *self)
a1b388
 {
a1b388
         /* setting WINDOWPATH for clients */
a1b388
         xcb_intern_atom_cookie_t atom_cookie;
a1b388
         xcb_intern_atom_reply_t *atom_reply = NULL;
a1b388
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
a1b388
index 0823e8638..cf982870c 100644
a1b388
--- a/daemon/gdm-manager.c
a1b388
+++ b/daemon/gdm-manager.c
a1b388
@@ -35,60 +35,61 @@
a1b388
 #include <glib-object.h>
a1b388
 
a1b388
 #include <act/act-user-manager.h>
a1b388
 
a1b388
 #include <systemd/sd-login.h>
a1b388
 
a1b388
 #include "gdm-common.h"
a1b388
 
a1b388
 #include "gdm-dbus-util.h"
a1b388
 #include "gdm-manager.h"
a1b388
 #include "gdm-manager-glue.h"
a1b388
 #include "gdm-display-store.h"
a1b388
 #include "gdm-display-factory.h"
a1b388
 #include "gdm-launch-environment.h"
a1b388
 #include "gdm-local-display.h"
a1b388
 #include "gdm-local-display-factory.h"
a1b388
 #include "gdm-session.h"
a1b388
 #include "gdm-session-record.h"
a1b388
 #include "gdm-settings-direct.h"
a1b388
 #include "gdm-settings-keys.h"
a1b388
 #include "gdm-xdmcp-display-factory.h"
a1b388
 #include "gdm-xdmcp-chooser-display.h"
a1b388
 
a1b388
 #define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
a1b388
 
a1b388
 #define GDM_DBUS_PATH             "/org/gnome/DisplayManager"
a1b388
 #define GDM_MANAGER_PATH          GDM_DBUS_PATH "/Manager"
a1b388
 #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
a1b388
 
a1b388
 #define INITIAL_SETUP_USERNAME "gnome-initial-setup"
a1b388
+#define ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT GDM_RUN_DIR "/gdm.ran-initial-setup"
a1b388
 
a1b388
 typedef struct
a1b388
 {
a1b388
         GdmManager *manager;
a1b388
         GdmSession *session;
a1b388
         char *service_name;
a1b388
         guint idle_id;
a1b388
 } StartUserSessionOperation;
a1b388
 
a1b388
 struct GdmManagerPrivate
a1b388
 {
a1b388
         GdmDisplayStore        *display_store;
a1b388
         GdmLocalDisplayFactory *local_factory;
a1b388
 #ifdef HAVE_LIBXDMCP
a1b388
         GdmXdmcpDisplayFactory *xdmcp_factory;
a1b388
 #endif
a1b388
         GdmDisplay             *automatic_login_display;
a1b388
         GList                  *user_sessions;
a1b388
         GHashTable             *transient_sessions;
a1b388
         GHashTable             *open_reauthentication_requests;
a1b388
         gboolean                xdmcp_enabled;
a1b388
 
a1b388
         gboolean                started;
a1b388
         gboolean                show_local_greeter;
a1b388
 
a1b388
         GDBusConnection          *connection;
a1b388
         GDBusObjectManagerServer *object_manager;
a1b388
 
a1b388
 #ifdef  WITH_PLYMOUTH
a1b388
         guint                     plymouth_is_running : 1;
a1b388
@@ -1630,130 +1631,261 @@ start_user_session (GdmManager *manager,
a1b388
 
a1b388
         destroy_start_user_session_operation (operation);
a1b388
 }
a1b388
 
a1b388
 static void
a1b388
 create_display_for_user_session (GdmManager *self,
a1b388
                                  GdmSession *session,
a1b388
                                  const char *session_id)
a1b388
 {
a1b388
         GdmDisplay *display;
a1b388
         /* at the moment we only create GdmLocalDisplay objects on seat0 */
a1b388
         const char *seat_id = "seat0";
a1b388
 
a1b388
         display = gdm_local_display_new ();
a1b388
 
a1b388
         g_object_set (G_OBJECT (display),
a1b388
                       "session-class", "user",
a1b388
                       "seat-id", seat_id,
a1b388
                       "session-id", session_id,
a1b388
                       NULL);
a1b388
         gdm_display_store_add (self->priv->display_store,
a1b388
                                display);
a1b388
         g_object_set_data (G_OBJECT (session), "gdm-display", display);
a1b388
         g_object_set_data_full (G_OBJECT (display),
a1b388
                                 "gdm-user-session",
a1b388
                                 g_object_ref (session),
a1b388
                                 (GDestroyNotify)
a1b388
                                 clean_user_session);
a1b388
 }
a1b388
 
a1b388
+static gboolean
a1b388
+chown_file (GFile   *file,
a1b388
+            uid_t    uid,
a1b388
+            gid_t    gid,
a1b388
+            GError **error)
a1b388
+{
a1b388
+        if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
a1b388
+                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
a1b388
+                                          NULL, error)) {
a1b388
+                return FALSE;
a1b388
+        }
a1b388
+        if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
a1b388
+                                          G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
a1b388
+                                          NULL, error)) {
a1b388
+                return FALSE;
a1b388
+        }
a1b388
+        return TRUE;
a1b388
+}
a1b388
+
a1b388
+static gboolean
a1b388
+chown_recursively (GFile   *dir,
a1b388
+                   uid_t    uid,
a1b388
+                   gid_t    gid,
a1b388
+                   GError **error)
a1b388
+{
a1b388
+        GFile *file = NULL;
a1b388
+        GFileInfo *info = NULL;
a1b388
+        GFileEnumerator *enumerator = NULL;
a1b388
+        gboolean retval = FALSE;
a1b388
+
a1b388
+        if (chown_file (dir, uid, gid, error) == FALSE) {
a1b388
+                goto out;
a1b388
+        }
a1b388
+
a1b388
+        enumerator = g_file_enumerate_children (dir,
a1b388
+                                                G_FILE_ATTRIBUTE_STANDARD_TYPE","
a1b388
+                                                G_FILE_ATTRIBUTE_STANDARD_NAME,
a1b388
+                                                G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
a1b388
+                                                NULL, error);
a1b388
+        if (!enumerator) {
a1b388
+                goto out;
a1b388
+        }
a1b388
+
a1b388
+        while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
a1b388
+                file = g_file_get_child (dir, g_file_info_get_name (info));
a1b388
+
a1b388
+                if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
a1b388
+                        if (chown_recursively (file, uid, gid, error) == FALSE) {
a1b388
+                                goto out;
a1b388
+                        }
a1b388
+                } else if (chown_file (file, uid, gid, error) == FALSE) {
a1b388
+                        goto out;
a1b388
+                }
a1b388
+
a1b388
+                g_clear_object (&file;;
a1b388
+                g_clear_object (&info;;
a1b388
+        }
a1b388
+
a1b388
+        if (*error) {
a1b388
+                goto out;
a1b388
+        }
a1b388
+
a1b388
+        retval = TRUE;
a1b388
+out:
a1b388
+        g_clear_object (&file;;
a1b388
+        g_clear_object (&info;;
a1b388
+        g_clear_object (&enumerator);
a1b388
+
a1b388
+        return retval;
a1b388
+}
a1b388
+
a1b388
+static void
a1b388
+chown_initial_setup_home_dir (void)
a1b388
+{
a1b388
+        GFile *dir;
a1b388
+        GError *error;
a1b388
+        char *gis_dir_path;
a1b388
+        char *gis_uid_path;
a1b388
+        char *gis_uid_contents;
a1b388
+        struct passwd *pwe;
a1b388
+        uid_t uid;
a1b388
+
a1b388
+        if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
a1b388
+                g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
a1b388
+                return;
a1b388
+        }
a1b388
+
a1b388
+        gis_dir_path = g_strdup (pwe->pw_dir);
a1b388
+
a1b388
+        gis_uid_path = g_build_filename (gis_dir_path,
a1b388
+                                         "gnome-initial-setup-uid",
a1b388
+                                         NULL);
a1b388
+        if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
a1b388
+                g_warning ("Unable to read %s", gis_uid_path);
a1b388
+                goto out;
a1b388
+        }
a1b388
+
a1b388
+        uid = (uid_t) atoi (gis_uid_contents);
a1b388
+        pwe = getpwuid (uid);
a1b388
+        if (uid == 0 || pwe == NULL) {
a1b388
+                g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
a1b388
+                goto out;
a1b388
+        }
a1b388
+
a1b388
+        error = NULL;
a1b388
+        dir = g_file_new_for_path (gis_dir_path);
a1b388
+        if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
a1b388
+                g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
a1b388
+                g_error_free (error);
a1b388
+        }
a1b388
+        g_object_unref (dir);
a1b388
+out:
a1b388
+        g_free (gis_uid_contents);
a1b388
+        g_free (gis_uid_path);
a1b388
+        g_free (gis_dir_path);
a1b388
+}
a1b388
+
a1b388
 static gboolean
a1b388
 on_start_user_session (StartUserSessionOperation *operation)
a1b388
 {
a1b388
         GdmManager *self = operation->manager;
a1b388
         gboolean migrated;
a1b388
         gboolean fail_if_already_switched = TRUE;
a1b388
         gboolean doing_initial_setup = FALSE;
a1b388
         GdmDisplay *display;
a1b388
         const char *session_id;
a1b388
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
a1b388
         g_autofree char *display_session_type = NULL;
a1b388
 #endif
a1b388
 
a1b388
         g_debug ("GdmManager: start or jump to session");
a1b388
 
a1b388
         /* If there's already a session running, jump to it.
a1b388
          * If the only session running is the one we just opened,
a1b388
          * start a session on it.
a1b388
          */
a1b388
         migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
a1b388
 
a1b388
         g_debug ("GdmManager: migrated: %d", migrated);
a1b388
         if (migrated) {
a1b388
                 /* We don't stop the manager here because
a1b388
                    when Xorg exits it switches to the VT it was
a1b388
                    started from.  That interferes with fast
a1b388
                    user switching. */
a1b388
                 gdm_session_reset (operation->session);
a1b388
                 destroy_start_user_session_operation (operation);
a1b388
                 goto out;
a1b388
         }
a1b388
 
a1b388
         display = get_display_for_user_session (operation->session);
a1b388
 
a1b388
         g_object_get (G_OBJECT (display),
a1b388
                       "doing-initial-setup", &doing_initial_setup,
a1b388
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
a1b388
                       "session-type", &display_session_type,
a1b388
 #endif
a1b388
                       NULL);
a1b388
 
a1b388
         session_id = gdm_session_get_conversation_session_id (operation->session,
a1b388
                                                               operation->service_name);
a1b388
 
a1b388
         if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
a1b388
                 /* In this case, the greeter's display is morphing into
a1b388
                  * the user session display. Kill the greeter on this session
a1b388
                  * and let the user session follow the same display. */
a1b388
                 gdm_display_stop_greeter_session (display);
a1b388
                 g_object_set (G_OBJECT (display),
a1b388
                                 "session-class", "user",
a1b388
                                 "session-id", session_id,
a1b388
                                 NULL);
a1b388
         } else {
a1b388
                 uid_t allowed_uid;
a1b388
 
a1b388
                 g_object_ref (display);
a1b388
                 if (doing_initial_setup) {
a1b388
+                        g_autoptr(GError) error = NULL;
a1b388
+
a1b388
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
a1b388
                         if (g_strcmp0 (display_session_type, "wayland") == 0) {
a1b388
                                 g_debug ("GdmManager: closing down initial setup display in background");
a1b388
                                 g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
a1b388
                         }
a1b388
 #endif
a1b388
                         if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
a1b388
                                 g_debug ("GdmManager: closing down initial setup display");
a1b388
                                 gdm_display_stop_greeter_session (display);
a1b388
                                 gdm_display_unmanage (display);
a1b388
                                 gdm_display_finish (display);
a1b388
                         }
a1b388
+
a1b388
+                        chown_initial_setup_home_dir ();
a1b388
+
a1b388
+                        if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
a1b388
+                                                  "1",
a1b388
+                                                  1,
a1b388
+                                                  &error)) {
a1b388
+                                g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
a1b388
+                                           ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
a1b388
+                                           error->message);
a1b388
+                                g_clear_error (&error);
a1b388
+                        }
a1b388
                 } else {
a1b388
                         g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
a1b388
                 }
a1b388
 
a1b388
                 /* The user session is going to follow the session worker
a1b388
                  * into the new display. Untie it from this display and
a1b388
                  * create a new session for a future user login. */
a1b388
                 allowed_uid = gdm_session_get_allowed_user (operation->session);
a1b388
                 g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
a1b388
                 g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
a1b388
                 create_user_session_for_display (operation->manager, display, allowed_uid);
a1b388
 
a1b388
                 /* Give the user session a new display object for bookkeeping purposes */
a1b388
                 create_display_for_user_session (operation->manager,
a1b388
                                                  operation->session,
a1b388
                                                  session_id);
a1b388
 
a1b388
                 if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
a1b388
                     !gdm_session_client_is_connected (operation->session)) {
a1b388
                         /* remove the unused prepared greeter display since we're not going
a1b388
                          * to have a greeter */
a1b388
                         gdm_display_store_remove (self->priv->display_store, display);
a1b388
                         g_object_unref (display);
a1b388
 
a1b388
                         self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
a1b388
                         g_object_add_weak_pointer (G_OBJECT (self->priv->automatic_login_display), (gpointer *) &self->priv->automatic_login_display);
a1b388
                 }
a1b388
         }
a1b388
 
a1b388
         start_user_session (operation->manager, operation);
a1b388
-- 
a1b388
2.27.0
a1b388