X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fcgroup-util.c;h=acace52bc8daaa7ab2299e85f2108fec27e63762;hb=e3ded78be7df143ba780dd55ca8897fdddd67460;hp=3d12233a1b394bd8b04a2ff0e5ed4ab1410b6fac;hpb=ef1673d16907726d83bdff2e57b5261997a85020;p=elogind.git diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 3d12233a1..acace52bc 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -990,6 +990,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); @@ -1007,7 +1009,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) { @@ -1024,29 +1026,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; } @@ -1211,75 +1218,63 @@ int cg_pid_get_cgroup(pid_t pid, char **root, char **cgroup) { return 0; } -static int instance_unit_from_cgroup(char **cgroup){ +static int instance_unit_from_cgroup(char *cgroup){ char *at; assert(cgroup); - at = memchr(*cgroup, '@', strlen(*cgroup)); - if (at && at[1] == '.') { - char *i, *s; - + at = strstr(cgroup, "@."); + if (at) { /* This is a templated service */ - i = memchr(at, '/', strlen(at)); - if(!i) - return -EIO; - s = strndup(at + 1, i - at); - if (!s) - return -ENOMEM; + char *i; + char _cleanup_free_ *i2 = NULL, *s = NULL; - i = strdup(i + 1); - if (!i) { - free(s); - return -ENOMEM; - } + i = strchr(at, '/'); + if (!i || !i[1]) /* disallow empty instances */ + return -EINVAL; - strcpy(at + 1, i); - strcpy(at + strlen(i) + 1, s); - at[strlen(at) - 1] = '\0'; + s = strndup(at + 1, i - at - 1); + i2 = strdup(i + 1); + if (!s || !i2) + return -ENOMEM; - free(i); - free(s); + strcpy(at + 1, i2); + strcat(at + 1, s); } return 0; } -static int cgroup_to_unit(char *cgroup, char **unit){ +/* non-static only for testing purposes */ +int cgroup_to_unit(char *cgroup, char **unit){ int r; - char *b, *p; - size_t k; + char *p; assert(cgroup); assert(unit); - r = instance_unit_from_cgroup(&cgroup); + r = instance_unit_from_cgroup(cgroup); if (r < 0) return r; - p = strrchr(cgroup, '/') + 1; - k = strlen(p); + p = strrchr(cgroup, '/'); + assert(p); - b = strndup(p, k); + r = unit_name_is_valid(p + 1, true); + if (!r) + return -EINVAL; - if (!b) + *unit = strdup(p + 1); + if (!*unit) return -ENOMEM; - r = unit_name_is_valid(b, true); - if (!r) { - free(b); - return -ENOENT; - } - - *unit = b; - return 0; } -int cg_pid_get_unit(pid_t pid, char **unit) { +static int cg_pid_get(const char *prefix, pid_t pid, char **unit) { int r; - char *cgroup; + char _cleanup_free_ *cgroup = NULL; assert(pid >= 0); assert(unit); @@ -1288,45 +1283,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; - } r = cgroup_to_unit(cgroup, unit); - if (r < 0){ - free(cgroup); - return r; - } - - free(cgroup); + return r; +} - return 0; +int cg_pid_get_unit(pid_t pid, char **unit) { + return cg_pid_get("/system/", pid, unit); } int cg_pid_get_user_unit(pid_t pid, char **unit) { - int r; - char *cgroup; + return cg_pid_get("/user/", pid, unit); +} - assert(pid >= 0); - assert(unit); +int cg_controller_from_attr(const char *attr, char **controller) { + const char *dot; + char *c; - r = cg_pid_get_cgroup(pid, NULL, &cgroup); - if (r < 0) - return r; + assert(attr); + assert(controller); - if (!startswith(cgroup, "/user/")) { - free(cgroup); - return -ENOENT; - } + if (!filename_is_safe(attr)) + return -EINVAL; - r = cgroup_to_unit(cgroup, unit); - if (r < 0) { - free(cgroup); - return r; + dot = strchr(attr, '.'); + if (!dot) { + *controller = NULL; + return 0; } - free(cgroup); + c = strndup(attr, dot - attr); + if (!c) + return -ENOMEM; - return 0; + if (!filename_is_safe(c)) { + free(c); + return -EINVAL; + } + + *controller = c; + return 1; }