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; |
