diff options
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 33 |
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) | |||
1279 | static int attach_task_by_pid(struct cgroup *cgrp, u64 pid) | 1280 | static 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); |