diff --git a/ChangeLog b/ChangeLog index a29a2e2f..cda9709a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,10 @@ getpwent / getgrent for system accounts. Trying the low-IDs with getpwuid / getgrgid should be more efficient on LDAP configured systems with many accounts. + * NEWS, libmisc/find_new_gid.c, libmisc/find_new_uid.c: Since + system accounts are allocated from SYS_?ID_MIN to SYS_?ID_MAX in + reverse order, accounts are packed close to SYS_?ID_MAX if + SYS_?ID_MIN is already used but there are still dome gaps. 2009-07-05 Piarres Beobide diff --git a/NEWS b/NEWS index 170fe29b..f489dd40 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,9 @@ shadow-4.1.4.1 -> shadow-4.1.4.2 UNRELEASED - addition of system users or groups * Speed improvement. This should be noticeable in case of LDAP configured systems. This should impact useradd, groupadd, and newusers + * Since system accounts are allocated from SYS_?ID_MIN to SYS_?ID_MAX in + reverse order, accounts are packed close to SYS_?ID_MAX if SYS_?ID_MIN + is already used but there are still dome gaps. - su * Preserve the DISPLAY and XAUTHORITY environment variables. This was diff --git a/libmisc/find_new_gid.c b/libmisc/find_new_gid.c index ed72f289..19bc1966 100644 --- a/libmisc/find_new_gid.c +++ b/libmisc/find_new_gid.c @@ -52,7 +52,7 @@ int find_new_gid (bool sys_group, /*@null@*/gid_t const *preferred_gid) { const struct group *grp; - gid_t gid_min, gid_max, group_id; + gid_t gid_min, gid_max, group_id, id; bool *used_gids; assert (gid != NULL); @@ -61,7 +61,7 @@ int find_new_gid (bool sys_group, gid_min = (gid_t) getdef_ulong ("GID_MIN", 1000UL); gid_max = (gid_t) getdef_ulong ("GID_MAX", 60000UL); } else { - gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 1UL); + gid_min = (gid_t) getdef_ulong ("SYS_GID_MIN", 101UL); gid_max = (gid_t) getdef_ulong ("GID_MIN", 1000UL) - 1; gid_max = (gid_t) getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max); } @@ -80,7 +80,6 @@ int find_new_gid (bool sys_group, return 0; } - group_id = gid_min; /* * Search the entire group file, @@ -90,19 +89,33 @@ int find_new_gid (bool sys_group, * but we also check the local database (gr_rewind/gr_next) in case * some groups were created but the changes were not committed yet. */ - if (sys_group ) { + if (sys_group) { /* setgrent / getgrent / endgrent can be very slow with * LDAP configurations (and many accounts). * Since there is a limited amount of IDs to be tested * for system accounts, we just check the existence * of IDs with getgrgid. */ - for (group_id = gid_min; group_id <= gid_max; group_id++) { - if (getgrgid (group_id) != NULL) { + group_id = gid_max; + for (id = gid_max; id >= gid_min; id--) { + if (getgrgid (id) != NULL) { + group_id = id - 1; + used_gids[id] = true; + } + } + + gr_rewind (); + while ((grp = gr_next ()) != NULL) { + if ((grp->gr_gid <= group_id) && (grp->gr_gid >= gid_min)) { + group_id = grp->gr_gid - 1; + } + /* create index of used GIDs */ + if (grp->gr_gid <= gid_max) { used_gids[grp->gr_gid] = true; } } } else { + group_id = gid_min; setgrent (); while ((grp = getgrent ()) != NULL) { if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) { @@ -114,32 +127,16 @@ int find_new_gid (bool sys_group, } } endgrent (); - } - gr_rewind (); - while ((grp = gr_next ()) != NULL) { - if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) { - group_id = grp->gr_gid + 1; - } - /* create index of used GIDs */ - if (grp->gr_gid <= gid_max) { - used_gids[grp->gr_gid] = true; - } - } - /* find free system account in reverse order */ - if (sys_group) { - for (group_id = gid_max; group_id >= gid_min; group_id--) { - if (false == used_gids[group_id]) { - break; + gr_rewind (); + while ((grp = gr_next ()) != NULL) { + if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) { + group_id = grp->gr_gid + 1; + } + /* create index of used GIDs */ + if (grp->gr_gid <= gid_max) { + used_gids[grp->gr_gid] = true; } - } - if ( group_id < gid_min ) { - fprintf (stderr, - _("%s: Can't get unique GID (no more available GIDs)\n"), - Prog); - SYSLOG ((LOG_WARN, - "no more available GID on the system")); - return -1; } } @@ -148,16 +145,36 @@ int find_new_gid (bool sys_group, * will give us GID_MAX+1 even if not unique. Search for the first * free GID starting with GID_MIN. */ - if (group_id == gid_max + 1) { - for (group_id = gid_min; group_id < gid_max; group_id++) { - if (false == used_gids[group_id]) { - break; + if (sys_group) { + if (group_id == gid_min - 1) { + for (group_id = gid_max; group_id >= gid_min; group_id--) { + if (false == used_gids[group_id]) { + break; + } + } + if ( group_id < gid_min ) { + fprintf (stderr, + _("%s: Can't get unique system GID (no more available GIDs)\n"), + Prog); + SYSLOG ((LOG_WARN, + "no more available GID on the system")); + return -1; } } - if (group_id == gid_max) { - fprintf (stderr, _("%s: Can't get unique GID (no more available GIDs)\n"), Prog); - SYSLOG ((LOG_WARN, "no more available GID on the system")); - return -1; + } else { + if (group_id == gid_max + 1) { + for (group_id = gid_min; group_id < gid_max; group_id++) { + if (false == used_gids[group_id]) { + break; + } + } + if (group_id == gid_max) { + fprintf (stderr, + _("%s: Can't get unique GID (no more available GIDs)\n"), + Prog); + SYSLOG ((LOG_WARN, "no more available GID on the system")); + return -1; + } } } diff --git a/libmisc/find_new_uid.c b/libmisc/find_new_uid.c index 3f3d0a95..b1a188af 100644 --- a/libmisc/find_new_uid.c +++ b/libmisc/find_new_uid.c @@ -52,7 +52,7 @@ int find_new_uid (bool sys_user, /*@null@*/uid_t const *preferred_uid) { const struct passwd *pwd; - uid_t uid_min, uid_max, user_id; + uid_t uid_min, uid_max, user_id, id; bool *used_uids; assert (uid != NULL); @@ -61,7 +61,7 @@ int find_new_uid (bool sys_user, uid_min = (uid_t) getdef_ulong ("UID_MIN", 1000UL); uid_max = (uid_t) getdef_ulong ("UID_MAX", 60000UL); } else { - uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 1UL); + uid_min = (uid_t) getdef_ulong ("SYS_UID_MIN", 101UL); uid_max = (uid_t) getdef_ulong ("UID_MIN", 1000UL) - 1; uid_max = (uid_t) getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max); } @@ -80,7 +80,6 @@ int find_new_uid (bool sys_user, return 0; } - user_id = uid_min; /* * Search the entire password file, @@ -97,12 +96,26 @@ int find_new_uid (bool sys_user, * for system accounts, we just check the existence * of IDs with getpwuid. */ - for (user_id = uid_min; user_id <= uid_max; user_id++) { - if (getpwuid (user_id) != NULL) { - used_uids[user_id] = true; + user_id = uid_max; + for (id = uid_max; id >= uid_min; id--) { + if (getpwuid (id) != NULL) { + user_id = id - 1; + used_uids[id] = true; + } + } + + pw_rewind (); + while ((pwd = pw_next ()) != NULL) { + if ((pwd->pw_uid <= user_id) && (pwd->pw_uid >= uid_min)) { + user_id = pwd->pw_uid - 1; + } + /* create index of used UIDs */ + if (pwd->pw_uid <= uid_max) { + used_uids[pwd->pw_uid] = true; } } } else { + user_id = uid_min; setpwent (); while ((pwd = getpwent ()) != NULL) { if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { @@ -114,32 +127,16 @@ int find_new_uid (bool sys_user, } } endpwent (); - } - pw_rewind (); - while ((pwd = pw_next ()) != NULL) { - if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { - user_id = pwd->pw_uid + 1; - } - /* create index of used UIDs */ - if (pwd->pw_uid <= uid_max) { - used_uids[pwd->pw_uid] = true; - } - } - /* find free system account in reverse order */ - if (sys_user) { - for (user_id = uid_max; user_id >= uid_min; user_id--) { - if (false == used_uids[user_id]) { - break; + pw_rewind (); + while ((pwd = pw_next ()) != NULL) { + if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) { + user_id = pwd->pw_uid + 1; + } + /* create index of used UIDs */ + if (pwd->pw_uid <= uid_max) { + used_uids[pwd->pw_uid] = true; } - } - if (user_id < uid_min ) { - fprintf (stderr, - _("%s: Can't get unique system UID (no more available UIDs)\n"), - Prog); - SYSLOG ((LOG_WARN, - "no more available UID on the system")); - return -1; } } @@ -148,16 +145,36 @@ int find_new_uid (bool sys_user, * will give us UID_MAX+1 even if not unique. Search for the first * free UID starting with UID_MIN. */ - if (user_id == uid_max + 1) { - for (user_id = uid_min; user_id < uid_max; user_id++) { - if (false == used_uids[user_id]) { - break; + if (sys_user) { + if (user_id == uid_min - 1) { + for (user_id = uid_max; user_id >= uid_min; user_id--) { + if (false == used_uids[user_id]) { + break; + } + } + if (user_id < uid_min ) { + fprintf (stderr, + _("%s: Can't get unique system UID (no more available UIDs)\n"), + Prog); + SYSLOG ((LOG_WARN, + "no more available UID on the system")); + return -1; } } - if (user_id == uid_max) { - fprintf (stderr, _("%s: Can't get unique UID (no more available UIDs)\n"), Prog); - SYSLOG ((LOG_WARN, "no more available UID on the system")); - return -1; + } else { + if (user_id == uid_max + 1) { + for (user_id = uid_min; user_id < uid_max; user_id++) { + if (false == used_uids[user_id]) { + break; + } + } + if (user_id == uid_max) { + fprintf (stderr, + _("%s: Can't get unique UID (no more available UIDs)\n"), + Prog); + SYSLOG ((LOG_WARN, "no more available UID on the system")); + return -1; + } } }