diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2019-01-06 11:41:29 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2019-01-17 11:52:49 -0500 |
commit | 399504e21a10be16dd1408ba0147367d9d82a10c (patch) | |
tree | 7762ae17e66c37d39687268eac7dd99965f2ba0a /fs/kernfs | |
parent | 1c7fc5cbc33980acd13d668f1c8f0313d6ae9fd8 (diff) | |
download | lwn-399504e21a10be16dd1408ba0147367d9d82a10c.tar.gz lwn-399504e21a10be16dd1408ba0147367d9d82a10c.zip |
fix cgroup_do_mount() handling of failure exits
same story as with last May fixes in sysfs (7b745a4e4051
"unfuck sysfs_mount()"); new_sb is left uninitialized
in case of early errors in kernfs_mount_ns() and papering
over it by treating any error from kernfs_mount_ns() as
equivalent to !new_ns ends up conflating the cases when
objects had never been transferred to a superblock with
ones when that has happened and resulting new superblock
had been dropped. Easily fixed (same way as in sysfs
case). Additionally, there's a superblock leak on
kernfs_node_dentry() failure *and* a dentry leak inside
kernfs_node_dentry() itself - the latter on probably
impossible errors, but the former not impossible to trigger
(as the matter of fact, injecting allocation failures
at that point *does* trigger it).
Cc: stable@kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/kernfs')
-rw-r--r-- | fs/kernfs/mount.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index fdf527b6d79c..d71c9405874a 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -196,8 +196,10 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, return dentry; knparent = find_next_ancestor(kn, NULL); - if (WARN_ON(!knparent)) + if (WARN_ON(!knparent)) { + dput(dentry); return ERR_PTR(-EINVAL); + } do { struct dentry *dtmp; @@ -206,8 +208,10 @@ struct dentry *kernfs_node_dentry(struct kernfs_node *kn, if (kn == knparent) return dentry; kntmp = find_next_ancestor(kn, knparent); - if (WARN_ON(!kntmp)) + if (WARN_ON(!kntmp)) { + dput(dentry); return ERR_PTR(-EINVAL); + } dtmp = lookup_one_len_unlocked(kntmp->name, dentry, strlen(kntmp->name)); dput(dentry); |