summaryrefslogtreecommitdiffstats
path: root/src/nspawn/nspawn-cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nspawn/nspawn-cgroup.c')
-rw-r--r--src/nspawn/nspawn-cgroup.c95
1 files changed, 56 insertions, 39 deletions
diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c
index a500243..4f28b4a 100644
--- a/src/nspawn/nspawn-cgroup.c
+++ b/src/nspawn/nspawn-cgroup.c
@@ -13,6 +13,7 @@
#include "mountpoint-util.h"
#include "nspawn-cgroup.h"
#include "nspawn-mount.h"
+#include "nsresource.h"
#include "path-util.h"
#include "rm-rf.h"
#include "string-util.h"
@@ -46,38 +47,6 @@ static int chown_cgroup_path(const char *path, uid_t uid_shift) {
return 0;
}
-int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) {
- _cleanup_free_ char *path = NULL, *fs = NULL;
- int r;
-
- r = cg_pid_get_path(NULL, pid, &path);
- if (r < 0)
- return log_error_errno(r, "Failed to get container cgroup path: %m");
-
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, path, NULL, &fs);
- if (r < 0)
- return log_error_errno(r, "Failed to get file system path for container cgroup: %m");
-
- r = chown_cgroup_path(fs, uid_shift);
- if (r < 0)
- return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs);
-
- if (unified_requested == CGROUP_UNIFIED_SYSTEMD || (unified_requested == CGROUP_UNIFIED_NONE && cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0)) {
- _cleanup_free_ char *lfs = NULL;
- /* Always propagate access rights from unified to legacy controller */
-
- r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, NULL, &lfs);
- if (r < 0)
- return log_error_errno(r, "Failed to get file system path for container cgroup: %m");
-
- r = chown_cgroup_path(lfs, uid_shift);
- if (r < 0)
- return log_error_errno(r, "Failed to chown() cgroup %s: %m", lfs);
- }
-
- return 0;
-}
-
int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) {
_cleanup_free_ char *cgroup = NULL;
char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1];
@@ -142,7 +111,14 @@ finish:
return r;
}
-int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested) {
+int create_subcgroup(
+ pid_t pid,
+ bool keep_unit,
+ CGroupUnified unified_requested,
+ uid_t uid_shift,
+ int userns_fd,
+ bool privileged) {
+
_cleanup_free_ char *cgroup = NULL, *payload = NULL;
CGroupMask supported;
char *e;
@@ -185,13 +161,54 @@ int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested)
if (!payload)
return log_oom();
- r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, payload, pid);
+ if (privileged)
+ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, payload, pid);
+ else
+ r = cg_create(SYSTEMD_CGROUP_CONTROLLER, payload);
if (r < 0)
return log_error_errno(r, "Failed to create %s subcgroup: %m", payload);
+ if (privileged) {
+ _cleanup_free_ char *fs = NULL;
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, payload, NULL, &fs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get file system path for container cgroup: %m");
+
+ r = chown_cgroup_path(fs, uid_shift);
+ if (r < 0)
+ return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs);
+
+ } else if (userns_fd >= 0) {
+ _cleanup_close_ int cgroup_fd = -EBADF;
+
+ cgroup_fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, payload);
+ if (cgroup_fd < 0)
+ return log_error_errno(cgroup_fd, "Failed to open cgroup %s: %m", payload);
+
+ r = cg_fd_attach(cgroup_fd, pid);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add process " PID_FMT " to cgroup %s: %m", pid, payload);
+
+ r = nsresource_add_cgroup(userns_fd, cgroup_fd);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add cgroup %s to userns: %m", payload);
+ }
+
+ if (unified_requested == CGROUP_UNIFIED_SYSTEMD || (unified_requested == CGROUP_UNIFIED_NONE && cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0)) {
+ _cleanup_free_ char *lfs = NULL;
+ /* Always propagate access rights from unified to legacy controller */
+
+ r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER_LEGACY, payload, NULL, &lfs);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get file system path for container cgroup: %m");
+
+ r = chown_cgroup_path(lfs, uid_shift);
+ if (r < 0)
+ return log_error_errno(r, "Failed to chown() cgroup %s: %m", lfs);
+ }
+
if (keep_unit) {
_cleanup_free_ char *supervisor = NULL;
-
supervisor = path_join(cgroup, "supervisor");
if (!supervisor)
return log_oom();
@@ -265,7 +282,7 @@ static int mount_legacy_cgroup_hierarchy(
to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy);
- r = path_is_mount_point(to, dest, 0);
+ r = path_is_mount_point_full(to, dest, /* flags = */ 0);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to determine if %s is mounted already: %m", to);
if (r > 0)
@@ -317,7 +334,7 @@ static int mount_legacy_cgns_supported(
(void) mkdir_p(cgroup_root, 0755);
/* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
- r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW);
+ r = path_is_mount_point_full(cgroup_root, dest, AT_SYMLINK_FOLLOW);
if (r < 0)
return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m");
if (r == 0) {
@@ -427,7 +444,7 @@ static int mount_legacy_cgns_unsupported(
(void) mkdir_p(cgroup_root, 0755);
/* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
- r = path_is_mount_point(cgroup_root, dest, AT_SYMLINK_FOLLOW);
+ r = path_is_mount_point_full(cgroup_root, dest, AT_SYMLINK_FOLLOW);
if (r < 0)
return log_error_errno(r, "Failed to determine if /sys/fs/cgroup is already mounted: %m");
if (r == 0) {
@@ -529,7 +546,7 @@ static int mount_unified_cgroups(const char *dest) {
(void) mkdir_p(p, 0755);
- r = path_is_mount_point(p, dest, AT_SYMLINK_FOLLOW);
+ r = path_is_mount_point_full(p, dest, AT_SYMLINK_FOLLOW);
if (r < 0)
return log_error_errno(r, "Failed to determine if %s is mounted already: %m", p);
if (r > 0) {