--- gdm-2.27.90/configure.ac-orig	2009-09-09 14:54:29.857753980 -0500
+++ gdm-2.27.90/configure.ac	2009-09-09 14:57:48.622432991 -0500
@@ -69,6 +69,7 @@ AC_SUBST(COMMON_LIBS)
 PKG_CHECK_MODULES(DAEMON,
         dbus-glib-1 >= $DBUS_GLIB_REQUIRED_VERSION
         gobject-2.0 >= $GLIB_REQUIRED_VERSION
+        gio-2.0 >= $GLIB_REQUIRED_VERSION
 )
 AC_SUBST(DAEMON_CFLAGS)
 AC_SUBST(DAEMON_LIBS)
--- gdm-2.27.90/daemon/Makefile.am-orig	2009-09-01 16:18:53.749422308 -0500
+++ gdm-2.27.90/daemon/Makefile.am	2009-09-01 16:32:35.706210019 -0500
@@ -15,6 +15,7 @@ AM_CPPFLAGS = \
 	-DSBINDIR=\"$(sbindir)\"			\
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
 	-DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\"		\
+	-DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\"	\
 	-DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \
 	$(DISABLE_DEPRECATED_CFLAGS)			\
 	$(DAEMON_CFLAGS)				\
--- gdm-2.27.90/gui/simple-greeter/Makefile.am-orig	2009-09-01 16:31:45.087141988 -0500
+++ gdm-2.27.90/gui/simple-greeter/Makefile.am	2009-09-01 16:33:16.616810887 -0500
@@ -13,11 +13,12 @@ AM_CPPFLAGS = \
 	-DSYSCONFDIR=\""$(sysconfdir)"\"		\
 	-DLIBLOCALEDIR=\""$(prefix)/lib/locale"\"	\
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\" 	\
-	-DGLADEDIR=\""$(pkgdatadir)"\" 	\
+	-DGLADEDIR=\""$(pkgdatadir)"\"			\
 	-DLIBEXECDIR=\""$(libexecdir)"\" 		\
 	-DSBINDIR=\""$(sbindir)"\"		 	\
+	-DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\"	\
 	-DAT_SPI_REGISTRYD_DIR="\"$(AT_SPI_REGISTRYD_DIR)\""	\
-	$(DISABLE_DEPRECATED_CFLAGS)	\
+	$(DISABLE_DEPRECATED_CFLAGS)			\
 	$(GTK_CFLAGS)					\
 	$(SIMPLE_GREETER_CFLAGS)			\
 	$(NULL)
--- gdm-2.27.90/data/Makefile.am-orig	2009-09-01 15:43:11.898651333 -0500
+++ gdm-2.27.90/data/Makefile.am	2009-09-01 15:43:49.273539306 -0500
@@ -13,6 +13,7 @@ predir = $(gdmconfdir)/PreSession
 postlogindir = $(gdmconfdir)/PostLogin
 workingdir = $(GDM_WORKING_DIR)
 xauthdir = $(GDM_XAUTH_DIR)
+cachedir = $(localstatedir)/cache/gdm
 
 Xsession: $(srcdir)/Xsession.in
 	sed	-e 's,[@]XSESSION_SHELL[@],$(XSESSION_SHELL),g' \
@@ -209,6 +210,12 @@ install-data-hook: gdm.conf-custom Xsess
 		chown root:gdm $(DESTDIR)$(workingdir) || : ; \
 	fi
 
+	if test '!' -d $(DESTDIR)$(cachedir); then \
+		$(mkinstalldirs) $(DESTDIR)$(cachedir); \
+		chmod 1750 $(DESTDIR)$(cachedir); \
+		chown root:gdm $(DESTDIR)$(cachedir) || : ; \
+	fi
+
 	$(INSTALL_DATA) $(srcdir)/gconf.path $(DESTDIR)$(workingdir)/.gconf.path
 	gconftool-2 --direct --config-source=xml:merged:$(DESTDIR)$(workingdir)/.gconf.mandatory --recursive-unset /
 	gconftool-2 --direct --config-source=xml:merged:$(DESTDIR)$(workingdir)/.gconf.mandatory --load $(srcdir)/session-setup.entries
--- gdm-2.27.90/gui/simple-greeter/gdm-user.c-orig	2009-09-01 18:39:56.231363096 -0500
+++ gdm-2.27.90/gui/simple-greeter/gdm-user.c	2009-09-01 18:40:58.628521989 -0500
@@ -764,7 +764,6 @@ gdm_user_collate (GdmUser *user1,
 
 static gboolean
 check_user_file (const char *filename,
-                 uid_t       user,
                  gssize      max_file_size,
                  gboolean    relax_group,
                  gboolean    relax_other)
@@ -785,11 +784,6 @@ check_user_file (const char *filename,
                 return FALSE;
         }
 
-        /* Owned by user? */
-        if (G_UNLIKELY (fileinfo.st_uid != user)) {
-                return FALSE;
-        }
-
         /* Group not writable or relax_group? */
         if (G_UNLIKELY ((fileinfo.st_mode & S_IWGRP) == S_IWGRP && !relax_group)) {
                 return FALSE;
@@ -842,50 +836,17 @@ get_filesystem_type (const char *path)
 }
 
 static GdkPixbuf *
-render_icon_from_home (GdmUser *user,
-                       int      icon_size)
+render_icon_from_cache (GdmUser *user,
+                        int      icon_size)
 {
         GdkPixbuf  *retval;
         char       *path;
-        gboolean    is_local;
         gboolean    is_autofs;
         gboolean    res;
         char       *filesystem_type;
 
-        is_local = FALSE;
-
-        /* special case: look at parent of home to detect autofs
-           this is so we don't try to trigger an automount */
-        path = g_path_get_dirname (user->home_dir);
-        filesystem_type = get_filesystem_type (path);
-        is_autofs = (filesystem_type != NULL && strcmp (filesystem_type, "autofs") == 0);
-        g_free (filesystem_type);
-        g_free (path);
-
-        if (is_autofs) {
-                return NULL;
-        }
-
-        /* now check that home dir itself is local */
-        filesystem_type = get_filesystem_type (user->home_dir);
-        is_local = ((filesystem_type != NULL) &&
-                    (strcmp (filesystem_type, "nfs") != 0) &&
-                    (strcmp (filesystem_type, "afs") != 0) &&
-                    (strcmp (filesystem_type, "autofs") != 0) &&
-                    (strcmp (filesystem_type, "unknown") != 0) &&
-                    (strcmp (filesystem_type, "ncpfs") != 0));
-        g_free (filesystem_type);
-
-        /* only look at local home directories so we don't try to
-           read from remote (e.g. NFS) volumes */
-        if (! is_local) {
-                return NULL;
-        }
-
-        /* First, try "~/.face" */
-        path = g_build_filename (user->home_dir, ".face", NULL);
+        path = g_build_filename (GDM_CACHE_DIR, user->user_name, "face", NULL);
         res = check_user_file (path,
-                               user->uid,
                                MAX_FILE_SIZE,
                                RELAX_GROUP,
                                RELAX_OTHER);
@@ -899,76 +860,6 @@ render_icon_from_home (GdmUser *user,
         }
         g_free (path);
 
-        /* Next, try "~/.face.icon" */
-        if (retval == NULL) {
-                path = g_build_filename (user->home_dir,
-                                         ".face.icon",
-                                         NULL);
-                res = check_user_file (path,
-                                       user->uid,
-                                       MAX_FILE_SIZE,
-                                       RELAX_GROUP,
-                                       RELAX_OTHER);
-                if (res) {
-                        retval = gdk_pixbuf_new_from_file_at_size (path,
-                                                                   icon_size,
-                                                                   icon_size,
-                                                                   NULL);
-                } else {
-                        retval = NULL;
-                }
-
-                g_free (path);
-        }
-
-        /* Still nothing, try the user's personal GDM config */
-        if (retval == NULL) {
-                path = g_build_filename (user->home_dir,
-                                         ".gnome",
-                                         "gdm",
-                                         NULL);
-                res = check_user_file (path,
-                                       user->uid,
-                                       MAX_FILE_SIZE,
-                                       RELAX_GROUP,
-                                       RELAX_OTHER);
-                if (res) {
-                        GKeyFile *keyfile;
-                        char     *icon_path;
-
-                        keyfile = g_key_file_new ();
-                        g_key_file_load_from_file (keyfile,
-                                                   path,
-                                                   G_KEY_FILE_NONE,
-                                                   NULL);
-
-                        icon_path = g_key_file_get_string (keyfile,
-                                                           "face",
-                                                           "picture",
-                                                           NULL);
-                        res = check_user_file (icon_path,
-                                               user->uid,
-                                               MAX_FILE_SIZE,
-                                               RELAX_GROUP,
-                                               RELAX_OTHER);
-                        if (icon_path && res) {
-                                retval = gdk_pixbuf_new_from_file_at_size (path,
-                                                                           icon_size,
-                                                                           icon_size,
-                                                                           NULL);
-                        } else {
-                                retval = NULL;
-                        }
-
-                        g_free (icon_path);
-                        g_key_file_free (keyfile);
-                } else {
-                        retval = NULL;
-                }
-
-                g_free (path);
-        }
-
         return retval;
 }
 
@@ -1218,7 +1109,7 @@ gdm_user_render_icon (GdmUser   *user,
 
         path = NULL;
 
-        pixbuf = render_icon_from_home (user, icon_size);
+        pixbuf = render_icon_from_cache (user, icon_size);
         if (pixbuf != NULL) {
                 goto out;
         }
@@ -1226,7 +1117,6 @@ gdm_user_render_icon (GdmUser   *user,
         /* Try ${GlobalFaceDir}/${username} */
         path = g_build_filename (GLOBAL_FACEDIR, user->user_name, NULL);
         res = check_user_file (path,
-                               user->uid,
                                MAX_FILE_SIZE,
                                RELAX_GROUP,
                                RELAX_OTHER);
@@ -1249,7 +1139,6 @@ gdm_user_render_icon (GdmUser   *user,
         path = g_build_filename (GLOBAL_FACEDIR, tmp, NULL);
         g_free (tmp);
         res = check_user_file (path,
-                               user->uid,
                                MAX_FILE_SIZE,
                                RELAX_GROUP,
                                RELAX_OTHER);
--- gdm-2.27.90/daemon/gdm-session-settings.h-orig	2009-09-09 16:39:57.272533584 -0500
+++ gdm-2.27.90/daemon/gdm-session-settings.h	2009-09-09 17:06:57.345624625 -0500
@@ -54,10 +54,12 @@ GType               gdm_session_settings
 GdmSessionSettings *gdm_session_settings_new                (void);
 
 gboolean            gdm_session_settings_load               (GdmSessionSettings  *settings,
-                                                             const char          *home_directory,
+                                                             const char          *username,
                                                              GError             **error);
 gboolean            gdm_session_settings_save               (GdmSessionSettings  *settings,
                                                              const char          *home_directory,
+                                                             uid_t                uid,
+                                                             gid_t                gid,
                                                              GError             **error);
 gboolean            gdm_session_settings_is_loaded          (GdmSessionSettings  *settings);
 char               *gdm_session_settings_get_language_name  (GdmSessionSettings *settings);
--- gdm-2.27.90/daemon/gdm-session-settings.c-orig	2009-09-09 16:39:49.172024795 -0500
+++ gdm-2.27.90/daemon/gdm-session-settings.c	2009-09-09 17:12:44.313798674 -0500
@@ -267,7 +267,7 @@ gdm_session_settings_is_loaded (GdmSessi
 
 gboolean
 gdm_session_settings_load (GdmSessionSettings  *settings,
-                           const char          *home_directory,
+                           const char          *username,
                            GError             **error)
 {
         GKeyFile *key_file;
@@ -279,9 +279,10 @@ gdm_session_settings_load (GdmSessionSet
         char     *filename;
 
         g_return_val_if_fail (settings != NULL, FALSE);
-        g_return_val_if_fail (home_directory != NULL, FALSE);
+        g_return_val_if_fail (username != NULL, FALSE);
         g_return_val_if_fail (!gdm_session_settings_is_loaded (settings), FALSE);
-        filename = g_build_filename (home_directory, ".dmrc", NULL);
+
+        filename = g_build_filename (GDM_CACHE_DIR, username, "dmrc", NULL);
 
         is_loaded = FALSE;
         key_file = g_key_file_new ();
@@ -346,6 +347,8 @@ out:
 gboolean
 gdm_session_settings_save (GdmSessionSettings  *settings,
                            const char          *home_directory,
+                           uid_t                uid,
+                           gid_t                gid,
                            GError             **error)
 {
         GKeyFile *key_file;
@@ -400,6 +403,7 @@ gdm_session_settings_save (GdmSessionSet
 
         is_saved = TRUE;
 out:
+        chown (filename, uid, gid);
         g_key_file_free (key_file);
         g_free (filename);
 
--- gdm-2.27.90/daemon/gdm-session-worker.c-orig	2009-09-09 16:38:29.315448763 -0500
+++ gdm-2.27.90/daemon/gdm-session-worker.c	2009-09-09 17:27:15.863303517 -0500
@@ -49,6 +49,7 @@
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <glib-object.h>
+#include <gio/gio.h>
 #define DBUS_API_SUBJECT_TO_CHANGE
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
@@ -96,6 +97,8 @@
 
 #define MESSAGE_REPLY_TIMEOUT (10 * 60 * 1000)
 
+#define MAX_FILE_SIZE     65536
+
 enum {
         GDM_SESSION_WORKER_STATE_NONE = 0,
         GDM_SESSION_WORKER_STATE_SETUP_COMPLETE,
@@ -129,6 +132,7 @@ struct GdmSessionWorkerPrivate
         char             *hostname;
         char             *username;
         uid_t             uid;
+        gid_t             gdm_gid;
         gboolean          password_is_required;
 
         int               cred_flags;
@@ -714,39 +718,9 @@ static void
 attempt_to_load_user_settings (GdmSessionWorker *worker,
                                const char       *username)
 {
-        struct passwd *passwd_entry;
-        uid_t          old_uid;
-        gid_t          old_gid;
-
-        old_uid = geteuid ();
-        old_gid = getegid ();
-
-        passwd_entry = getpwnam (username);
-
-        /* User input isn't a valid username
-         */
-        if (passwd_entry == NULL) {
-                return;
-        }
-
-        /* We may get called late in the pam conversation after
-         * the user has already been authenticated.  This could
-         * happen if for instance, the user's home directory isn't
-         * available until late in the pam conversation so user
-         * settings couldn't get loaded until late in the conversation.
-         * If we get called late the seteuid/setgid calls here will fail,
-         * but that's okay, because we'll already be the uid/gid we want
-         * to be.
-         */
-        setegid (passwd_entry->pw_gid);
-        seteuid (passwd_entry->pw_uid);
-
         gdm_session_settings_load (worker->priv->user_settings,
-                                   passwd_entry->pw_dir,
+                                   username,
                                    NULL);
-
-        seteuid (old_uid);
-        setegid (old_gid);
 }
 
 static void
@@ -1093,6 +1067,204 @@ gdm_session_worker_stop_auditor (GdmSess
         worker->priv->auditor = NULL;
 }
 
+static gboolean
+check_user_file (const char *srcfile,
+                 const char *destfile,
+                 uid_t       uid,
+                 gssize      max_file_size)
+{
+        struct stat srcfileinfo;
+        struct stat destfileinfo;
+
+        if (max_file_size < 0) {
+                max_file_size = G_MAXSIZE;
+        }
+
+        /* Exists/Readable? */
+        if (g_stat (srcfile, &srcfileinfo) < 0) {
+                g_debug ("file does not exist");
+                return FALSE;
+        }
+
+        /* Is newer than the file already in the cache? */
+        if (destfile != NULL && g_stat (destfile, &destfileinfo) == 0) {
+                if (srcfileinfo.st_mtime <= destfileinfo.st_mtime) {
+                        g_debug ("destination file is newer");
+                        return FALSE;
+                }
+        }
+
+        /* Is a regular file */
+        if (G_UNLIKELY (!S_ISREG (srcfileinfo.st_mode))) {
+                g_debug ("file is not a regular file");
+                return FALSE;
+        }
+
+        /* Owned by user? */
+        if (G_UNLIKELY (srcfileinfo.st_uid != uid)) {
+                g_debug ("file is not owned by user");
+                return FALSE;
+        }
+
+        /* Size is kosher? */
+        if (G_UNLIKELY (srcfileinfo.st_size > max_file_size)) {
+                g_debug ("file is too large");
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+static gboolean
+gdm_cache_copy_file (GdmSessionWorker *worker,
+                     const char *userfilename,
+                     const char *cachefilename)
+{
+        gboolean res;
+
+        g_debug ("Checking if %s should be copied to cache %s", userfilename, cachefilename);
+
+        res = check_user_file (userfilename,
+                               cachefilename,
+                               worker->priv->uid,
+                               MAX_FILE_SIZE);
+
+        if (res) {
+                 GFile  *src_file;
+                 GFile  *dst_file;
+                 GError *error;
+
+                 src_file = g_file_new_for_path (userfilename);
+                 dst_file = g_file_new_for_path (cachefilename);
+
+                 error = NULL;
+                 res = g_file_copy (src_file,
+                                    dst_file, 
+                                    G_FILE_COPY_OVERWRITE |
+                                    G_FILE_COPY_NOFOLLOW_SYMLINKS,
+                                    NULL,
+                                    NULL,
+                                    NULL,
+                                    &error);
+
+                 if (! res) {
+                        g_warning ("Could not copy file to cache: %s",
+                                   error->message);
+                        g_error_free (error);
+                 } else {
+                        chown (cachefilename, 0, worker->priv->gdm_gid);
+                        g_chmod (cachefilename, S_IRWXU | S_IRGRP);
+                        g_debug ("Copy successful");
+                }
+
+                g_object_unref (src_file);
+                g_object_unref (dst_file);
+        } else {
+                g_debug ("Not copying file %s to cache",
+                         userfilename);
+        }
+        return res;
+}
+
+static void
+gdm_session_worker_cache_userfiles (GdmSessionWorker *worker)
+{
+        struct passwd *passwd_entry;
+        struct stat    statbuf;
+        char          *cachedirname;
+        char          *cachefilename;
+        char          *userfilename;
+        gboolean       res;
+        int            r;
+
+        passwd_entry = getpwnam (GDM_USERNAME);
+        worker->priv->gdm_gid = passwd_entry->pw_gid;
+
+        passwd_entry = getpwnam (worker->priv->username);
+        if (passwd_entry == NULL)
+                return;
+
+        cachedirname = g_build_filename (GDM_CACHE_DIR,
+                                         worker->priv->username,
+                                         NULL);
+
+        /* Verify user cache directory exists, create if needed */
+        r = g_stat (cachedirname, &statbuf);
+        if (r < 0) {
+                g_debug ("Making user cache directory %s", cachedirname);
+                g_mkdir (cachedirname, S_ISVTX | S_IRWXU | S_IXGRP | S_IRGRP);
+                g_chmod (cachedirname, S_ISVTX | S_IRWXU | S_IXGRP | S_IRGRP);
+                chown (cachedirname, 0, worker->priv->gdm_gid);
+        }
+
+        g_debug ("Copying user dmrc file to cache");
+        cachefilename = g_build_filename (cachedirname,
+                                          "dmrc",
+                                          NULL);
+        userfilename = g_build_filename (passwd_entry->pw_dir, ".dmrc", NULL);
+
+        gdm_cache_copy_file (worker, userfilename, cachefilename);
+        g_free (cachefilename);
+        g_free (userfilename);
+
+        g_debug ("Copying user face file to cache");
+        cachefilename = g_build_filename (cachedirname,
+                                          "face",
+                                          NULL);
+
+        /* First, try "~/.face" */
+        userfilename = g_build_filename (passwd_entry->pw_dir, ".face", NULL);
+        res = gdm_cache_copy_file (worker, userfilename, cachefilename);
+
+        /* Next, try "~/.face.icon" */
+        if (!res) {
+                g_free (userfilename);
+                userfilename = g_build_filename (passwd_entry->pw_dir,
+                                                 ".face.icon",
+                                                 NULL);
+                res = gdm_cache_copy_file (worker, userfilename, cachefilename);
+        }
+
+        /* Still nothing, try the user's personal GDM config */
+        if (!res) {
+                char *tempfilename;
+
+                tempfilename = g_build_filename (passwd_entry->pw_dir,
+                                                 ".gnome",
+                                                 "gdm",
+                                                 NULL);
+                g_debug ("Checking user's ~/.gnome/gdm file");
+                res = check_user_file (tempfilename,
+                                       NULL,
+                                       worker->priv->uid,
+                                       MAX_FILE_SIZE);
+                if (res) {
+                        GKeyFile *keyfile;
+
+                        g_free (userfilename);
+
+                        keyfile = g_key_file_new ();
+                        g_key_file_load_from_file (keyfile,
+                                                   userfilename,
+                                                   G_KEY_FILE_NONE,
+                                                   NULL);
+
+                        userfilename = g_key_file_get_string (keyfile,
+                                                              "face",
+                                                              "picture",
+                                                              NULL);
+                        res = gdm_cache_copy_file (worker, userfilename, cachefilename);
+
+                        g_key_file_free (keyfile);
+                  }
+                  g_free (tempfilename);
+        }
+
+        g_free (cachedirname);
+        g_free (cachefilename);
+        g_free (userfilename);
+}
+
 static void
 gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
                                      int               status)
@@ -1103,6 +1275,7 @@ gdm_session_worker_uninitialize_pam (Gdm
                 return;
 
         if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
+                gdm_session_worker_cache_userfiles (worker);
                 pam_close_session (worker->priv->pam_handle, 0);
                 gdm_session_auditor_report_logout (worker->priv->auditor);
 
@@ -1883,7 +2058,7 @@ out:
 
 static void
 _save_user_settings (GdmSessionWorker *worker,
-                     const char       *home_dir)
+                     struct passwd *passwd_entry)
 {
         GError *error;
 
@@ -1893,11 +2068,16 @@ _save_user_settings (GdmSessionWorker *w
 
         error = NULL;
         if (!gdm_session_settings_save (worker->priv->user_settings,
-                                        home_dir, &error)) {
+                                        passwd_entry->pw_dir,
+                                        passwd_entry->pw_uid,
+                                        passwd_entry->pw_gid,
+                                        &error)) {
                 g_warning ("could not save session and language settings: %s",
                            error->message);
                 g_error_free (error);
         }
+
+        gdm_session_worker_cache_userfiles (worker);
 }
 
 static gboolean
@@ -1959,6 +2139,8 @@ gdm_session_worker_start_user_session (G
                 char  *home_dir;
                 int    fd;
 
+                _save_user_settings (worker, passwd_entry);
+
                 if (setuid (worker->priv->uid) < 0) {
                         g_debug ("GdmSessionWorker: could not reset uid - %s", g_strerror (errno));
                         _exit (1);
@@ -1990,8 +2172,6 @@ gdm_session_worker_start_user_session (G
                 dup2 (fd, STDERR_FILENO);
                 close (fd);
 
-                _save_user_settings (worker, home_dir);
-
                 gdm_session_execute (worker->priv->arguments[0],
                                      worker->priv->arguments,
                                      environment,
