1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-09 13:57:42 +03:00

core: change ownership of subcgroup we create recursively, it shall be owned by the user delegated to

If we create a subcroup (regardless if the '.control' subgroup we
always created or one configured via DelegateSubgroup=) it's inside of
the delegated territory of the cgroup tree, hence it should be owned
fully by the unit's users. Hence do so.
This commit is contained in:
Lennart Poettering 2023-04-24 10:05:10 +02:00
parent 18c1e481b6
commit bcd9b98159
3 changed files with 78 additions and 1 deletions

View File

@ -4904,7 +4904,7 @@ static int exec_child(
return log_unit_error_errno(unit, r, "Failed to acquire cgroup path: %m");
}
if (r > 0) {
r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER, p, uid, gid);
r = cg_set_access_recursive(SYSTEMD_CGROUP_CONTROLLER, p, uid, gid);
if (r < 0) {
*exit_status = EXIT_CGROUP;
return log_unit_error_errno(unit, r, "Failed to adjust control subgroup access: %m");

View File

@ -483,6 +483,82 @@ int cg_set_access(
return 0;
}
struct access_callback_data {
uid_t uid;
gid_t gid;
int error;
};
static int access_callback(
RecurseDirEvent event,
const char *path,
int dir_fd,
int inode_fd,
const struct dirent *de,
const struct statx *sx,
void *userdata) {
struct access_callback_data *d = ASSERT_PTR(userdata);
if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY))
return RECURSE_DIR_CONTINUE;
assert(inode_fd >= 0);
/* fchown() doesn't support O_PATH fds, hence we use the /proc/self/fd/ trick */
if (chown(FORMAT_PROC_FD_PATH(inode_fd), d->uid, d->gid) < 0) {
log_debug_errno(errno, "Failed to change ownership of '%s', ignoring: %m", ASSERT_PTR(path));
if (d->error == 0) /* Return last error to caller */
d->error = errno;
}
return RECURSE_DIR_CONTINUE;
}
int cg_set_access_recursive(
const char *controller,
const char *path,
uid_t uid,
gid_t gid) {
_cleanup_close_ int fd = -EBADF;
_cleanup_free_ char *fs = NULL;
int r;
/* A recursive version of cg_set_access(). But note that this one changes ownership of *all* files,
* not just the allowlist that cg_set_access() uses. Use cg_set_access() on the cgroup you want to
* delegate, and cg_set_access_recursive() for any subcrgoups you might want to create below it. */
if (!uid_is_valid(uid) && !gid_is_valid(gid))
return 0;
r = cg_get_path(controller, path, NULL, &fs);
if (r < 0)
return r;
fd = open(fs, O_DIRECTORY|O_CLOEXEC|O_RDONLY);
if (fd < 0)
return -errno;
struct access_callback_data d = {
.uid = uid,
.gid = gid,
};
r = recurse_dir(fd,
fs,
/* statx_mask= */ 0,
/* n_depth_max= */ UINT_MAX,
RECURSE_DIR_SAME_MOUNT|RECURSE_DIR_INODE_FD|RECURSE_DIR_TOPLEVEL,
access_callback,
&d);
if (r < 0)
return r;
return -d.error;
}
int cg_migrate(
const char *cfrom,
const char *pfrom,

View File

@ -24,6 +24,7 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid);
int cg_create_and_attach(const char *controller, const char *path, pid_t pid);
int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
int cg_set_access_recursive(const char *controller, const char *path, uid_t uid, gid_t gid);
int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);