From bde80a30bc2c3bff9a57c68ac4bd735aade78544 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Tue, 7 Sep 2010 23:34:52 +0530 Subject: [PATCH] Rewrite cg_mkdir_p so it does not change current working directory. Old sequence of operations when creating e.g. /cgroup/cpu $OLDCWD=$PWD cd / mkdir cgroup cd cgroup mkdir cpu cd $OLDCWD New sequence is: mkdir /cgroup mkdir /cgroup/cpu Some tools, namely those used in /etc/init.d/cgconfig, might be executed with security constrained context, which does not allow them to access certain directories (like /var/log/audit). And when e.g. cgconfigparser is executed in /var/log/audit as current working directory, chdir("/var/log/audit") in cg_mkdir_p() fails. As consequence, "/etc/init.d/cgconfig start" randomly fails or succeeds, depending on current working directory and current SELinux policy. Signed-off-by: Jan Safranek Signed-off-by: Balbir Singh --- src/api.c | 57 +++++++++++-------------------------------------------- 1 file changed, 11 insertions(+), 46 deletions(-) diff --git a/src/api.c b/src/api.c index 492fb515..935fad94 100644 --- a/src/api.c +++ b/src/api.c @@ -1027,20 +1027,9 @@ int cgroup_attach_task(struct cgroup *cgroup) int cg_mkdir_p(const char *path) { char *real_path = NULL; - char *wd = NULL; - int i = 0, j = 0; + int i = 0; char pos; - char *str = NULL; int ret = 0; - char cwd[FILENAME_MAX]; - char *buf = NULL; - - buf = getcwd(cwd, FILENAME_MAX); - - if (!buf) { - last_errno = errno; - return ECGOTHER; - } real_path = strdup(path); if (!real_path) { @@ -1049,23 +1038,16 @@ int cg_mkdir_p(const char *path) } do { - while (real_path[j] != '\0' && real_path[j] != '/') - j++; - while (real_path[j] != '\0' && real_path[j] == '/') - j++; - if (i == j) - continue; - pos = real_path[j]; - real_path[j] = '\0'; /* Temporarily overwrite "/" */ - str = &real_path[i]; - ret = mkdir(str, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - wd = strdup(str); - if (!wd) { - last_errno = errno; - ret = ECGOTHER; - break; - } - real_path[j] = pos; + while (real_path[i] != '\0' && real_path[i] == '/') + i++; + if (real_path[i] == '\0') + break; /* The path ends with '/', ignore it. */ + while (real_path[i] != '\0' && real_path[i] != '/') + i++; + pos = real_path[i]; + real_path[i] = '\0'; /* Temporarily overwrite "/" */ + ret = mkdir(real_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + real_path[i] = pos; if (ret) { switch (errno) { case EEXIST: @@ -1073,31 +1055,14 @@ int cg_mkdir_p(const char *path) break; case EPERM: ret = ECGROUPNOTOWNER; - free(wd); goto done; default: ret = ECGROUPNOTALLOWED; - free(wd); goto done; } } - i = j; - ret = chdir(wd); - if (ret) { - cgroup_dbg("could not chdir to child directory (%s)\n", - wd); - break; - } - free(wd); } while (real_path[i]); - ret = chdir(buf); - if (ret) { - last_errno = errno; - ret = ECGOTHER; - cgroup_dbg("could not go back to old directory (%s)\n", cwd); - } - done: free(real_path); return ret; -- 2.47.2