From 20c0315bbde5d0fdc72d5a5dd6dedfaf54ccae45 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 29 Jun 2016 16:22:42 -0400 Subject: [PATCH] daemon: constrain max local users to 50 Systems with tens of thousands of users don't want all those users showing up in the user list. Set a cap at an even 50, which should cover the lion's share of use cases well. Of course, if a user not in the list explicitly logs in (from Not Listed? or whatever) they get added to the list. https://bugs.freedesktop.org/show_bug.cgi?id=48177 --- src/daemon.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/daemon.c b/src/daemon.c index 2010b82..1700c8a 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -108,60 +108,64 @@ error_quark (void) return (GQuark) quark_volatile; } #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } GType error_get_type (void) { static GType etype = 0; if (etype == 0) { static const GEnumValue values[] = { ENUM_ENTRY (ERROR_FAILED, "Failed"), ENUM_ENTRY (ERROR_USER_EXISTS, "UserExists"), ENUM_ENTRY (ERROR_USER_DOES_NOT_EXIST, "UserDoesntExist"), ENUM_ENTRY (ERROR_PERMISSION_DENIED, "PermissionDenied"), ENUM_ENTRY (ERROR_NOT_SUPPORTED, "NotSupported"), { 0, 0, 0 } }; g_assert (NUM_ERRORS == G_N_ELEMENTS (values) - 1); etype = g_enum_register_static ("Error", values); } return etype; } #ifndef HAVE_FGETPWENT #include "fgetpwent.c" #endif +#ifndef MAX_LOCAL_USERS +#define MAX_LOCAL_USERS 50 +#endif + static struct passwd * entry_generator_fgetpwent (GHashTable *users, gpointer *state, struct spwd **spent) { struct passwd *pwent; struct { struct spwd spbuf; char buf[1024]; } *shadow_entry_buffers; struct { FILE *fp; GHashTable *users; } *generator_state; /* First iteration */ if (*state == NULL) { GHashTable *shadow_users = NULL; FILE *fp; struct spwd *shadow_entry; fp = fopen (PATH_SHADOW, "r"); if (fp == NULL) { g_warning ("Unable to open %s: %s", PATH_SHADOW, g_strerror (errno)); return NULL; } shadow_users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); @@ -179,67 +183,70 @@ entry_generator_fgetpwent (GHashTable *users, if (errno != EINTR) { break; } } } while (shadow_entry != NULL); fclose (fp); if (g_hash_table_size (shadow_users) == 0) { g_clear_pointer (&shadow_users, g_hash_table_unref); return NULL; } fp = fopen (PATH_PASSWD, "r"); if (fp == NULL) { g_clear_pointer (&shadow_users, g_hash_table_unref); g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno)); return NULL; } generator_state = g_malloc0 (sizeof (generator_state)); generator_state->fp = fp; generator_state->users = shadow_users; *state = generator_state; } /* Every iteration */ generator_state = *state; - pwent = fgetpwent (generator_state->fp); - if (pwent != NULL) { - shadow_entry_buffers = g_hash_table_lookup (generator_state->users, pwent->pw_name); - if (shadow_entry_buffers != NULL) { - *spent = &shadow_entry_buffers->spbuf; - return pwent; + if (g_hash_table_size (users) < MAX_LOCAL_USERS) { + pwent = fgetpwent (generator_state->fp); + if (pwent != NULL) { + shadow_entry_buffers = g_hash_table_lookup (generator_state->users, pwent->pw_name); + + if (shadow_entry_buffers != NULL) { + *spent = &shadow_entry_buffers->spbuf; + return pwent; + } } } /* Last iteration */ fclose (generator_state->fp); g_hash_table_unref (generator_state->users); g_free (generator_state); *state = NULL; return NULL; } static struct passwd * entry_generator_cachedir (GHashTable *users, gpointer *state, struct spwd **shadow_entry) { struct passwd *pwent; const gchar *name; GError *error = NULL; gchar *filename; gboolean regular; GHashTableIter iter; GKeyFile *key_file; User *user; GDir *dir; /* First iteration */ if (*state == NULL) { *state = g_dir_open (USERDIR, 0, &error); -- 2.7.4