From 1872798c5ec1dfa8400f3a92f305d992e4ff4bc5 Mon Sep 17 00:00:00 2001 From: William Jon McCann Date: Jun 23 2014 12:29:21 +0000 Subject: Wrap getpw* calls to retry in EINTR if getpwnam(username) returns NULL, errno needs to be checked for EINTR. This indicates that a signal was received while waiting for the blocking call to return, and getpwnam() should be retried. --- diff --git a/common/gdm-common.c b/common/gdm-common.c index b428f5b..1b344f3 100644 --- a/common/gdm-common.c +++ b/common/gdm-common.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,24 @@ gdm_set_fatal_warnings_if_unstable (void) } } +gboolean +gdm_get_pwent_for_name (const char *name, + struct passwd **pwentp) +{ + struct passwd *pwent; + + do { + errno = 0; + pwent = getpwnam (name); + } while (errno != EINTR); + + if (pwentp != NULL) { + *pwentp = pwent; + } + + return (pwent != NULL); +} + int gdm_wait_on_pid (int pid) { diff --git a/common/gdm-common.h b/common/gdm-common.h index 191bd70..ae7469e 100644 --- a/common/gdm-common.h +++ b/common/gdm-common.h @@ -22,6 +22,7 @@ #define _GDM_COMMON_H #include +#include #include "gdm-common-unknown-origin.h" @@ -33,6 +34,8 @@ void gdm_set_fatal_warnings_if_unstable (void); int gdm_wait_on_pid (int pid); int gdm_signal_pid (int pid, int signal); +gboolean gdm_get_pwent_for_name (const char *name, + struct passwd **pwentp); const char * gdm_make_temp_dir (char *template); diff --git a/daemon/gdm-chooser-server.c b/daemon/gdm-chooser-server.c index 2268838..fc9fd3c 100644 --- a/daemon/gdm-chooser-server.c +++ b/daemon/gdm-chooser-server.c @@ -43,6 +43,7 @@ #include #include +#include "gdm-common.h" #include "gdm-chooser-server.h" #define GDM_CHOOSER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/ChooserServer" @@ -325,7 +326,7 @@ allow_user_function (DBusConnection *connection, return FALSE; } - pwent = getpwnam (chooser_server->priv->user_name); + gdm_get_pwent_for_name (chooser_server->priv->user_name, &pwent); if (pwent == NULL) { return FALSE; } diff --git a/daemon/gdm-display-access-file.c b/daemon/gdm-display-access-file.c index 1b52f15..2fc0c78 100644 --- a/daemon/gdm-display-access-file.c +++ b/daemon/gdm-display-access-file.c @@ -209,7 +209,7 @@ _get_uid_and_gid_for_user (const char *username, g_assert (gid != NULL); errno = 0; - passwd_entry = getpwnam (username); + gdm_get_pwent_for_name (username, &passwd_entry); if (passwd_entry == NULL) { return FALSE; diff --git a/daemon/gdm-greeter-server.c b/daemon/gdm-greeter-server.c index cecce83..0c67f1e 100644 --- a/daemon/gdm-greeter-server.c +++ b/daemon/gdm-greeter-server.c @@ -43,6 +43,7 @@ #include #include +#include "gdm-common.h" #include "gdm-greeter-server.h" #define GDM_GREETER_SERVER_DBUS_PATH "/org/gnome/DisplayManager/GreeterServer" @@ -885,7 +886,7 @@ allow_user_function (DBusConnection *connection, return FALSE; } - pwent = getpwnam (greeter_server->priv->user_name); + gdm_get_pwent_for_name (greeter_server->priv->user_name, &pwent); if (pwent == NULL) { return FALSE; } diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c index 4c5f24e..ab21770 100644 --- a/daemon/gdm-server.c +++ b/daemon/gdm-server.c @@ -363,7 +363,7 @@ change_user (GdmServer *server) return; } - pwent = getpwnam (server->priv->user_name); + gdm_get_pwent_for_name (server->priv->user_name, &pwent); if (pwent == NULL) { g_warning (_("Server was to be spawned by user %s but that user doesn't exist"), server->priv->user_name); @@ -534,7 +534,7 @@ get_server_environment (GdmServer *server) if (server->priv->user_name != NULL) { struct passwd *pwent; - pwent = getpwnam (server->priv->user_name); + gdm_get_pwent_for_name (server->priv->user_name, &pwent); if (pwent->pw_dir != NULL && g_file_test (pwent->pw_dir, G_FILE_TEST_EXISTS)) { diff --git a/daemon/gdm-session-linux-auditor.c b/daemon/gdm-session-linux-auditor.c index 1542563..6c581f7 100644 --- a/daemon/gdm-session-linux-auditor.c +++ b/daemon/gdm-session-linux-auditor.c @@ -1,4 +1,4 @@ -/* gdm-session-linux-auditor.c - Object for Linux auditing of session login/logout +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2004, 2008 Sun Microsystems, Inc. * Copyright (C) 2005, 2008 Red Hat, Inc. @@ -35,6 +35,8 @@ #include +#include "gdm-common.h" + struct _GdmSessionLinuxAuditorPrivate { int audit_fd; @@ -63,7 +65,7 @@ log_user_message (GdmSessionAuditor *auditor, g_object_get (G_OBJECT (auditor), "display-device", &display_device, NULL); if (username != NULL) { - pw = getpwnam (username); + gdm_get_pwent_for_name (username, &pw); } else { username = g_strdup ("unknown"); pw = NULL; diff --git a/daemon/gdm-session-solaris-auditor.c b/daemon/gdm-session-solaris-auditor.c index badbdbb..aa7c5c9 100644 --- a/daemon/gdm-session-solaris-auditor.c +++ b/daemon/gdm-session-solaris-auditor.c @@ -1,4 +1,4 @@ -/* gdm-session-solaris-auditor.c - Object for Solaris auditing of session login/logout +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- * * Copyright (C) 2004, 2008 Sun Microsystems, Inc. * Copyright (C) 2005, 2008 Red Hat, Inc. @@ -326,7 +326,7 @@ on_username_set (GdmSessionSolarisAuditor *auditor) g_object_get (G_OBJECT (auditor), "username", &username, NULL); - passwd_entry = getpwnam (username); + gdm_get_pwent_for_name (username, &passwd_entry); if (passwd_entry != NULL) { auditor->priv->uid = passwd_entry->pw_uid; diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c index ea3662a..35a6bfe 100644 --- a/daemon/gdm-session-worker.c +++ b/daemon/gdm-session-worker.c @@ -52,6 +52,7 @@ #include "ck-connector.h" +#include "gdm-common.h" #include "gdm-session-worker.h" #include "gdm-marshal.h" @@ -210,7 +211,7 @@ open_ck_session (GdmSessionWorker *worker) is_local = FALSE; } - pwent = getpwnam (worker->priv->username); + gdm_get_pwent_for_name (worker->priv->username, &pwent); if (pwent == NULL) { goto out; } @@ -1095,7 +1096,7 @@ gdm_session_worker_cache_userfiles (GdmSessionWorker *worker) char *userfile; gboolean res; - passwd_entry = getpwnam (worker->priv->username); + gdm_get_pwent_for_name (worker->priv->username, &passwd_entry); if (passwd_entry == NULL) return; @@ -1603,6 +1604,7 @@ _lookup_passwd_info (const char *username, * passwd_entry doesn't potentially get stomped on * by a PAM module */ + again: passwd_entry = NULL; #ifdef HAVE_POSIX_GETPWNAM_R errno = getpwnam_r (username, @@ -1617,8 +1619,10 @@ _lookup_passwd_info (const char *username, (size_t) aux_buffer_size); errno = 0; #endif /* !HAVE_POSIX_GETPWNAM_R */ - - if (errno != 0) { + if (errno == EINTR) { + g_debug ("%s", g_strerror (errno)); + goto again; + } else if (errno != 0) { g_warning ("%s", g_strerror (errno)); goto out; } @@ -1982,7 +1986,7 @@ gdm_session_worker_start_user_session (GdmSessionWorker *worker, register_ck_session (worker); - passwd_entry = getpwnam (worker->priv->username); + gdm_get_pwent_for_name (worker->priv->username, &passwd_entry); #ifdef HAVE_LOGINDEVPERM /* diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c index 2b34fe4..b7d4165 100644 --- a/daemon/gdm-slave.c +++ b/daemon/gdm-slave.c @@ -204,7 +204,7 @@ get_script_environment (GdmSlave *slave, g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (username)); - pwent = getpwnam (username); + gdm_get_pwent_for_name (username, &pwent); if (pwent != NULL) { if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') { g_hash_table_insert (hash, g_strdup ("HOME"), @@ -1092,7 +1092,7 @@ gdm_slave_get_timed_login_details (GdmSlave *slave, g_free (username); if (usernamep != NULL && *usernamep != NULL) { - pwent = getpwnam (*usernamep); + gdm_get_pwent_for_name (*usernamep, &pwent); if (pwent == NULL) { g_debug ("Invalid username %s for auto/timed login", *usernamep); @@ -1126,7 +1126,7 @@ _get_uid_and_gid_for_user (const char *username, g_assert (username != NULL); errno = 0; - passwd_entry = getpwnam (username); + gdm_get_pwent_for_name (username, &passwd_entry); if (passwd_entry == NULL) { return FALSE; diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c index 04775ea..555d873 100644 --- a/daemon/gdm-welcome-session.c +++ b/daemon/gdm-welcome-session.c @@ -145,7 +145,7 @@ open_welcome_session (GdmWelcomeSession *welcome_session) session_type = "LoginWindow"; - pwent = getpwnam (welcome_session->priv->user_name); + gdm_get_pwent_for_name (welcome_session->priv->user_name, &pwent); if (pwent == NULL) { /* FIXME: */ g_warning ("Couldn't look up uid"); @@ -412,7 +412,7 @@ get_welcome_environment (GdmWelcomeSession *welcome_session) g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup ("/")); g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup ("/bin/sh")); - pwent = getpwnam (welcome_session->priv->user_name); + gdm_get_pwent_for_name (welcome_session->priv->user_name, &pwent); if (pwent != NULL) { if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') { g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup (pwent->pw_dir)); @@ -530,7 +530,7 @@ spawn_child_setup (SpawnChildData *data) return; } - pwent = getpwnam (data->user_name); + gdm_get_pwent_for_name (data->user_name, &pwent); if (pwent == NULL) { g_warning (_("User %s doesn't exist"), data->user_name); diff --git a/daemon/main.c b/daemon/main.c index 89b5bef..ddc4ca3 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -408,7 +408,7 @@ gdm_daemon_change_user (uid_t *uidp, g_debug ("Changing user:group to %s:%s", username, groupname); /* Lookup user and groupid for the GDM user */ - pwent = getpwnam (username); + gdm_get_pwent_for_name (username, &pwent); /* Set uid and gid */ if G_UNLIKELY (pwent == NULL) { diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c index 2b6bd47..b0fd88a 100644 --- a/gui/simple-greeter/gdm-user-manager.c +++ b/gui/simple-greeter/gdm-user-manager.c @@ -998,6 +998,42 @@ failed: unload_new_session (new_session); } +static gboolean +get_pwent_for_name (const char *name, + struct passwd **pwentp) +{ + struct passwd *pwent; + + do { + errno = 0; + pwent = getpwnam (name); + } while (errno != EINTR); + + if (pwentp != NULL) { + *pwentp = pwent; + } + + return (pwent != NULL); +} + +static gboolean +get_pwent_for_uid (uid_t uid, + struct passwd **pwentp) +{ + struct passwd *pwent; + + do { + errno = 0; + pwent = getpwuid (uid); + } while (errno != EINTR); + + if (pwentp != NULL) { + *pwentp = pwent; + } + + return (pwent != NULL); +} + static void maybe_add_new_session (GdmUserManagerNewSession *new_session) { @@ -1009,7 +1045,7 @@ maybe_add_new_session (GdmUserManagerNewSession *new_session) manager = GDM_USER_MANAGER (new_session->manager); errno = 0; - pwent = getpwuid (new_session->uid); + get_pwent_for_uid (new_session->uid, &pwent); if (pwent == NULL) { g_warning ("Unable to lookup user ID %d: %s", (int) new_session->uid, g_strerror (errno)); @@ -1274,8 +1310,7 @@ gdm_user_manager_get_user (GdmUserManager *manager, if (user == NULL) { struct passwd *pwent; - pwent = getpwnam (username); - + get_pwent_for_name (username, &pwent); if (pwent != NULL) { user = add_new_user_for_pwent (manager, pwent); } @@ -1293,7 +1328,7 @@ gdm_user_manager_get_user_by_uid (GdmUserManager *manager, g_return_val_if_fail (GDM_IS_USER_MANAGER (manager), NULL); - pwent = getpwuid (uid); + get_pwent_for_uid (uid, &pwent); if (pwent == NULL) { g_warning ("GdmUserManager: unable to lookup uid %d", (int)uid); return NULL; @@ -1689,7 +1724,8 @@ reload_passwd_file (GHashTable *valid_shells, g_hash_table_iter_init (&iter, current_users_by_name); while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &user)) { struct passwd *pwent; - pwent = getpwnam (name); + + get_pwent_for_name (name, &pwent); if (pwent == NULL) { continue; } @@ -1703,7 +1739,8 @@ reload_passwd_file (GHashTable *valid_shells, GSList *l; for (l = include_users; l != NULL; l = l->next) { struct passwd *pwent; - pwent = getpwnam (l->data); + + get_pwent_for_name (l->data, &pwent); if (pwent == NULL) { continue; }