aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index fe00b3b983a8..891a84eb9d30 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -571,8 +571,8 @@ static struct inode *cgroup_new_inode(mode_t mode, struct super_block *sb)
571 571
572 if (inode) { 572 if (inode) {
573 inode->i_mode = mode; 573 inode->i_mode = mode;
574 inode->i_uid = current->fsuid; 574 inode->i_uid = current_fsuid();
575 inode->i_gid = current->fsgid; 575 inode->i_gid = current_fsgid();
576 inode->i_blocks = 0; 576 inode->i_blocks = 0;
577 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; 577 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
578 inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info; 578 inode->i_mapping->backing_dev_info = &cgroup_backing_dev_info;
@@ -702,7 +702,7 @@ static int rebind_subsystems(struct cgroupfs_root *root,
702 * any child cgroups exist. This is theoretically supportable 702 * any child cgroups exist. This is theoretically supportable
703 * but involves complex error handling, so it's being left until 703 * but involves complex error handling, so it's being left until
704 * later */ 704 * later */
705 if (!list_empty(&cgrp->children)) 705 if (root->number_of_cgroups > 1)
706 return -EBUSY; 706 return -EBUSY;
707 707
708 /* Process each subsystem */ 708 /* Process each subsystem */
@@ -1024,7 +1024,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
1024 if (ret == -EBUSY) { 1024 if (ret == -EBUSY) {
1025 mutex_unlock(&cgroup_mutex); 1025 mutex_unlock(&cgroup_mutex);
1026 mutex_unlock(&inode->i_mutex); 1026 mutex_unlock(&inode->i_mutex);
1027 goto drop_new_super; 1027 goto free_cg_links;
1028 } 1028 }
1029 1029
1030 /* EBUSY should be the only error here */ 1030 /* EBUSY should be the only error here */
@@ -1073,10 +1073,11 @@ static int cgroup_get_sb(struct file_system_type *fs_type,
1073 1073
1074 return simple_set_mnt(mnt, sb); 1074 return simple_set_mnt(mnt, sb);
1075 1075
1076 free_cg_links:
1077 free_cg_links(&tmp_cg_links);
1076 drop_new_super: 1078 drop_new_super:
1077 up_write(&sb->s_umount); 1079 up_write(&sb->s_umount);
1078 deactivate_super(sb); 1080 deactivate_super(sb);
1079 free_cg_links(&tmp_cg_links);
1080 return ret; 1081 return ret;
1081} 1082}
1082 1083
@@ -1279,6 +1280,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1279static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) 1280static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
1280{ 1281{
1281 struct task_struct *tsk; 1282 struct task_struct *tsk;
1283 const struct cred *cred = current_cred(), *tcred;
1282 int ret; 1284 int ret;
1283 1285
1284 if (pid) { 1286 if (pid) {
@@ -1288,14 +1290,16 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid)
1288 rcu_read_unlock(); 1290 rcu_read_unlock();
1289 return -ESRCH; 1291 return -ESRCH;
1290 } 1292 }
1291 get_task_struct(tsk);
1292 rcu_read_unlock();
1293 1293
1294 if ((current->euid) && (current->euid != tsk->uid) 1294 tcred = __task_cred(tsk);
1295 && (current->euid != tsk->suid)) { 1295 if (cred->euid &&
1296 put_task_struct(tsk); 1296 cred->euid != tcred->uid &&
1297 cred->euid != tcred->suid) {
1298 rcu_read_unlock();
1297 return -EACCES; 1299 return -EACCES;
1298 } 1300 }
1301 get_task_struct(tsk);
1302 rcu_read_unlock();
1299 } else { 1303 } else {
1300 tsk = current; 1304 tsk = current;
1301 get_task_struct(tsk); 1305 get_task_struct(tsk);
@@ -2934,9 +2938,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
2934 again: 2938 again:
2935 root = subsys->root; 2939 root = subsys->root;
2936 if (root == &rootnode) { 2940 if (root == &rootnode) {
2937 printk(KERN_INFO
2938 "Not cloning cgroup for unused subsystem %s\n",
2939 subsys->name);
2940 mutex_unlock(&cgroup_mutex); 2941 mutex_unlock(&cgroup_mutex);
2941 return 0; 2942 return 0;
2942 } 2943 }
@@ -2944,7 +2945,11 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
2944 parent = task_cgroup(tsk, subsys->subsys_id); 2945 parent = task_cgroup(tsk, subsys->subsys_id);
2945 2946
2946 /* Pin the hierarchy */ 2947 /* Pin the hierarchy */
2947 atomic_inc(&parent->root->sb->s_active); 2948 if (!atomic_inc_not_zero(&parent->root->sb->s_active)) {
2949 /* We race with the final deactivate_super() */
2950 mutex_unlock(&cgroup_mutex);
2951 return 0;
2952 }
2948 2953
2949 /* Keep the cgroup alive */ 2954 /* Keep the cgroup alive */
2950 get_css_set(cg); 2955 get_css_set(cg);