return 0;
}
-static int synthesize_group_creds(
- const char **groupname,
- gid_t *ret_gid) {
-
+static int synthesize_group_creds(const char *groupname, char **ret_name, gid_t *ret_gid) {
assert(groupname);
- assert(*groupname);
-
- if (STR_IN_SET(*groupname, "root", "0")) {
- *groupname = "root";
-
- if (ret_gid)
- *ret_gid = 0;
-
- return 0;
- }
-
- if (STR_IN_SET(*groupname, NOBODY_GROUP_NAME, "65534") &&
- synthesize_nobody()) {
- *groupname = NOBODY_GROUP_NAME;
-
- if (ret_gid)
- *ret_gid = GID_NOBODY;
- return 0;
- }
+ gid_t id;
+ const char *n;
+ int r;
- return -ENOMEDIUM;
+ if (STR_IN_SET(groupname, "root", "0")) {
+ id = 0;
+ n = "root";
+ } else if (STR_IN_SET(groupname, NOBODY_GROUP_NAME, "65534") &&
+ synthesize_nobody()) {
+ id = GID_NOBODY;
+ n = NOBODY_GROUP_NAME;
+ } else
+ return -ENOMEDIUM;
+
+ r = strdup_to_full(ret_name, n);
+ if (r < 0)
+ return r;
+ if (ret_gid)
+ *ret_gid = id;
+ return 0;
}
-int get_group_creds(const char **groupname, gid_t *ret_gid, UserCredsFlags flags) {
- bool patch_groupname = false;
- struct group *g;
+int get_group_creds(const char *groupname, UserCredsFlags flags, char **ret_name, gid_t *ret_gid) {
+ _cleanup_free_ struct group *gr = NULL;
gid_t id;
int r;
assert(groupname);
- assert(*groupname);
if (!FLAGS_SET(flags, USER_CREDS_PREFER_NSS)) {
- r = synthesize_group_creds(groupname, ret_gid);
+ r = synthesize_group_creds(groupname, ret_name, ret_gid);
if (r >= 0)
return 0;
if (r != -ENOMEDIUM) /* not a groupname we can synthesize */
return r;
}
- if (parse_gid(*groupname, &id) >= 0) {
- errno = 0;
- g = getgrgid(id);
-
- if (g)
- patch_groupname = true;
+ if (parse_gid(groupname, &id) >= 0) {
+ r = getgrgid_malloc(id, &gr);
+ if (r >= 0)
+ groupname = gr->gr_name;
else if (FLAGS_SET(flags, USER_CREDS_ALLOW_MISSING)) {
if (ret_gid)
*ret_gid = id;
-
+ if (ret_name)
+ *ret_name = NULL;
return 0;
}
- } else {
- errno = 0;
- g = getgrnam(*groupname);
- }
-
- if (!g) {
- /* getgrnam() may fail with ENOENT if /etc/group is missing.
- * For us that is equivalent to the name not being defined. */
- r = IN_SET(errno, 0, ENOENT) ? -ESRCH : -errno;
-
- if (FLAGS_SET(flags, USER_CREDS_PREFER_NSS))
- if (synthesize_group_creds(groupname, ret_gid) >= 0)
- return 0;
+ } else
+ r = getgrnam_malloc(groupname, &gr);
+ if (r < 0) {
+ if (FLAGS_SET(flags, USER_CREDS_PREFER_NSS) &&
+ synthesize_group_creds(groupname, ret_name, ret_gid) >= 0)
+ return 0;
return r;
}
- if (ret_gid) {
- if (!gid_is_valid(g->gr_gid))
- return -EBADMSG;
-
- *ret_gid = g->gr_gid;
- }
-
- if (patch_groupname)
- *groupname = g->gr_name;
+ if (ret_gid && !gid_is_valid(gr->gr_gid))
+ return -EBADMSG;
+ r = strdup_to_full(ret_name, groupname);
+ if (r < 0)
+ return r;
+ if (ret_gid)
+ *ret_gid = gr->gr_gid;
return 0;
}
int r;
gid_t gid;
- r = get_group_creds(&name, &gid, 0);
+ r = get_group_creds(name, /* flags= */ 0, /* ret_name= */ NULL, &gid);
if (r < 0)
return r;
} UserCredsFlags;
int get_user_creds(const char **username, uid_t *ret_uid, gid_t *ret_gid, const char **ret_home, const char **ret_shell, UserCredsFlags flags);
-int get_group_creds(const char **groupname, gid_t *ret_gid, UserCredsFlags flags);
+int get_group_creds(const char *groupname, UserCredsFlags flags, char **ret_name, gid_t *ret_gid);
char* uid_to_name(uid_t uid);
char* gid_to_name(gid_t gid);
return 0;
}
-static int get_fixed_group(
- const char *group_or_gid,
- const char **ret_groupname,
- gid_t *ret_gid) {
-
- int r;
-
- assert(group_or_gid);
- assert(ret_groupname);
-
- r = get_group_creds(&group_or_gid, ret_gid, /* flags= */ 0);
- if (r < 0)
- return r;
-
- /* group_or_gid is normalized by get_group_creds to groupname */
- *ret_groupname = group_or_gid;
-
- return 0;
-}
-
static int get_supplementary_groups(
const ExecContext *c,
const char *user,
if (k >= ngroups_max)
return -E2BIG;
- const char *g = *i;
- r = get_group_creds(&g, l_gids + k, /* flags= */ 0);
+ r = get_group_creds(*i, /* flags= */ 0, /* ret_name= */ NULL, l_gids + k);
if (r < 0)
return r;
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **joined_exec_search_path = NULL, **accum_env = NULL;
int r;
- const char *username = NULL, *groupname = NULL;
+ const char *username = NULL;
_cleanup_free_ char *home_buffer = NULL, *own_user = NULL;
_cleanup_(free_pressure_paths) char *pressure_path[_PRESSURE_RESOURCE_MAX] = {};
const char *pwent_home = NULL, *shell = NULL;
}
if (context->group) {
- r = get_fixed_group(context->group, &groupname, &gid);
+ r = get_group_creds(context->group, /* flags= */ 0, /* ret_name= */ NULL, &gid);
if (r < 0) {
*exit_status = EXIT_GROUP;
log_error_errno(r, "Failed to determine credentials for group '%s': %s",
- u, STRERROR_GROUP(r));
+ context->group, STRERROR_GROUP(r));
return ERRNO_IS_NEG_BAD_ACCOUNT(r) ? -EINVAL : r; /* Suppress confusing errno */
}
}
}
if (!isempty(s->group)) {
- const char *group = s->group;
-
- r = get_group_creds(&group, &gid, 0);
+ r = get_group_creds(s->group, /* flags= */ 0, /* ret_name= */ NULL, &gid);
if (r < 0) {
log_unit_error_errno(UNIT(s), r,
"Failed to resolve group '%s': %s",
- group, STRERROR_GROUP(r));
+ s->group, STRERROR_GROUP(r));
_exit(EXIT_GROUP);
}
}
}
if (!isempty(s->group)) {
- const char *group = s->group;
-
- r = get_group_creds(&group, &gid, 0);
+ r = get_group_creds(s->group, /* flags= */ 0, /* ret_name= */ NULL, &gid);
if (r < 0) {
log_unit_error_errno(UNIT(s), r,
"Failed to resolve group '%s': %s",
- group, STRERROR_GROUP(r));
+ s->group, STRERROR_GROUP(r));
_exit(EXIT_GROUP);
}
}
if (arg_exec_group) {
gid_t gid;
- r = get_group_creds(&arg_exec_group, &gid, 0);
+ r = get_group_creds(arg_exec_group, /* flags= */ 0, /* ret_name= */ NULL, &gid);
if (r < 0)
return log_error_errno(r, "Failed to resolve group '%s': %s",
arg_exec_group, STRERROR_GROUP(r));
if (r < 0)
return log_oom();
- if (!arg_exec_group) {
- if (setresgid(gid, gid, gid) < 0)
- return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
- }
+ if (!arg_exec_group &&
+ setresgid(gid, gid, gid) < 0)
+ return log_error_errno(errno, "Failed to change GID to " GID_FMT ": %m", gid);
if (setresuid(uid, uid, uid) < 0)
return log_error_errno(errno, "Failed to change UID to " UID_FMT ": %m", uid);
test_get_user_creds_one("65534", NOBODY_USER_NAME, UID_NOBODY, GID_NOBODY, "/", NOLOGIN);
}
-static void test_get_group_creds_one(const char *id, const char *name, gid_t gid) {
+static void test_get_group_creds_one(const char *id, const char *expected_name, gid_t expected_gid) {
gid_t rgid = GID_INVALID;
+ _cleanup_free_ char *rnam = NULL;
int r;
- log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, name, gid);
+ log_info("/* %s(\"%s\", \"%s\", "GID_FMT") */", __func__, id, expected_name, expected_gid);
- r = get_group_creds(&id, &rgid, 0);
- log_info_errno(r, "got \"%s\", "GID_FMT": %m", id, rgid);
- if (!synthesize_nobody() && streq(name, NOBODY_GROUP_NAME)) {
+ r = get_group_creds(id, /* flags= */ 0, &rnam, &rgid);
+ log_info_errno(r, "→ \"%s\", "GID_FMT": %m", strnull(rnam), rgid);
+ if (!synthesize_nobody() && streq(expected_name, NOBODY_GROUP_NAME)) {
log_info("(skipping detailed tests because nobody is not synthesized)");
return;
}
ASSERT_OK(r);
- ASSERT_STREQ(id, name);
- ASSERT_EQ(rgid, gid);
+ ASSERT_STREQ(rnam, expected_name);
+ ASSERT_EQ(rgid, expected_gid);
}
TEST(get_group_creds) {
/* Second: pass to NSS if we are running "online" */
if (!arg_root)
- return get_group_creds(&group, ret_gid, 0);
+ return get_group_creds(group, /* flags= */ 0, /* ret_name= */ NULL, ret_gid);
/* Third, synthesize "root" unconditionally */
if (streq(group, "root")) {