slub: fix leak of 'name' in sysfs_slab_add
authorDave Jones <davej@fedoraproject.org>
Mon, 7 Apr 2014 22:39:32 +0000 (15:39 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 7 Apr 2014 23:36:13 +0000 (16:36 -0700)
The failure paths of sysfs_slab_add don't release the allocation of
'name' made by create_unique_id() a few lines above the context of the
diff below.  Create a common exit path to make it more obvious what
needs freeing.

[vdavydov@parallels.com: free the name only if !unmergeable]
Signed-off-by: Dave Jones <davej@fedoraproject.org>
Signed-off-by: Vladimir Davydov <vdavydov@parallels.com>
Cc: Pekka Enberg <penberg@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/slub.c

index 3508ede..e745186 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -5214,25 +5214,19 @@ static int sysfs_slab_add(struct kmem_cache *s)
 
        s->kobj.kset = cache_kset(s);
        err = kobject_init_and_add(&s->kobj, &slab_ktype, NULL, "%s", name);
-       if (err) {
-               kobject_put(&s->kobj);
-               return err;
-       }
+       if (err)
+               goto out_put_kobj;
 
        err = sysfs_create_group(&s->kobj, &slab_attr_group);
-       if (err) {
-               kobject_del(&s->kobj);
-               kobject_put(&s->kobj);
-               return err;
-       }
+       if (err)
+               goto out_del_kobj;
 
 #ifdef CONFIG_MEMCG_KMEM
        if (is_root_cache(s)) {
                s->memcg_kset = kset_create_and_add("cgroup", NULL, &s->kobj);
                if (!s->memcg_kset) {
-                       kobject_del(&s->kobj);
-                       kobject_put(&s->kobj);
-                       return -ENOMEM;
+                       err = -ENOMEM;
+                       goto out_del_kobj;
                }
        }
 #endif
@@ -5241,9 +5235,16 @@ static int sysfs_slab_add(struct kmem_cache *s)
        if (!unmergeable) {
                /* Setup first alias */
                sysfs_slab_alias(s, s->name);
-               kfree(name);
        }
-       return 0;
+out:
+       if (!unmergeable)
+               kfree(name);
+       return err;
+out_del_kobj:
+       kobject_del(&s->kobj);
+out_put_kobj:
+       kobject_put(&s->kobj);
+       goto out;
 }
 
 static void sysfs_slab_remove(struct kmem_cache *s)