int sync_cgroup(pid_t pid, CGroupUnified unified_requested) { _cleanup_free_ char *cgroup = NULL; char tree[] = "/tmp/unifiedXXXXXX", pid_string[DECIMAL_STR_MAX(pid) + 1]; bool undo_mount = false; const char *fn; int unified, r; unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER); if (unified < 0) return log_error_errno(unified, "Failed to determine whether the unified hierarchy is used: %m"); if ((unified > 0) == (unified_requested >= CGROUP_UNIFIED_SYSTEMD)) return 0; /* When the host uses the legacy cgroup setup, but the * container shall use the unified hierarchy, let's make sure * we copy the path from the name=systemd hierarchy into the * unified hierarchy. Similar for the reverse situation. */ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); if (r < 0) return log_error_errno(r, "Failed to get control group of " PID_FMT ": %m", pid); /* In order to access the unified hierarchy we need to mount it */ if (!mkdtemp(tree)) return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m"); if (unified) r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); else r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); if (r < 0) goto finish; undo_mount = true; fn = strjoina(tree, cgroup, "/cgroup.procs"); (void) mkdir_parents(fn, 0755); sprintf(pid_string, PID_FMT, pid); r = write_string_file(fn, pid_string, 0); if (r < 0) log_error_errno(r, "Failed to move process: %m"); finish: if (undo_mount) (void) umount_verbose(tree); (void) rmdir(tree); return r; }
static int make_overlay(const char *path) { _cleanup_free_ char *escaped_path = NULL; bool tmpfs_mounted = false; const char *options = NULL; int r; assert(path); r = mkdir_p("/run/systemd/overlay-sysroot", 0700); if (r < 0) return log_error_errno(r, "Couldn't create overlay sysroot directory: %m"); r = mount_verbose(LOG_ERR, "tmpfs", "/run/systemd/overlay-sysroot", "tmpfs", MS_STRICTATIME, "mode=755"); if (r < 0) goto finish; tmpfs_mounted = true; if (mkdir("/run/systemd/overlay-sysroot/upper", 0755) < 0) { r = log_error_errno(errno, "Failed to create /run/systemd/overlay-sysroot/upper: %m"); goto finish; } if (mkdir("/run/systemd/overlay-sysroot/work", 0755) < 0) { r = log_error_errno(errno, "Failed to create /run/systemd/overlay-sysroot/work: %m"); goto finish; } escaped_path = shell_escape(path, ",:"); if (!escaped_path) { r = log_oom(); goto finish; } options = strjoina("lowerdir=", escaped_path, ",upperdir=/run/systemd/overlay-sysroot/upper,workdir=/run/systemd/overlay-sysroot/work"); r = mount_verbose(LOG_ERR, "overlay", path, "overlay", 0, options); finish: if (tmpfs_mounted) (void) umount_verbose("/run/systemd/overlay-sysroot"); (void) rmdir("/run/systemd/overlay-sysroot"); return r; }
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]; bool undo_mount = false; const char *fn; int r, unified_controller; unified_controller = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); if (unified_controller < 0) return log_error_errno(unified_controller, "Failed to determine whether the systemd hierarchy is unified: %m"); if ((unified_controller > 0) == (unified_requested >= CGROUP_UNIFIED_SYSTEMD)) return 0; /* When the host uses the legacy cgroup setup, but the * container shall use the unified hierarchy, let's make sure * we copy the path from the name=systemd hierarchy into the * unified hierarchy. Similar for the reverse situation. */ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); if (r < 0) return log_error_errno(r, "Failed to get control group of " PID_FMT ": %m", pid); /* In order to access the unified hierarchy we need to mount it */ if (!mkdtemp(tree)) return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m"); if (unified_controller > 0) r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup", MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); else r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); if (r < 0) goto finish; undo_mount = true; /* If nspawn dies abruptly the cgroup hierarchy created below * its unit isn't cleaned up. So, let's remove it * https://github.com/systemd/systemd/pull/4223#issuecomment-252519810 */ fn = strjoina(tree, cgroup); (void) rm_rf(fn, REMOVE_ROOT|REMOVE_ONLY_DIRECTORIES); fn = strjoina(tree, cgroup, "/cgroup.procs"); (void) mkdir_parents(fn, 0755); sprintf(pid_string, PID_FMT, pid); r = write_string_file(fn, pid_string, 0); if (r < 0) { log_error_errno(r, "Failed to move process: %m"); goto finish; } fn = strjoina(tree, cgroup); r = chown_cgroup_path(fn, uid_shift); if (r < 0) log_error_errno(r, "Failed to chown() cgroup %s: %m", fn); finish: if (undo_mount) (void) umount_verbose(tree); (void) rmdir(tree); return r; }