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 <[email protected]>
---
src/api.c | 57 +++++++++++----------------------------------------------
1 files changed, 11 insertions(+), 46 deletions(-)
diff --git a/src/api.c b/src/api.c
index 4bd6b46..66734ed 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1026,20 +1026,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) {
@@ -1048,23 +1037,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:
@@ -1072,31 +1054,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;
------------------------------------------------------------------------------
This SF.net Dev2Dev email is sponsored by:
Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd
_______________________________________________
Libcg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libcg-devel