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.

The primary intelligence is implemented in cg_chmod_path function which
takes an argument which says whether user permissions should be used
as a template.

This patch adds and exports cgroup_set_permissions which sets
permissions of all cgroup files according to cgroup data structure. It
uses cg_chmod_recursive_controller and cg_chmod_path internally.

Example:
/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 |    8 ++++
 src/api.c                  |   80 +++++++++++++++++++++++++++++++++-----------
 src/libcgroup-internal.h   |   11 ++++++
 src/libcgroup.map          |    2 +-
 src/tools/cgcreate.c       |    5 ++-
 5 files changed, 83 insertions(+), 23 deletions(-)

diff --git a/include/libcgroup/groups.h b/include/libcgroup/groups.h
index 61f18a0..3271c52 100644
--- a/include/libcgroup/groups.h
+++ b/include/libcgroup/groups.h
@@ -341,6 +341,14 @@ int cgroup_get_uid_gid(struct cgroup *cgroup, uid_t 
*tasks_uid,
                gid_t *tasks_gid, uid_t *control_uid, gid_t *control_gid);
 
 /**
+ * Sets file permissions of the group's control and tasks files according
+ * to the configuration stored in the given @c cgroup structure.
+ * @param path Path to the group.
+ * @param cgroup
+ */
+int cgroup_set_permissions(const char *path, struct cgroup *cgroup);
+
+/**
  * @}
  * @name Group parameters
  * These are functions can read or modify parameter of a group.
diff --git a/src/api.c b/src/api.c
index 23772f3..c3d5a9d 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,20 +225,16 @@ 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;
 }
 
@@ -212,7 +243,7 @@ int cg_chmod_file(FTS *fts, FTSENT *ent, mode_t dir_mode,
  * TODO: Need to decide a better place to put this function.
  */
 static int cg_chmod_recursive_controller(char *path, 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;
        int final_ret =0;
@@ -239,7 +270,7 @@ static int cg_chmod_recursive_controller(char *path, 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;
@@ -269,7 +300,7 @@ int cg_chmod_recursive(struct cgroup *cgroup, mode_t 
dir_mode,
                        break;
                }
                ret = cg_chmod_recursive_controller(path, dir_mode, dirm_change,
-                               file_mode, filem_change);
+                               file_mode, filem_change, 0);
                if (ret)
                        final_ret = ret;
        }
@@ -277,6 +308,23 @@ int cg_chmod_recursive(struct cgroup *cgroup, mode_t 
dir_mode,
        return final_ret;
 }
 
+int cgroup_set_permissions(const char *path, struct cgroup *cgroup)
+{
+       int error;
+
+       error = cg_chmod_recursive_controller(path,
+                       cgroup->control_dperm,
+                       cgroup->control_dperm != NO_PERMS,
+                       cgroup->control_fperm,
+                       cgroup->control_fperm != NO_PERMS,
+                       1);
+
+       if (!error && cgroup->task_fperm != NO_PERMS)
+               error = cg_chmod_path(path, cgroup->task_fperm, 1);
+
+       return error;
+
+}
 static char *cgroup_basename(const char *path)
 {
        char *base;
@@ -1475,13 +1523,8 @@ int cgroup_create_cgroup(struct cgroup *cgroup, int 
ignore_ownership)
                        cgroup_dbg("Changing ownership of %s\n", fts_path[0]);
                        error = cg_chown_recursive(fts_path,
                                cgroup->control_uid, cgroup->control_gid);
-                       if (!error) {
-                               error = 
cg_chmod_recursive_controller(fts_path[0],
-                                                               
cgroup->control_dperm,
-                                                               
cgroup->control_dperm != NO_PERMS,
-                                                               
cgroup->control_fperm,
-                                                               
cgroup->control_fperm != NO_PERMS);
-                       }
+                       if (!error)
+                               error = cgroup_set_permissions(fts_path[0], 
cgroup);
                }
 
                if (error)
@@ -1528,9 +1571,6 @@ 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);
-
                        if (error) {
                                last_errno = errno;
                                error = ECGOTHER;
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
index e79c038..b57a887 100644
--- a/src/libcgroup-internal.h
+++ b/src/libcgroup-internal.h
@@ -250,6 +250,17 @@ extern int cgroup_dictionary_iterator_next(void **handle,
  */
 extern void cgroup_dictionary_iterator_end(void **handle);
 
+/**
+ * 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);
+
 __END_DECLS
 
 #endif
diff --git a/src/libcgroup.map b/src/libcgroup.map
index fb30801..f1afaf6 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;
+       cgroup_set_permissions;
 } CGROUP_0.37;
-
diff --git a/src/tools/cgcreate.c b/src/tools/cgcreate.c
index 7312b32..96f65da 100644
--- a/src/tools/cgcreate.c
+++ b/src/tools/cgcreate.c
@@ -311,8 +311,9 @@ int main(int argc, char *argv[])
                        goto err;
                }
                if (dirm_change + filem_change > 0) {
-                       ret = cg_chmod_recursive(cgroup, dir_mode, dirm_change,
-                               file_mode, filem_change);
+                       cgroup->control_dperm = dir_mode;
+                       cgroup->control_fperm = cgroup->task_fperm = file_mode;
+                       ret = cgroup_set_permissions(cgroup_list[i]->path, 
cgroup);
                        if (ret) {
                                fprintf(stderr, "%s: can't change permission " \
                                        "of cgroup %s: %s\n", argv[0],
-- 
1.7.5.3


------------------------------------------------------------------------------
EditLive Enterprise is the world's most technically advanced content
authoring tool. Experience the power of Track Changes, Inline Image
Editing and ensure content is compliant with Accessibility Checking.
http://p.sf.net/sfu/ephox-dev2dev
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to