mirror of
https://github.com/systemd/systemd
synced 2024-10-15 04:24:19 +00:00
Merge pull request #7059 from yuwata/dynamic-user-7013
dynamic-user: permit the case static uid and gid are different
This commit is contained in:
commit
895265ad7d
|
@ -206,7 +206,10 @@
|
|||
enabled for a unit, the name of the dynamic user/group is implicitly derived from the unit name. If the unit
|
||||
name without the type suffix qualifies as valid user name it is used directly, otherwise a name incorporating a
|
||||
hash of it is used. If a statically allocated user or group of the configured name already exists, it is used
|
||||
and no dynamic user/group is allocated. Dynamic users/groups are allocated from the UID/GID range
|
||||
and no dynamic user/group is allocated. Note that if <varname>User=</varname> is specified and the static group
|
||||
with the name exists, then it is required that the static user with the name already exists. Similarly,
|
||||
if <varname>Group=</varname> is specified and the static user with the name exists, then it is required that
|
||||
the static group with the name already exists. Dynamic users/groups are allocated from the UID/GID range
|
||||
61184…65519. It is recommended to avoid this range for regular system or login users. At any point in time
|
||||
each UID/GID from this range is only assigned to zero or one dynamically allocated users/groups in
|
||||
use. However, UID/GIDs are recycled after a unit is terminated. Care should be taken that any processes running
|
||||
|
|
|
@ -82,7 +82,7 @@ static int dynamic_user_add(Manager *m, const char *name, int storage_socket[2],
|
|||
return 0;
|
||||
}
|
||||
|
||||
int dynamic_user_acquire(Manager *m, const char *name, DynamicUser** ret) {
|
||||
static int dynamic_user_acquire(Manager *m, const char *name, DynamicUser** ret) {
|
||||
_cleanup_close_pair_ int storage_socket[2] = { -1, -1 };
|
||||
DynamicUser *d;
|
||||
int r;
|
||||
|
@ -421,7 +421,7 @@ static void unlink_uid_lock(int lock_fd, uid_t uid, const char *name) {
|
|||
(void) make_uid_symlinks(uid, name, false); /* remove direct lookup symlinks */
|
||||
}
|
||||
|
||||
int dynamic_user_realize(DynamicUser *d, char **suggested_dirs, uid_t *ret) {
|
||||
static int dynamic_user_realize(DynamicUser *d, char **suggested_dirs, uid_t *ret, bool is_user) {
|
||||
|
||||
_cleanup_close_ int etc_passwd_lock_fd = -1, uid_lock_fd = -1;
|
||||
uid_t uid = UID_INVALID;
|
||||
|
@ -460,19 +460,28 @@ int dynamic_user_realize(DynamicUser *d, char **suggested_dirs, uid_t *ret) {
|
|||
struct passwd *p;
|
||||
struct group *g;
|
||||
|
||||
/* OK, this is not a numeric UID. Let's see if there's a user by this name */
|
||||
p = getpwnam(d->name);
|
||||
if (p)
|
||||
uid = p->pw_uid;
|
||||
|
||||
/* Let's see if there's a group by this name */
|
||||
g = getgrnam(d->name);
|
||||
if (g) {
|
||||
/* If the UID/GID of the user/group of the same don't match, refuse operation */
|
||||
if (uid != UID_INVALID && uid != (uid_t) g->gr_gid)
|
||||
return -EILSEQ;
|
||||
|
||||
uid = (uid_t) g->gr_gid;
|
||||
if (is_user) {
|
||||
/* OK, this is not a numeric UID. Let's see if there's a user by this name */
|
||||
p = getpwnam(d->name);
|
||||
if (p)
|
||||
uid = p->pw_uid;
|
||||
else {
|
||||
/* if the user does not exist but the group with the same name exists, refuse operation */
|
||||
g = getgrnam(d->name);
|
||||
if (g)
|
||||
return -EILSEQ;
|
||||
}
|
||||
} else {
|
||||
/* Let's see if there's a group by this name */
|
||||
g = getgrnam(d->name);
|
||||
if (g)
|
||||
uid = (uid_t) g->gr_gid;
|
||||
else {
|
||||
/* if the group does not exist but the user with the same name exists, refuse operation */
|
||||
p = getpwnam(d->name);
|
||||
if (p)
|
||||
return -EILSEQ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,7 +535,7 @@ finish:
|
|||
return r;
|
||||
}
|
||||
|
||||
int dynamic_user_current(DynamicUser *d, uid_t *ret) {
|
||||
static int dynamic_user_current(DynamicUser *d, uid_t *ret) {
|
||||
_cleanup_close_ int lock_fd = -1;
|
||||
uid_t uid;
|
||||
int r;
|
||||
|
@ -555,7 +564,7 @@ finish:
|
|||
return r;
|
||||
}
|
||||
|
||||
DynamicUser* dynamic_user_ref(DynamicUser *d) {
|
||||
static DynamicUser* dynamic_user_ref(DynamicUser *d) {
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
|
@ -565,7 +574,7 @@ DynamicUser* dynamic_user_ref(DynamicUser *d) {
|
|||
return d;
|
||||
}
|
||||
|
||||
DynamicUser* dynamic_user_unref(DynamicUser *d) {
|
||||
static DynamicUser* dynamic_user_unref(DynamicUser *d) {
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
|
@ -608,7 +617,7 @@ finish:
|
|||
return r;
|
||||
}
|
||||
|
||||
DynamicUser* dynamic_user_destroy(DynamicUser *d) {
|
||||
static DynamicUser* dynamic_user_destroy(DynamicUser *d) {
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
|
@ -814,13 +823,13 @@ int dynamic_creds_realize(DynamicCreds *creds, char **suggested_paths, uid_t *ui
|
|||
/* Realize both the referenced user and group */
|
||||
|
||||
if (creds->user) {
|
||||
r = dynamic_user_realize(creds->user, suggested_paths, &u);
|
||||
r = dynamic_user_realize(creds->user, suggested_paths, &u, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (creds->group && creds->group != creds->user) {
|
||||
r = dynamic_user_realize(creds->group, suggested_paths, &g);
|
||||
r = dynamic_user_realize(creds->group, suggested_paths, &g, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else
|
||||
|
|
|
@ -43,15 +43,6 @@ struct DynamicUser {
|
|||
char name[];
|
||||
};
|
||||
|
||||
int dynamic_user_acquire(Manager *m, const char *name, DynamicUser **ret);
|
||||
|
||||
int dynamic_user_realize(DynamicUser *d, char **suggested_paths, uid_t *ret);
|
||||
int dynamic_user_current(DynamicUser *d, uid_t *ret);
|
||||
|
||||
DynamicUser* dynamic_user_ref(DynamicUser *d);
|
||||
DynamicUser* dynamic_user_unref(DynamicUser *d);
|
||||
DynamicUser* dynamic_user_destroy(DynamicUser *d);
|
||||
|
||||
int dynamic_user_serialize(Manager *m, FILE *f, FDSet *fds);
|
||||
void dynamic_user_deserialize_one(Manager *m, const char *value, FDSet *fds);
|
||||
void dynamic_user_vacuum(Manager *m, bool close_user);
|
||||
|
|
|
@ -2795,6 +2795,10 @@ static int exec_child(
|
|||
r = dynamic_creds_realize(dcreds, suggested_paths, &uid, &gid);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_USER;
|
||||
if (r == -EILSEQ) {
|
||||
log_unit_error(unit, "Failed to update dynamic user credentials: User or group with specified name already exists.");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return log_unit_error_errno(unit, r, "Failed to update dynamic user credentials: %m");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue