X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fcgroup-util.c;h=be00b40fa2346afb2ebf43ab6847d4d61a025f6f;hb=518dc5dff557116db3f072eb9d0a9492b6226778;hp=9dfab2eaacf8d9a8b5584127cbd29a763f620b02;hpb=246aa6dd9dcea84bb945d16ec86e69f869dbb9b4;p=elogind.git diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 9dfab2eaa..be00b40fa 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -36,6 +36,8 @@ #include "util.h" #include "path-util.h" #include "strv.h" +#include "unit-name.h" +#include "fileio.h" int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) { char *fs; @@ -810,7 +812,7 @@ int cg_get_by_pid(const char *controller, pid_t pid, char **path) { continue; l++; - if (strncmp(l, controller, cs) != 0) + if (!strneq(l, controller, cs)) continue; if (l[cs] != ':') @@ -989,6 +991,8 @@ int cg_split_spec(const char *spec, char **controller, char **path) { assert(spec); if (*spec == '/') { + if (!path_is_safe(spec)) + return -EINVAL; if (path) { t = strdup(spec); @@ -1006,7 +1010,7 @@ int cg_split_spec(const char *spec, char **controller, char **path) { e = strchr(spec, ':'); if (!e) { - if (strchr(spec, '/') || spec[0] == 0) + if (!filename_is_safe(spec)) return -EINVAL; if (controller) { @@ -1023,29 +1027,34 @@ int cg_split_spec(const char *spec, char **controller, char **path) { return 0; } - if (e[1] != '/' || e == spec || memchr(spec, '/', e-spec)) + t = strndup(spec, e-spec); + if (!t) + return -ENOMEM; + if (!filename_is_safe(t)) { + free(t); return -EINVAL; - - if (controller) { - t = strndup(spec, e-spec); - if (!t) - return -ENOMEM; - } - if (path) { - u = strdup(e+1); - if (!u) { - free(t); - return -ENOMEM; - } + u = strdup(e+1); + if (!u) { + free(t); + return -ENOMEM; + } + if (!path_is_safe(u)) { + free(t); + free(u); + return -EINVAL; } if (controller) *controller = t; + else + free(t); if (path) *path = u; + else + free(u); return 0; } @@ -1210,10 +1219,63 @@ int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) { return 0; } -int cg_pid_get_unit(pid_t pid, char **unit) { +static int instance_unit_from_cgroup(char *cgroup){ + char *at; + + assert(cgroup); + + at = strstr(cgroup, "@."); + if (at) { + /* This is a templated service */ + + char *i; + char _cleanup_free_ *i2 = NULL, *s = NULL; + + i = strchr(at, '/'); + if (!i || !i[1]) /* disallow empty instances */ + return -EINVAL; + + s = strndup(at + 1, i - at - 1); + i2 = strdup(i + 1); + if (!s || !i2) + return -ENOMEM; + + strcpy(at + 1, i2); + strcat(at + 1, s); + } + + return 0; +} + +/* non-static only for testing purposes */ +int cgroup_to_unit(char *cgroup, char **unit){ int r; - char *cgroup, *p, *at, *b; - size_t k; + char *p; + + assert(cgroup); + assert(unit); + + r = instance_unit_from_cgroup(cgroup); + if (r < 0) + return r; + + p = strrchr(cgroup, '/'); + assert(p); + + r = unit_name_is_valid(p + 1, true); + if (!r) + return -EINVAL; + + *unit = strdup(p + 1); + if (!*unit) + return -ENOMEM; + + return 0; +} + +static int cg_pid_get(const char *prefix, pid_t pid, char **unit) { + int r; + char _cleanup_free_ *cgroup = NULL; assert(pid >= 0); assert(unit); @@ -1222,43 +1284,46 @@ int cg_pid_get_unit(pid_t pid, char **unit) { if (r < 0) return r; - if (!startswith(cgroup, "/system/")) { - free(cgroup); + if (!startswith(cgroup, prefix)) return -ENOENT; - } - p = cgroup + 8; - k = strcspn(p, "/"); + r = cgroup_to_unit(cgroup, unit); + return r; +} - at = memchr(p, '@', k); - if (at && at[1] == '.') { - size_t j; +int cg_pid_get_unit(pid_t pid, char **unit) { + return cg_pid_get("/system/", pid, unit); +} - /* This is a templated service */ - if (p[k] != '/') { - free(cgroup); - return -EIO; - } +int cg_pid_get_user_unit(pid_t pid, char **unit) { + return cg_pid_get("/user/", pid, unit); +} - j = strcspn(p+k+1, "/"); +int cg_controller_from_attr(const char *attr, char **controller) { + const char *dot; + char *c; - b = malloc(k + j + 1); + assert(attr); + assert(controller); - if (b) { - memcpy(b, p, at - p + 1); - memcpy(b + (at - p) + 1, p + k + 1, j); - memcpy(b + (at - p) + 1 + j, at + 1, k - (at - p) - 1); - b[k+j] = 0; - } - } else - b = strndup(p, k); + if (!filename_is_safe(attr)) + return -EINVAL; - free(cgroup); + dot = strchr(attr, '.'); + if (!dot) { + *controller = NULL; + return 0; + } - if (!b) + c = strndup(attr, dot - attr); + if (!c) return -ENOMEM; - *unit = b; - return 0; + if (!filename_is_safe(c)) { + free(c); + return -EINVAL; + } + *controller = c; + return 1; }