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.
This commit is contained in:
nekral-guest 2008-09-13 11:54:49 +00:00
parent 70c9eeff05
commit 8c060833c8
4 changed files with 39 additions and 12 deletions

View File

@ -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> 2008-09-07 Nicolas François <nicolas.francois@centraliens.net>
* configure.in: Fix the dependency of ACCT_TOOLS_SETUID on * configure.in: Fix the dependency of ACCT_TOOLS_SETUID on

7
NEWS
View File

@ -12,6 +12,10 @@ shadow-4.1.2.1 -> shadow-4.1.3 UNRELEASED
groupadd, groupdel, groupmod, newusers, useradd, userdel, and usermod. groupadd, groupdel, groupmod, newusers, useradd, userdel, and usermod.
This authentication is not necessary when these tools are not This authentication is not necessary when these tools are not
installed setuid root. 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 - gpasswd
* Added support for long options --add (-a), --delete (-d), * 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). --members (-M).
- groupadd - groupadd
* audit logging improvements. * audit logging improvements.
* Speedup (see "addition of users or groups" above).
- groupdel - groupdel
* audit logging improvements. * audit logging improvements.
- groupmems - groupmems
@ -35,12 +40,14 @@ shadow-4.1.2.1 -> shadow-4.1.3 UNRELEASED
--list (-l), --group (-g). --list (-l), --group (-g).
- newusers - newusers
* Implement the -r, --system option. * Implement the -r, --system option.
* Speedup (see "addition of users or groups" above).
- passwd - passwd
* For compatibility with other passwd version, the --lock an --unlock * For compatibility with other passwd version, the --lock an --unlock
options do not lock or unlock the user account anymore. They only options do not lock or unlock the user account anymore. They only
lock or unlock the user's password. lock or unlock the user's password.
- useradd - useradd
* audit logging improvements. * audit logging improvements.
* Speedup (see "addition of users or groups" above).
- userdel - userdel
* audit logging improvements. * audit logging improvements.
- usermod - usermod

View File

@ -51,6 +51,7 @@ int find_new_gid (bool sys_group, gid_t *gid, gid_t const *preferred_gid)
{ {
const struct group *grp; const struct group *grp;
gid_t gid_min, gid_max, group_id; gid_t gid_min, gid_max, group_id;
char *used_gids;
assert (gid != NULL); 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 ("GID_MIN", 1000L) - 1;
gid_max = getdef_ulong ("SYS_GID_MAX", (unsigned long) gid_max); 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) if ( (NULL != preferred_gid)
&& (*preferred_gid >= gid_min) && (*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, * Search the entire group file,
* looking for the largest unused value. * looking for the largest unused value.
* *
* We check the list of users according to NSS (setpwent/getpwent), * We check the list of groups according to NSS (setgrent/getgrent),
* but we also check the local database (pw_rewind/pw_next) in case * but we also check the local database (gr_rewind/gr_next) in case
* some groups were created but the changes were not committed yet. * some groups were created but the changes were not committed yet.
*/ */
setgrent (); 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)) { if ((grp->gr_gid >= group_id) && (grp->gr_gid <= gid_max)) {
group_id = grp->gr_gid + 1; group_id = grp->gr_gid + 1;
} }
/* create index of used GIDs */
if (grp->gr_gid <= gid_max) {
used_gids[grp->gr_gid] = 1;
}
} }
endgrent (); endgrent ();
/* /*
* If a group with GID equal to GID_MAX exists, the above algorithm * 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 * 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 * free GID starting with GID_MIN.
* by not having users with GID equal to GID_MAX). --marekm
*/ */
if (group_id == gid_max + 1) { if (group_id == gid_max + 1) {
for (group_id = gid_min; group_id < gid_max; group_id++) { for (group_id = gid_min; group_id < gid_max; group_id++) {
/* local, no need for xgetgrgid */ if (0 == used_gids[grp->gr_gid]) {
if ( (getgrgid (group_id) == NULL)
&& (gr_locate_gid (group_id) == NULL)) {
break; break;
} }
} }

View File

@ -51,6 +51,7 @@ int find_new_uid (bool sys_user, uid_t *uid, uid_t const *preferred_uid)
{ {
const struct passwd *pwd; const struct passwd *pwd;
uid_t uid_min, uid_max, user_id; uid_t uid_min, uid_max, user_id;
char *used_uids;
assert (uid != NULL); 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 ("UID_MIN", 1000L) - 1;
uid_max = getdef_ulong ("SYS_UID_MAX", (unsigned long) uid_max); 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) if ( (NULL != preferred_uid)
&& (*preferred_uid >= uid_min) && (*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)) { if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
user_id = pwd->pw_uid + 1; user_id = pwd->pw_uid + 1;
} }
/* create index of used UIDs */
if (pwd->pw_uid <= uid_max) {
used_uids[pwd->pw_uid] = 1;
}
} }
endpwent (); endpwent ();
/* /*
* If a user with UID equal to UID_MAX exists, the above algorithm * 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 * 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 * free UID starting with UID_MIN.
* by not having users with UID equal to UID_MAX). --marekm
*/ */
if (user_id == uid_max + 1) { if (user_id == uid_max + 1) {
for (user_id = uid_min; user_id < uid_max; user_id++) { for (user_id = uid_min; user_id < uid_max; user_id++) {
/* local, no need for xgetpwuid */ if (0 == used_uids[pwd->pw_uid]) {
if ( (getpwuid (user_id) == NULL)
&& (pw_locate_uid (user_id) == NULL)) {
break; break;
} }
} }