Merge tag 'backlight-for-linus-3.15' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / kernel / cgroup.c
index fede3d3..9fcdaa7 100644 (file)
@@ -1487,6 +1487,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
        struct cgroup_sb_opts opts;
        struct dentry *dentry;
        int ret;
+       bool new_sb;
 
        /*
         * The first time anyone tries to mount a cgroup, enable the list
@@ -1603,8 +1604,8 @@ out_unlock:
        if (ret)
                return ERR_PTR(ret);
 
-       dentry = kernfs_mount(fs_type, flags, root->kf_root, NULL);
-       if (IS_ERR(dentry))
+       dentry = kernfs_mount(fs_type, flags, root->kf_root, &new_sb);
+       if (IS_ERR(dentry) || !new_sb)
                cgroup_put(&root->cgrp);
        return dentry;
 }
@@ -2345,11 +2346,26 @@ static int cgroup_rename(struct kernfs_node *kn, struct kernfs_node *new_parent,
        return ret;
 }
 
+/* set uid and gid of cgroup dirs and files to that of the creator */
+static int cgroup_kn_set_ugid(struct kernfs_node *kn)
+{
+       struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
+                              .ia_uid = current_fsuid(),
+                              .ia_gid = current_fsgid(), };
+
+       if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
+           gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
+               return 0;
+
+       return kernfs_setattr(kn, &iattr);
+}
+
 static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
 {
        char name[CGROUP_FILE_NAME_MAX];
        struct kernfs_node *kn;
        struct lock_class_key *key = NULL;
+       int ret;
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
        key = &cft->lockdep_key;
@@ -2357,7 +2373,13 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft)
        kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name),
                                  cgroup_file_mode(cft), 0, cft->kf_ops, cft,
                                  NULL, false, key);
-       return PTR_ERR_OR_ZERO(kn);
+       if (IS_ERR(kn))
+               return PTR_ERR(kn);
+
+       ret = cgroup_kn_set_ugid(kn);
+       if (ret)
+               kernfs_remove(kn);
+       return ret;
 }
 
 /**
@@ -3752,6 +3774,10 @@ static long cgroup_create(struct cgroup *parent, const char *name,
         */
        idr_replace(&root->cgroup_idr, cgrp, cgrp->id);
 
+       err = cgroup_kn_set_ugid(kn);
+       if (err)
+               goto err_destroy;
+
        err = cgroup_addrm_files(cgrp, cgroup_base_files, true);
        if (err)
                goto err_destroy;