Skip to content

Commit

Permalink
shared/condition: avoid nss lookup in PID1
Browse files Browse the repository at this point in the history
PID 1 is not allowed to do nss lookups because this may take a long time or
even deadlock.

While at it, the comparisons are reordered to do the "easy" comparisons which
only require a string comparison first. Delay parsing of the UID until it is
really necessary. The result is the same, because we know that "root" and
"nobody" parse as valid.

(cherry picked from commit 734f96b)
  • Loading branch information
keszybz committed Oct 13, 2022
1 parent 40053e6 commit 5da595d
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions src/shared/condition.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,31 +375,36 @@ static int condition_test_cpus(Condition *c, char **env) {
static int condition_test_user(Condition *c, char **env) {
uid_t id;
int r;
_cleanup_free_ char *username = NULL;
const char *u;

assert(c);
assert(c->parameter);
assert(c->type == CONDITION_USER);

/* Do the quick&easy comparisons first, and only parse the UID later. */
if (streq(c->parameter, "root"))
return getuid() == 0 || geteuid() == 0;
if (streq(c->parameter, NOBODY_USER_NAME))
return getuid() == UID_NOBODY || geteuid() == UID_NOBODY;
if (streq(c->parameter, "@system"))
return uid_is_system(getuid()) || uid_is_system(geteuid());

r = parse_uid(c->parameter, &id);
if (r >= 0)
return id == getuid() || id == geteuid();

if (streq("@system", c->parameter))
return uid_is_system(getuid()) || uid_is_system(geteuid());
if (getpid_cached() == 1) /* We already checked for "root" above, and we know that
* PID 1 is running as root, hence we know it cannot match. */
return false;

username = getusername_malloc();
/* getusername_malloc() may do an nss lookup, which is not allowed in PID 1. */
_cleanup_free_ char *username = getusername_malloc();
if (!username)
return -ENOMEM;

if (streq(username, c->parameter))
return 1;

if (getpid_cached() == 1)
return streq(c->parameter, "root");

u = c->parameter;
const char *u = c->parameter;
r = get_user_creds(&u, &id, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
if (r < 0)
return 0;
Expand Down

0 comments on commit 5da595d

Please sign in to comment.