summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBostjan Skufca <bostjan@a2o.si>2014-09-06 18:47:55 +0000
committerSerge Hallyn <serge.hallyn@ubuntu.com>2014-09-17 15:48:24 -0500
commit1d049b6aedb7f94a97369215787e111b4b1dc584 (patch)
treedc35303495fc4ba4e1b7afea978fceb36efdd988
parent37e2a687e3a67a3ea14f8ed01a52ec6a76149990 (diff)
sub[ug]id: compare range before comparing username/UID, to avoid unnecessary syscallssubuigid-numeric
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>
-rw-r--r--lib/subordinateio.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/lib/subordinateio.c b/lib/subordinateio.c
index 25353368..88cc5817 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;
}
}