]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
sub[ug]id: compare range before comparing username/UID, to avoid unnecessary syscalls subuigid-numeric
authorBostjan Skufca <bostjan@a2o.si>
Sat, 6 Sep 2014 18:47:55 +0000 (18:47 +0000)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 17 Sep 2014 20:48:24 +0000 (15:48 -0500)
Change suggested by Nicolas François as performance optimization.
Performance penalty would be really noticeable when usernames are
stored in remote databases (ldap).

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
lib/subordinateio.c

index 25353368238fd620c7e1425cd716e752be08b56c..88cc58176e96de865843383c96b75af83069d592 100644 (file)
@@ -245,36 +245,38 @@ static const struct subordinate_range *find_range(struct commonio_db *db,
                 unsigned long first = range->start;
                 unsigned long last = first + range->count - 1;
 
+                /* For performance reasons check range before using getpwnam() */
+                if ((val < first) || (val > last)) {
+                        continue;
+                }
+
+                /*
+                 * Range matches. Check if range owner is specified
+                 * as numeric UID and if it matches.
+                 */
+                if (0 == strcmp(range->owner, owner_uid_string)) {
+                        return range;
+                }
+
                 /*
-                 * First check if range owner is specified as numeric UID
-                 * and if it matches.
+                 * Ok, this range owner is not specified as numeric UID
+                 * we are looking for. It may be specified as another
+                 * UID or as a literal username.
+                 *
+                 * If specified as another UID, the call to getpwnam()
+                 * will return NULL.
+                 *
+                 * If specified as literal username, we will get its
+                 * UID and compare that to UID we are looking for.
                  */
-                if (0 != strcmp(range->owner, owner_uid_string)) {
-                        /*
-                         * Ok, this range owner is not specified as numeric UID
-                         * we are looking for. It may be specified as another
-                         * UID or as a literal username.
-                         *
-                         * If specified as another UID, the call to getpwnam()
-                         * will return NULL.
-                         *
-                         * If specified as literal username, we will get its
-                         * UID and compare that to UID we are looking for.
-                         */
-                        const struct passwd *range_owner_pwd;
-
-                        range_owner_pwd = getpwnam(range->owner);
-                        if (NULL == range_owner_pwd) {
-                                continue;
-                        }
-
-                        if (owner_uid != range_owner_pwd->pw_uid) {
-                                continue;
-                        }
+                const struct passwd *range_owner_pwd;
+
+                range_owner_pwd = getpwnam(range->owner);
+                if (NULL == range_owner_pwd) {
+                        continue;
                 }
 
-                /* Owner matches, now let us check this UID/GID range */
-                if ((val >= first) && (val <= last)) {
+                if (owner_uid == range_owner_pwd->pw_uid) {
                         return range;
                 }
         }