From b41dca52762c5188638236ae81b9f4597bb29ac9 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 9 Nov 2022 11:14:12 -0500 Subject: pwcache: Fill the user/group caches lazily Iterating all the users/groups can be expensive, especially with NSS. Android has so many that it doesn't even return them all from get{pw,gr}ent() for performance reasons, leading to incorrect behaviour of -user/-group/etc. --- src/opt.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src/opt.c') diff --git a/src/opt.c b/src/opt.c index cece337..fa2e66c 100644 --- a/src/opt.c +++ b/src/opt.c @@ -48,6 +48,7 @@ #include "expr.h" #include "pwcache.h" #include +#include #include #include #include @@ -789,12 +790,13 @@ static void infer_icmp_facts(struct opt_state *state, const struct bfs_expr *exp static void infer_gid_facts(struct opt_state *state, const struct bfs_expr *expr) { infer_icmp_facts(state, expr, GID_RANGE); - const struct bfs_groups *groups = bfs_ctx_groups(state->ctx); struct range *range = &state->facts_when_true.ranges[GID_RANGE]; - if (groups && range->min == range->max) { + if (range->min == range->max) { gid_t gid = range->min; - bool nogroup = !bfs_getgrgid(groups, gid); - constrain_pred(&state->facts_when_true.preds[NOGROUP_PRED], nogroup); + bool nogroup = !bfs_getgrgid(state->ctx->groups, gid); + if (errno == 0) { + constrain_pred(&state->facts_when_true.preds[NOGROUP_PRED], nogroup); + } } } @@ -802,12 +804,13 @@ static void infer_gid_facts(struct opt_state *state, const struct bfs_expr *expr static void infer_uid_facts(struct opt_state *state, const struct bfs_expr *expr) { infer_icmp_facts(state, expr, UID_RANGE); - const struct bfs_users *users = bfs_ctx_users(state->ctx); struct range *range = &state->facts_when_true.ranges[UID_RANGE]; - if (users && range->min == range->max) { + if (range->min == range->max) { uid_t uid = range->min; - bool nouser = !bfs_getpwuid(users, uid); - constrain_pred(&state->facts_when_true.preds[NOUSER_PRED], nouser); + bool nouser = !bfs_getpwuid(state->ctx->users, uid); + if (errno == 0) { + constrain_pred(&state->facts_when_true.preds[NOUSER_PRED], nouser); + } } } -- cgit v1.2.3