There is no general rule on which permissions make sense for files in
different subsystems. Nevertheless the kernel creates those files with
the maximum allowed permissions for owner so we should use its part as
an umask for group and others permissions as well.
This means that if we specify 777 for file_mode we will end up having
same permissions as owner what ever they are.

This patch adds cg_chmod_path which can be used for non recursive
permissions setting for path names and cg_owner_mask_chmod_recursive
owner permissions aware variant of cg_chmod_recursive.

/etc/cgconfig.conf:
mount {
        cpu = /cgroup/cpuctl/;
}

group devel {
        perm {
                task {
                        uid = root;
                        gid = cgroup;
                        fperm = 770;
                }
                admin {
                        uid = root;
                        gid = cgroup;
                        dperm = 775;
                        fperm = 770;
                }
        }
        cpu {
                cpu.shares = 5120;
        }
}

cd /cgroup/cpuctl/devel/
ls -la
drwxrwxr-x 2 root cgroup 0 May 19 16:42 .
drwxr-xr-x 4 root root   0 May 19 16:14 ..
-rw-rw---- 1 root cgroup 0 May 19 16:42 cgroup.clone_children
--w--w---- 1 root cgroup 0 May 19 16:42 cgroup.event_control
-r--r----- 1 root cgroup 0 May 19 16:42 cgroup.procs
-rw-rw---- 1 root cgroup 0 May 19 16:42 cpu.rt_period_us
-rw-rw---- 1 root cgroup 0 May 19 16:42 cpu.rt_runtime_us
-rw-rw---- 1 root cgroup 0 May 19 16:42 cpu.shares
-rw-rw---- 1 root cgroup 0 May 19 16:42 notify_on_release
-rw-rw---- 1 root cgroup 0 May 19 16:42 tasks

Signed-off-by: Michal Hocko <mho...@suse.cz>
---
 include/libcgroup/groups.h |   22 +++++++++++++
 src/api.c                  |   73 ++++++++++++++++++++++++++++++++++---------
 src/libcgroup.map          |    2 +-
 src/tools/cgcreate.c       |    2 +-
 4 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/include/libcgroup/groups.h b/include/libcgroup/groups.h
index 61f18a0..ebad462 100644
--- a/include/libcgroup/groups.h
+++ b/include/libcgroup/groups.h
@@ -536,6 +536,28 @@ int cg_chmod_recursive(struct cgroup *cgroup, mode_t 
dir_mode,
        int dirm_change, mode_t file_mode, int filem_change);
 
 /**
+ * Change permission of files and directories of given group and uses
+ * owner permissions as a mask for group and others permissions
+ * @param cgroup The cgroup which permissions should be changed
+ * @param dir_mode The permission mode of group directory
+ * @param dirm_change Denotes whether the directory change should be done
+ * @param file_mode The permission mode of group files
+ * @param filem_change Denotes whether the directory change should be done
+ */
+int cg_owner_mask_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode,
+       int dirm_change, mode_t file_mode, int filem_change);
+
+/** Changes permissions for given path. If owner_is_umask is specified
+ * then it uses owner permissions as a mask for group and others permissions.
+ *
+ * @param path Patch to chmod.
+ * @param mode File permissions to set.
+ * @param owner_is_umask Flag whether path owner permissions should be used
+ * as a mask for group and others permissions.
+ */
+int cg_chmod_path(const char *path, mode_t mode, int owner_is_umask);
+
+/**
  * @}
  * @}
  */
diff --git a/src/api.c b/src/api.c
index eb9f902..d2220c8 100644
--- a/src/api.c
+++ b/src/api.c
@@ -175,12 +175,47 @@ static int cg_chown_recursive(char **path, uid_t owner, 
gid_t group)
        return ret;
 }
 
+int cg_chmod_path(const char *path, mode_t mode, int owner_is_umask)
+{
+       struct stat buf;
+       mode_t mask = -1U;
+
+       if (owner_is_umask) {
+               mode_t umask, gmask, omask;
+
+               /*
+                * Use owner permissions as an umask for group and others
+                * permissions because we trust kernel to initialize owner
+                * permissions to something useful.
+                */
+               if (stat(path, &buf) == -1)
+                       goto fail;
+               umask = S_IRWXU & buf.st_mode;
+               gmask = umask >> 3;
+               omask = gmask >> 3;
+
+               mask = umask|gmask|omask;
+       }
+
+       if (chmod(path, mode & mask))
+               goto fail;
+
+       return 0;
+
+fail:
+       last_errno = errno;
+       return ECGOTHER;
+}
+
 int cg_chmod_file(FTS *fts, FTSENT *ent, mode_t dir_mode,
-       int dirm_change, mode_t file_mode, int filem_change)
+       int dirm_change, mode_t file_mode, int filem_change,
+       int owner_is_umask)
 {
        int ret = 0;
        const char *filename = fts->fts_path;
+
        cgroup_dbg("chmod: seeing file %s\n", filename);
+
        switch (ent->fts_info) {
        case FTS_ERR:
                errno = ent->fts_errno;
@@ -190,29 +225,22 @@ int cg_chmod_file(FTS *fts, FTSENT *ent, mode_t dir_mode,
        case FTS_DNR:
        case FTS_DP:
                if (dirm_change)
-                       ret = chmod(filename, dir_mode);
+                       ret = cg_chmod_path(filename, dir_mode, owner_is_umask);
                break;
        case FTS_F:
        case FTS_NSOK:
        case FTS_NS:
        case FTS_DEFAULT:
                if (filem_change)
-                       ret = chmod(filename, file_mode);
+                       ret = cg_chmod_path(filename, file_mode, 
owner_is_umask);
                break;
        }
-       if (ret < 0) {
-               last_errno = errno;
-               ret = ECGOTHER;
-       }
        return ret;
 }
 
-
-/*
- * TODO: Need to decide a better place to put this function.
- */
-int cg_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode,
-       int dirm_change, mode_t file_mode, int filem_change)
+int __cg_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode,
+       int dirm_change, mode_t file_mode, int filem_change,
+       int owner_is_umask)
 {
        int ret = 0;
        int final_ret =0;
@@ -250,7 +278,7 @@ int cg_chmod_recursive(struct cgroup *cgroup, mode_t 
dir_mode,
                        break;
                }
                ret = cg_chmod_file(fts, ent, dir_mode, dirm_change,
-                       file_mode, filem_change);
+                       file_mode, filem_change, owner_is_umask);
                if (ret) {
                        last_errno = errno;
                        final_ret = ECGOTHER;
@@ -263,6 +291,19 @@ err:
        return final_ret;
 }
 
+int cg_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode,
+       int dirm_change, mode_t file_mode, int filem_change)
+{
+       return __cg_chmod_recursive(cgroup, dir_mode, dirm_change,
+                       file_mode, filem_change, 0);
+}
+
+int cg_owner_mask_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode,
+       int dirm_change, mode_t file_mode, int filem_change)
+{
+       return __cg_chmod_recursive(cgroup, dir_mode, dirm_change,
+                       file_mode, filem_change, 1);
+}
 
 static char *cgroup_basename(const char *path)
 {
@@ -1457,7 +1498,7 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int 
ignore_ownership)
                        error = cg_chown_recursive(fts_path,
                                cgroup->control_uid, cgroup->control_gid);
                        if (!error) {
-                               error = cg_chmod_recursive(cgroup,
+                               error = cg_owner_mask_chmod_recursive(cgroup,
                                                cgroup->control_dperm,
                                                cgroup->control_dperm != 
NO_PERMS,
                                                cgroup->control_fperm,
@@ -1510,7 +1551,7 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int 
ignore_ownership)
                        error = chown(path, cgroup->tasks_uid,
                                                        cgroup->tasks_gid);
                        if (!error && cgroup->task_fperm != NO_PERMS)
-                               error = chmod(path, cgroup->task_fperm);
+                               error = cg_chmod_path(path, cgroup->task_fperm, 
1);
 
                        if (error) {
                                last_errno = errno;
diff --git a/src/libcgroup.map b/src/libcgroup.map
index fb30801..4a5145a 100644
--- a/src/libcgroup.map
+++ b/src/libcgroup.map
@@ -101,5 +101,5 @@ CGROUP_0.38 {
        cgroup_get_subsys_mount_point_begin;
        cgroup_get_subsys_mount_point_next;
        cgroup_get_subsys_mount_point_end;
+       cg_owner_mask_chmod_recursive;
 } CGROUP_0.37;
-
diff --git a/src/tools/cgcreate.c b/src/tools/cgcreate.c
index 7312b32..e510dd1 100644
--- a/src/tools/cgcreate.c
+++ b/src/tools/cgcreate.c
@@ -311,7 +311,7 @@ int main(int argc, char *argv[])
                        goto err;
                }
                if (dirm_change + filem_change > 0) {
-                       ret = cg_chmod_recursive(cgroup, dir_mode, dirm_change,
+                       ret = cg_owner_mask_chmod_recursive(cgroup, dir_mode, 
dirm_change,
                                file_mode, filem_change);
                        if (ret) {
                                fprintf(stderr, "%s: can't change permission " \
-- 
1.7.4.4


------------------------------------------------------------------------------
vRanger cuts backup time in half-while increasing security.
With the market-leading solution for virtual backup and recovery, 
you get blazing-fast, flexible, and affordable data protection.
Download your free trial now. 
http://p.sf.net/sfu/quest-d2dcopy1
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to