From: Bostjan Skufca Date: Sat, 6 Sep 2014 18:47:55 +0000 (+0000) Subject: sub[ug]id: compare range before comparing username/UID, to avoid unnecessary syscalls X-Git-Tag: 4.3.0~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fsubuigid-numeric;p=thirdparty%2Fshadow.git sub[ug]id: compare range before comparing username/UID, to avoid unnecessary syscalls 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 --- diff --git a/lib/subordinateio.c b/lib/subordinateio.c index 253533682..88cc58176 100644 --- a/lib/subordinateio.c +++ b/lib/subordinateio.c @@ -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; } }