]> granicus.if.org Git - shadow/commitdiff
From RedHat's patch shadow-4.1.2-sysAccountDownhill.patch
authornekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Sat, 13 Sep 2008 11:54:49 +0000 (11:54 +0000)
committernekral-guest <nekral-guest@5a98b0ae-9ef6-0310-add3-de5d479b70d7>
Sat, 13 Sep 2008 11:54:49 +0000 (11:54 +0000)
Thanks to Peter Vrabec.
* NEWS, libmisc/find_new_gid.c, libmisc/find_new_uid.c: Build an
index of used IDs to avoid a database request for each id in the
allowed range (when the highest allowed ID is already used).
This speedups the addition of users or groups when the highest
allowed ID is already used. The additional memory usage of the
tools should be acceptable when UID_MAX/SYS_UID_MAX are set to a
reasonable number.

ChangeLog
NEWS
libmisc/find_new_gid.c
libmisc/find_new_uid.c

index 1d5fe2cec98862f9693b7e93d445ccdac4110dd4..a1cdcd2689648fdc49eee59b54b666b9b38a0986 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-09-07  Nicolas François  <nicolas.francois@centraliens.net>
+
+       From RedHat's patch shadow-4.1.2-sysAccountDownhill.patch
+       Thanks to Peter Vrabec.
+       * NEWS, libmisc/find_new_gid.c, libmisc/find_new_uid.c: Build an
+       index of used IDs to avoid a database request for each id in the
+       allowed range (when the highest allowed ID is already used).
+       This speedups the addition of users or groups when the highest
+       allowed ID is already used. The additional memory usage of the
+       tools should be acceptable when UID_MAX/SYS_UID_MAX are set to a
+       reasonable number.
+
 2008-09-07  Nicolas François  <nicolas.francois@centraliens.net>
 
        * configure.in: Fix the dependency of ACCT_TOOLS_SETUID on
diff --git a/NEWS b/NEWS
index 205dc2e961a2cce6236f4bb35c1af19d3a9c0696..31ef88c711474e88b685c4da8d05acdcfffa767f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,10 @@ shadow-4.1.2.1 -> shadow-4.1.3                                               UNRELEASED
     groupadd, groupdel, groupmod, newusers, useradd, userdel, and usermod.
     This authentication is not necessary when these tools are not
     installed setuid root.
+- addition of users or groups
+  * Speed improvement in case UID_MAX/SYS_UID_MAX/GID_MAX/SYS_GID_MAX is
+    used for an user/group. This should be noticeable in case of LDAP
+    configured systems. This should impact useradd, groupadd, and newusers
 
 - gpasswd
   * Added support for long options --add (-a), --delete (-d),
@@ -19,6 +23,7 @@ shadow-4.1.2.1 -> shadow-4.1.3                                                UNRELEASED
     --members (-M).
 - groupadd
   * audit logging improvements.
+  * Speedup (see "addition of users or groups" above).
 - groupdel
   * audit logging improvements.
 - groupmems
@@ -35,12 +40,14 @@ shadow-4.1.2.1 -> shadow-4.1.3                                              UNRELEASED
     --list (-l), --group (-g).
 - newusers
   * Implement the -r, --system option.
+  * Speedup (see "addition of users or groups" above).
 - passwd
   * For compatibility with other passwd version, the --lock an --unlock
     options do not lock or unlock the user account anymore.  They only
     lock or unlock the user's password.
 - useradd
   * audit logging improvements.
+  * Speedup (see "addition of users or groups" above).
 - userdel
   * audit logging improvements.
 - usermod
index 7225ce30c086b0d90a4a927964a53c1f4010e9fd..85e00d3e9f83adf5a066ab893588ba73a70657dc 100644 (file)
@@ -51,6 +51,7 @@ int find_new_gid (bool sys_group, gid_t *gid, gid_t const *preferred_gid)
 {
        const struct group *grp;
        gid_t gid_min, gid_max, group_id;
+       char *used_gids;
 
        assert (gid != NULL);
 
@@ -62,6 +63,8 @@ int find_new_gid (bool sys_group, gid_t *gid, gid_t const *preferred_gid)
                gid_max = getdef_ulong ("GID_MIN", 1000L) - 1;
                gid_max = getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max);
        }
+       used_gids = alloca (sizeof (char) * gid_max +1);
+       memset (used_gids, 0, sizeof (char) * gid_max + 1);
 
        if (   (NULL != preferred_gid)
            && (*preferred_gid >= gid_min)
@@ -81,8 +84,8 @@ int find_new_gid (bool sys_group, gid_t *gid, gid_t const *preferred_gid)
         * Search the entire group file,
         * looking for the largest unused value.
         *
-        * We check the list of users according to NSS (setpwent/getpwent),
-        * but we also check the local database (pw_rewind/pw_next) in case
+        * We check the list of groups according to NSS (setgrent/getgrent),
+        * but we also check the local database (gr_rewind/gr_next) in case
         * some groups were created but the changes were not committed yet.
         */
        setgrent ();
@@ -92,20 +95,21 @@ int find_new_gid (bool sys_group, gid_t *gid, gid_t const *preferred_gid)
                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] = 1;
+               }
        }
        endgrent ();
 
        /*
         * If a group with GID equal to GID_MAX exists, the above algorithm
         * will give us GID_MAX+1 even if not unique. Search for the first
-        * free GID starting with GID_MIN (it's O(n*n) but can be avoided
-        * by not having users with GID equal to GID_MAX).  --marekm
+        * free GID starting with GID_MIN.
         */
        if (group_id == gid_max + 1) {
                for (group_id = gid_min; group_id < gid_max; group_id++) {
-                       /* local, no need for xgetgrgid */
-                       if (   (getgrgid (group_id) == NULL)
-                           && (gr_locate_gid (group_id) == NULL)) {
+                       if (0 == used_gids[grp->gr_gid]) {
                                break;
                        }
                }
index cdf1252197b56376156b76c86a7c9ccc71e9bafc..f4efb9f8c3bcdaa480b46979a506c753ed78a19e 100644 (file)
@@ -51,6 +51,7 @@ int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid)
 {
        const struct passwd *pwd;
        uid_t uid_min, uid_max, user_id;
+       char *used_uids;
 
        assert (uid != NULL);
 
@@ -62,6 +63,8 @@ int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid)
                uid_max = getdef_ulong ("UID_MIN", 1000L) - 1;
                uid_max = getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max);
        }
+       used_uids = alloca (sizeof (char) * uid_max +1);
+       memset (used_uids, 0, sizeof (char) * uid_max + 1);
 
        if (   (NULL != preferred_uid)
            && (*preferred_uid >= uid_min)
@@ -93,20 +96,21 @@ int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid)
                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] = 1;
+               }
        }
        endpwent ();
 
        /*
         * If a user with UID equal to UID_MAX exists, the above algorithm
         * will give us UID_MAX+1 even if not unique. Search for the first
-        * free UID starting with UID_MIN (it's O(n*n) but can be avoided
-        * by not having users with UID equal to UID_MAX).  --marekm
+        * free UID starting with UID_MIN.
         */
        if (user_id == uid_max + 1) {
                for (user_id = uid_min; user_id < uid_max; user_id++) {
-                       /* local, no need for xgetpwuid */
-                       if (   (getpwuid (user_id) == NULL)
-                           && (pw_locate_uid (user_id) == NULL)) {
+                       if (0 == used_uids[pwd->pw_uid]) {
                                break;
                        }
                }