diff options
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/cgroup-label.c | 11 | ||||
-rw-r--r-- | src/shared/cgroup-show.c | 1 | ||||
-rw-r--r-- | src/shared/cgroup-util.c | 269 | ||||
-rw-r--r-- | src/shared/cgroup-util.h | 24 | ||||
-rw-r--r-- | src/shared/fileio.c | 1 | ||||
-rw-r--r-- | src/shared/mkdir.c | 74 | ||||
-rw-r--r-- | src/shared/mkdir.h | 8 |
7 files changed, 244 insertions, 144 deletions
diff --git a/src/shared/cgroup-label.c b/src/shared/cgroup-label.c index 5b5163c250..574a7be3ee 100644 --- a/src/shared/cgroup-label.c +++ b/src/shared/cgroup-label.c @@ -36,15 +36,18 @@ #include "util.h" #include "mkdir.h" -int cg_create(const char *controller, const char *path, const char *suffix) { +/* This is split out since it needs label calls, either directly or + * indirectly. */ + +int cg_create(const char *controller, const char *path) { _cleanup_free_ char *fs = NULL; int r; - r = cg_get_path_and_check(controller, path, suffix, &fs); + r = cg_get_path_and_check(controller, path, NULL, &fs); if (r < 0) return r; - r = mkdir_parents_label(fs, 0755); + r = mkdir_parents_prefix("/sys/fs/cgroup", fs, 0755); if (r < 0) return r; @@ -64,7 +67,7 @@ int cg_create_and_attach(const char *controller, const char *path, pid_t pid) { assert(pid >= 0); - r = cg_create(controller, path, NULL); + r = cg_create(controller, path); if (r < 0) return r; diff --git a/src/shared/cgroup-show.c b/src/shared/cgroup-show.c index 83cc0731b8..e971f36190 100644 --- a/src/shared/cgroup-show.c +++ b/src/shared/cgroup-show.c @@ -241,7 +241,6 @@ static int show_extra_pids(const char *controller, const char *path, const char unsigned i, j; int r; - assert(controller); assert(path); if (n_pids <= 0) diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 9cbc64a541..5816b7d4d6 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -132,7 +132,7 @@ int cg_read_subgroup(DIR *d, char **fn) { return 0; } -int cg_rmdir(const char *controller, const char *path, bool honour_sticky) { +int cg_rmdir(const char *controller, const char *path) { _cleanup_free_ char *p = NULL; int r; @@ -140,34 +140,6 @@ int cg_rmdir(const char *controller, const char *path, bool honour_sticky) { if (r < 0) return r; - if (honour_sticky) { - char *fn; - - /* If the sticky bit is set on cgroup.procs, don't - * remove the directory */ - - fn = strappend(p, "/cgroup.procs"); - if (!fn) - return -ENOMEM; - - r = file_is_priv_sticky(fn); - free(fn); - - if (r > 0) - return 0; - - /* Compatibility ... */ - fn = strappend(p, "/tasks"); - if (!fn) - return -ENOMEM; - - r = file_is_priv_sticky(fn); - free(fn); - - if (r > 0) - return 0; - } - r = rmdir(p); if (r < 0 && errno != ENOENT) return -errno; @@ -298,7 +270,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si ret = r; if (rem) { - r = cg_rmdir(controller, path, true); + r = cg_rmdir(controller, path); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; } @@ -407,7 +379,14 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char return ret; } -int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem) { +int cg_migrate_recursive( + const char *cfrom, + const char *pfrom, + const char *cto, + const char *pto, + bool ignore_self, + bool rem) { + _cleanup_closedir_ DIR *d = NULL; int r, ret = 0; char *fn; @@ -448,7 +427,7 @@ int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, ret = r; if (rem) { - r = cg_rmdir(cfrom, pfrom, true); + r = cg_rmdir(cfrom, pfrom); if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY) return r; } @@ -558,8 +537,9 @@ int cg_get_path_and_check(const char *controller, const char *path, const char * } static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { - char *p; - bool is_sticky; + assert(path); + assert(sb); + assert(ftwbuf); if (typeflag != FTW_DP) return 0; @@ -567,31 +547,6 @@ static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct if (ftwbuf->level < 1) return 0; - p = strappend(path, "/cgroup.procs"); - if (!p) { - errno = ENOMEM; - return 1; - } - - is_sticky = file_is_priv_sticky(p) > 0; - free(p); - - if (is_sticky) - return 0; - - /* Compatibility */ - p = strappend(path, "/tasks"); - if (!p) { - errno = ENOMEM; - return 1; - } - - is_sticky = file_is_priv_sticky(p) > 0; - free(p); - - if (is_sticky) - return 0; - rmdir(path); return 0; } @@ -611,28 +566,8 @@ int cg_trim(const char *controller, const char *path, bool delete_root) { r = errno ? -errno : -EIO; if (delete_root) { - bool is_sticky; - char *p; - - p = strappend(fs, "/cgroup.procs"); - if (!p) - return -ENOMEM; - - is_sticky = file_is_priv_sticky(p) > 0; - free(p); - - if (!is_sticky) { - p = strappend(fs, "/tasks"); - if (!p) - return -ENOMEM; - - is_sticky = file_is_priv_sticky(p) > 0; - free(p); - } - - if (!is_sticky) - if (rmdir(fs) < 0 && errno != ENOENT && r == 0) - return -errno; + if (rmdir(fs) < 0 && errno != ENOENT) + return -errno; } return r; @@ -699,15 +634,14 @@ int cg_set_task_access( const char *path, mode_t mode, uid_t uid, - gid_t gid, - int sticky) { + gid_t gid) { _cleanup_free_ char *fs = NULL, *procs = NULL; int r; assert(path); - if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0) + if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1) return 0; if (mode != (mode_t) -1) @@ -717,28 +651,6 @@ int cg_set_task_access( if (r < 0) return r; - if (sticky >= 0 && mode != (mode_t) -1) - /* Both mode and sticky param are passed */ - mode |= (sticky ? S_ISVTX : 0); - else if ((sticky >= 0 && mode == (mode_t) -1) || - (mode != (mode_t) -1 && sticky < 0)) { - struct stat st; - - /* Only one param is passed, hence read the current - * mode from the file itself */ - - r = lstat(fs, &st); - if (r < 0) - return -errno; - - if (mode == (mode_t) -1) - /* No mode set, we just shall set the sticky bit */ - mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0); - else - /* Only mode set, leave sticky bit untouched */ - mode = (st.st_mode & ~0777) | mode; - } - r = chmod_and_chown(fs, mode, uid, gid); if (r < 0) return r; @@ -1688,3 +1600,148 @@ int cg_slice_to_path(const char *unit, char **ret) { return 0; } + +int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) { + _cleanup_free_ char *p = NULL; + int r; + + r = cg_get_path(controller, path, attribute, &p); + if (r < 0) + return r; + + return write_string_file(p, value); +} + +static const char mask_names[] = + "cpu\0" + "cpuacct\0" + "blkio\0" + "memory\0" + "devices\0"; + +int cg_create_with_mask(CGroupControllerMask mask, const char *path) { + CGroupControllerMask bit = 1; + const char *n; + int r; + + /* This one will create a cgroup in our private tree, but also + * duplicate it in the trees specified in mask, and remove it + * in all others */ + + /* First create the cgroup in our own hierarchy. */ + r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path); + if (r < 0) + return r; + + /* Then, do the same in the other hierarchies */ + NULSTR_FOREACH(n, mask_names) { + if (bit & mask) + cg_create(n, path); + else + cg_trim(n, path, true); + + bit <<= 1; + } + + return r; +} + +int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid) { + CGroupControllerMask bit = 1; + const char *n; + int r; + + r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid); + + NULSTR_FOREACH(n, mask_names) { + if (bit & mask) + cg_attach(n, path, pid); + else { + char prefix[strlen(path) + 1], *slash; + + /* OK, this one is a bit harder... Now we need + * to add to the closest parent cgroup we + * can find */ + strcpy(prefix, path); + while ((slash = strrchr(prefix, '/'))) { + int q; + *slash = 0; + + q = cg_attach(n, prefix, pid); + if (q >= 0) + break; + } + } + + bit <<= 1; + } + + return r; +} + +int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to) { + CGroupControllerMask bit = 1; + const char *n; + int r; + + if (path_equal(from, to)) + return 0; + + r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true); + + NULSTR_FOREACH(n, mask_names) { + if (bit & mask) + cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false); + else { + char prefix[strlen(to) + 1], *slash; + + strcpy(prefix, to); + while ((slash = strrchr(prefix, '/'))) { + int q; + + *slash = 0; + + q = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, prefix, false, false); + if (q >= 0) + break; + } + } + + bit <<= 1; + } + + return r; +} + +int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root) { + CGroupControllerMask bit = 1; + const char *n; + int r; + + r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root); + if (r < 0) + return r; + + NULSTR_FOREACH(n, mask_names) { + if (bit & mask) + cg_trim(n, path, delete_root); + + bit <<= 1; + } + + return r; +} + +CGroupControllerMask cg_mask_supported(void) { + CGroupControllerMask bit = 1, mask = 0; + const char *n; + + NULSTR_FOREACH(n, mask_names) { + if (check_hierarchy(n) >= 0) + mask |= bit; + + bit <<= 1; + } + + return mask; +} diff --git a/src/shared/cgroup-util.h b/src/shared/cgroup-util.h index 2d00bb3fff..9883d941c2 100644 --- a/src/shared/cgroup-util.h +++ b/src/shared/cgroup-util.h @@ -28,6 +28,15 @@ #include "set.h" #include "def.h" +/* A bit mask of well known cgroup controllers */ +typedef enum CGroupControllerMask { + CGROUP_CPU = 1, + CGROUP_CPUACCT = 2, + CGROUP_BLKIO = 4, + CGROUP_MEMORY = 8, + CGROUP_DEVICE = 16 +} CGroupControllerMask; + /* * General rules: * @@ -67,15 +76,17 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path); int cg_trim(const char *controller, const char *path, bool delete_root); -int cg_rmdir(const char *controller, const char *path, bool honour_sticky); +int cg_rmdir(const char *controller, const char *path); int cg_delete(const char *controller, const char *path); -int cg_create(const char *controller, const char *path, const char *suffix); +int cg_create(const char *controller, const char *path); int cg_attach(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_attribute(const char *controller, const char *path, const char *attribute, const char *value); + int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); -int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid, int sticky); +int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid); int cg_install_release_agent(const char *controller, const char *agent); @@ -113,3 +124,10 @@ char *cg_unescape(const char *p) _pure_; bool cg_controller_is_valid(const char *p, bool allow_named); int cg_slice_to_path(const char *unit, char **ret); + +int cg_create_with_mask(CGroupControllerMask mask, const char *path); +int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid); +int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to); +int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root); + +CGroupControllerMask cg_mask_supported(void); diff --git a/src/shared/fileio.c b/src/shared/fileio.c index ad068bf30d..dc13c9ee63 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -24,7 +24,6 @@ #include "util.h" #include "strv.h" - int write_string_to_file(FILE *f, const char *line) { errno = 0; fputs(line, f); diff --git a/src/shared/mkdir.c b/src/shared/mkdir.c index 0e51b64f69..e21a0f3989 100644 --- a/src/shared/mkdir.c +++ b/src/shared/mkdir.c @@ -26,15 +26,16 @@ #include <stdlib.h> #include <stdio.h> -#include "mkdir.h" #include "label.h" #include "util.h" +#include "path-util.h" +#include "mkdir.h" int mkdir_label(const char *path, mode_t mode) { return label_mkdir(path, mode, true); } -static int makedir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, bool apply) { +static int mkdir_safe_internal(const char *path, mode_t mode, uid_t uid, gid_t gid, bool apply) { struct stat st; if (label_mkdir(path, mode, apply) >= 0) @@ -56,36 +57,50 @@ static int makedir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid, boo } int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid) { - return makedir_safe(path, mode, uid, gid, false); + return mkdir_safe_internal(path, mode, uid, gid, false); } int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid) { - return makedir_safe(path, mode, uid, gid, true); + return mkdir_safe_internal(path, mode, uid, gid, true); } -static int makedir_parents(const char *path, mode_t mode, bool apply) { +static int is_dir(const char* path) { struct stat st; + + if (stat(path, &st) < 0) + return -errno; + + return S_ISDIR(st.st_mode); +} + +static int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, bool apply) { const char *p, *e; + int r; assert(path); + if (prefix && !path_startswith(path, prefix)) + return -ENOTDIR; + /* return immediately if directory exists */ e = strrchr(path, '/'); if (!e) return -EINVAL; + + if (e == path) + return 0; + p = strndupa(path, e - path); - if (stat(p, &st) >= 0) { - if ((st.st_mode & S_IFMT) == S_IFDIR) - return 0; - else - return -ENOTDIR; - } + r = is_dir(p); + if (r > 0) + return 0; + if (r == 0) + return -ENOTDIR; /* create every parent directory in the path, except the last component */ p = path + strspn(path, "/"); for (;;) { - int r; - char *t; + char t[strlen(path) + 1]; e = p + strcspn(p, "/"); p = e + strspn(e, "/"); @@ -95,39 +110,36 @@ static int makedir_parents(const char *path, mode_t mode, bool apply) { if (*p == 0) return 0; - t = strndup(path, e - path); - if (!t) - return -ENOMEM; + memcpy(t, path, e - path); + t[e-path] = 0; - r = label_mkdir(t, mode, apply); - free(t); + if (prefix && path_startswith(prefix, t)) + continue; + r = label_mkdir(t, mode, apply); if (r < 0 && errno != EEXIST) return -errno; } } int mkdir_parents(const char *path, mode_t mode) { - return makedir_parents(path, mode, false); + return mkdir_parents_internal(NULL, path, mode, false); } int mkdir_parents_label(const char *path, mode_t mode) { - return makedir_parents(path, mode, true); + return mkdir_parents_internal(NULL, path, mode, true); } -static int is_dir(const char* path) { - struct stat st; - if (stat(path, &st) < 0) - return -errno; - return S_ISDIR(st.st_mode); +int mkdir_parents_prefix(const char *prefix, const char *path, mode_t mode) { + return mkdir_parents_internal(prefix, path, mode, true); } -static int makedir_p(const char *path, mode_t mode, bool apply) { +static int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, bool apply) { int r; /* Like mkdir -p */ - r = makedir_parents(path, mode, apply); + r = mkdir_parents_internal(prefix, path, mode, apply); if (r < 0) return r; @@ -139,9 +151,13 @@ static int makedir_p(const char *path, mode_t mode, bool apply) { } int mkdir_p(const char *path, mode_t mode) { - return makedir_p(path, mode, false); + return mkdir_p_internal(NULL, path, mode, false); } int mkdir_p_label(const char *path, mode_t mode) { - return makedir_p(path, mode, true); + return mkdir_p_internal(NULL, path, mode, true); +} + +int mkdir_p_prefix(const char *prefix, const char *path, mode_t mode) { + return mkdir_p_internal(prefix, path, mode, false); } diff --git a/src/shared/mkdir.h b/src/shared/mkdir.h index ce1c35e9ba..3d39b2910f 100644 --- a/src/shared/mkdir.h +++ b/src/shared/mkdir.h @@ -22,11 +22,19 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ +#include <sys/types.h> + int mkdir_label(const char *path, mode_t mode); + int mkdir_safe(const char *path, mode_t mode, uid_t uid, gid_t gid); int mkdir_safe_label(const char *path, mode_t mode, uid_t uid, gid_t gid); + int mkdir_parents(const char *path, mode_t mode); int mkdir_parents_label(const char *path, mode_t mode); +int mkdir_parents_prefix(const char *prefix, const char *path, mode_t mode); + int mkdir_p(const char *path, mode_t mode); int mkdir_p_label(const char *path, mode_t mode); +int mkdir_p_prefix(const char *prefix, const char *path, mode_t mode); + #endif |