X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Fcgroup-util.c;h=b2fb324a18c995255e954ff2bc5e644c5d8f0ba9;hb=3474ae3c7e1981301d0b35bc89d759ca13f06e8f;hp=86f354dbe7e8285c6a91fb3b81d2a7f26b509f7c;hpb=80172751b7a678834c1a453ae28c0eb333958250;p=elogind.git diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 86f354dbe..b2fb324a1 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -502,14 +502,47 @@ finish: return ret; } +static const char *normalize_controller(const char *controller) { + + if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + return "systemd"; + else if (startswith(controller, "name=")) + return controller + 5; + else + return controller; +} + +static int join_path(const char *controller, const char *path, const char *suffix, char **fs) { + char *t; + + if (path && suffix) + t = join("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL); + else if (path) + t = join("/sys/fs/cgroup/", controller, "/", path, NULL); + else if (suffix) + t = join("/sys/fs/cgroup/", controller, "/", suffix, NULL); + else + t = join("/sys/fs/cgroup/", controller, NULL); + + if (!t) + return -ENOMEM; + + path_kill_slashes(t); + + *fs = t; + return 0; +} + int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) { const char *p; - char *t; static __thread bool good = false; assert(controller); assert(fs); + if (isempty(controller)) + return -EINVAL; + if (_unlikely_(!good)) { int r; @@ -521,38 +554,30 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch good = true; } - if (isempty(controller)) - return -EINVAL; + p = normalize_controller(controller); - /* This is a very minimal lookup from controller names to - * paths. Since we have mounted most hierarchies ourselves - * should be kinda safe, but eventually we might want to - * extend this to have a fallback to actually check - * /proc/mounts. Might need caching then. */ + return join_path(p, path, suffix, fs); +} - if (streq(controller, SYSTEMD_CGROUP_CONTROLLER)) - p = "systemd"; - else if (startswith(controller, "name=")) - p = controller + 5; - else - p = controller; +int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) { + const char *p; + char *cc; - if (path && suffix) - t = join("/sys/fs/cgroup/", p, "/", path, "/", suffix, NULL); - else if (path) - t = join("/sys/fs/cgroup/", p, "/", path, NULL); - else if (suffix) - t = join("/sys/fs/cgroup/", p, "/", suffix, NULL); - else - t = join("/sys/fs/cgroup/", p, NULL); + assert(controller); + assert(fs); - if (!t) - return -ENOMEM; + if (isempty(controller)) + return -EINVAL; - path_kill_slashes(t); + p = normalize_controller(controller); - *fs = t; - return 0; + /* Check if this controller actually really exists */ + cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p)); + strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p); + if (access(cc, F_OK) < 0) + return -errno; + + return join_path(p, path, suffix, fs); } static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { @@ -646,7 +671,8 @@ int cg_attach(const char *controller, const char *path, pid_t pid) { assert(path); assert(pid >= 0); - if ((r = cg_get_path(controller, path, "tasks", &fs)) < 0) + r = cg_get_path_and_check(controller, path, "tasks", &fs); + if (r < 0) return r; if (pid == 0)