diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-07 18:20:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-07 18:20:10 -0400 |
commit | dc5ed40686a4da95881c35d913b60f867755cbe2 (patch) | |
tree | 8553406baccf981cdc3b6251dd3c7e89de2fc4ca /kernel | |
parent | 467a9e1633043810259a7f5368fbcc1e84746137 (diff) | |
parent | 49957f8e2a43035a97d05bddefa394492a969c0d (diff) |
Merge branch 'for-3.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup fixes from Tejun Heo:
"Two patches to fix fallouts from the kernfs conversion:
Li's patch to stop leaking cgroup_root refs across multiple mounts and
the other fixes the 90s hang during shutdown caused by always using
root's uid/gid for new cgroup dirs and files."
* 'for-3.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
cgroup: newly created dirs and files should be owned by the creator
cgroup: fix top cgroup refcnt leak
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cgroup.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index fede3d3f28ff..9fcdaa705b6c 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -1487,6 +1487,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, | |||
1487 | struct cgroup_sb_opts opts; | 1487 | struct cgroup_sb_opts opts; |
1488 | struct dentry *dentry; | 1488 | struct dentry *dentry; |
1489 | int ret; | 1489 | int ret; |
1490 | bool new_sb; | ||
1490 | 1491 | ||
1491 | /* | 1492 | /* |
1492 | * The first time anyone tries to mount a cgroup, enable the list | 1493 | * The first time anyone tries to mount a cgroup, enable the list |
@@ -1603,8 +1604,8 @@ out_unlock: | |||
1603 | if (ret) | 1604 | if (ret) |
1604 | return ERR_PTR(ret); | 1605 | return ERR_PTR(ret); |
1605 | 1606 | ||
1606 | dentry = kernfs_mount(fs_type, flags, root->kf_root, NULL); | 1607 | dentry = kernfs_mount(fs_type, flags, root->kf_root, &new_sb); |
1607 | if (IS_ERR(dentry)) | 1608 | if (IS_ERR(dentry) || !new_sb) |
1608 | cgroup_put(&root->cgrp); | 1609 | cgroup_put(&root->cgrp); |
1609 | return dentry; | 1610 | return dentry; |
1610 | } | 1611 | } |
@@ -2345,11 +2346,26 @@ static int cgroup_rename(struct kernfs_node *kn, struct kernfs_node *new_parent, | |||
2345 | return ret; | 2346 | return ret; |
2346 | } | 2347 | } |
2347 | 2348 | ||
2349 | /* set uid and gid of cgroup dirs and files to that of the creator */ | ||
2350 | static int cgroup_kn_set_ugid(struct kernfs_node *kn) | ||
2351 | { | ||
2352 | struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID, | ||
2353 | .ia_uid = current_fsuid(), | ||
2354 | .ia_gid = current_fsgid(), }; | ||
2355 | |||
2356 | if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) && | ||
2357 | gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID)) | ||
2358 | return 0; | ||
2359 | |||
2360 | return kernfs_setattr(kn, &iattr); | ||
2361 | } | ||
2362 | |||
2348 | static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft) | 2363 | static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft) |
2349 | { | 2364 | { |
2350 | char name[CGROUP_FILE_NAME_MAX]; | 2365 | char name[CGROUP_FILE_NAME_MAX]; |
2351 | struct kernfs_node *kn; | 2366 | struct kernfs_node *kn; |
2352 | struct lock_class_key *key = NULL; | 2367 | struct lock_class_key *key = NULL; |
2368 | int ret; | ||
2353 | 2369 | ||
2354 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 2370 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
2355 | key = &cft->lockdep_key; | 2371 | key = &cft->lockdep_key; |
@@ -2357,7 +2373,13 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cftype *cft) | |||
2357 | kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name), | 2373 | kn = __kernfs_create_file(cgrp->kn, cgroup_file_name(cgrp, cft, name), |
2358 | cgroup_file_mode(cft), 0, cft->kf_ops, cft, | 2374 | cgroup_file_mode(cft), 0, cft->kf_ops, cft, |
2359 | NULL, false, key); | 2375 | NULL, false, key); |
2360 | return PTR_ERR_OR_ZERO(kn); | 2376 | if (IS_ERR(kn)) |
2377 | return PTR_ERR(kn); | ||
2378 | |||
2379 | ret = cgroup_kn_set_ugid(kn); | ||
2380 | if (ret) | ||
2381 | kernfs_remove(kn); | ||
2382 | return ret; | ||
2361 | } | 2383 | } |
2362 | 2384 | ||
2363 | /** | 2385 | /** |
@@ -3752,6 +3774,10 @@ static long cgroup_create(struct cgroup *parent, const char *name, | |||
3752 | */ | 3774 | */ |
3753 | idr_replace(&root->cgroup_idr, cgrp, cgrp->id); | 3775 | idr_replace(&root->cgroup_idr, cgrp, cgrp->id); |
3754 | 3776 | ||
3777 | err = cgroup_kn_set_ugid(kn); | ||
3778 | if (err) | ||
3779 | goto err_destroy; | ||
3780 | |||
3755 | err = cgroup_addrm_files(cgrp, cgroup_base_files, true); | 3781 | err = cgroup_addrm_files(cgrp, cgroup_base_files, true); |
3756 | if (err) | 3782 | if (err) |
3757 | goto err_destroy; | 3783 | goto err_destroy; |