Skip to contentSkip to conversation

lib/kobject: fix memory leak in error path of kset_create_and_add()

PATCH Superseded Nicolai Stange 2 participants 9 messages Nov 17, 2015 – Feb 23, 2016

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 lib/kobject: fix memory leak in error path of kset_create_and_add()

In kset_create_and_add(), the name duped into the kset's kobject by kset_create() gets leaked if the call to kset_register() fails.

Indeed, triggering failure by invoking kset_create_and_add() with a duplicate name makes kmemleak reporting

unreferenced object 0xffff8800b4a1f428 (size 16):

    comm "insmod", pid 682, jiffies 4294745489 (age 50.477s)
    hex dump (first 16 bytes):
      64 75 70 6c 69 63 61 74 65 00 6b 6b 6b 6b 6b a5  duplicate.kkkkk.
    backtrace:
      [<ffffffff814380ee>] kmemleak_alloc+0x4e/0xb0
      [<ffffffff811aab01>] __kmalloc_track_caller+0x2b1/0x390
      [<ffffffff811797f1>] kstrdup+0x31/0x60
      [<ffffffff81179843>] kstrdup_const+0x23/0x30
      [<ffffffff81290254>] kvasprintf_const+0x54/0x90
      [<ffffffff81284d21>] kobject_set_name_vargs+0x21/0xa0
      [<ffffffff81284dee>] kobject_set_name+0x4e/0x70
      [<ffffffff812854f5>] kset_create_and_add+0x45/0xa0
      [...]

Similar problems exist at all call sites of kset_register(), that is in drivers/base, fs/ext4 and in fs/ocfs2.

The deeper cause behind this are the current semantics of the kset initialization, creation and registration functions which differ from the ones of their corresponding kobject counterparts.
Namely,
- there is no _exported_ kset initialization function,
- the (not exported) kset_create() creates a halfway initialized kset object,
- and the kset_register() finishes a kset object's initialization but expects its name to already have been set at its entry.

To fix this:
- Export kset_init() and let it mimic the semantics of kobject_init(). Especially it takes and sets a kobj_type which makes the kset object kset_put()able upon return.
- Let the internal kset_create() do the complete initialization by means of kset_init().
- Remove any kset initialization from kset_register(): it expects a readily initialized kset object now. Furthermore, let kset_register() take and set the kset object's name. This resembles the behaviour of kobject_add(). In analogy to the latter, require the caller to call kset_put() or kset_unregister() unconditionally, even on failure.

At the call sites of kset_register():
- Replace the open coded kset object initialization by a call to kset_init().
- Remove the explicit name setting and let the kset_register() call do that work.
- Replace any kfree()s by kset_put()s where appropriate.

---
To the maintainers of ext4 and ocfs2: although several subsystems are touched, the changes come in one single patch in order to keep them bisectable.

 drivers/base/bus.c         | 14 ++-----
 drivers/base/class.c       | 39 ++++++++++++++-----
 fs/ext4/sysfs.c            | 13 +++----
 fs/ocfs2/cluster/masklog.c | 13 ++++---
 include/linux/kobject.h    |  6 ++-
 lib/kobject.c              | 94 ++++++++++++++++++++++++++++------------------
 6 files changed, 110 insertions(+), 69 deletions(-)
drivers/base/bus.c +4 -10
index 5005924..a81227c 100644
@@ -900,15 +900,11 @@ int bus_register(struct bus_type *bus)
 
 	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
 
-	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
-	if (retval)
-		goto out;
-
-	priv->subsys.kobj.kset = bus_kset;
-	priv->subsys.kobj.ktype = &bus_ktype;
 	priv->drivers_autoprobe = 1;
 
-	retval = kset_register(&priv->subsys);
+	kset_init(&priv->subsys, &bus_ktype, NULL);
+	priv->subsys.kobj.kset = bus_kset;
+	retval = kset_register(&priv->subsys, bus->name, NULL);
 	if (retval)
 		goto out;
 
@@ -955,10 +951,8 @@ bus_drivers_fail:
 bus_devices_fail:
 	bus_remove_file(bus, &bus_attr_uevent);
 bus_uevent_fail:
-	kset_unregister(&bus->p->subsys);
 out:
-	kfree(bus->p);
-	bus->p = NULL;
+	kset_unregister(&bus->p->subsys);
 	return retval;
 }
 EXPORT_SYMBOL_GPL(bus_register);
drivers/base/class.c +30 -9
index 71059e3..94a5b040 100644
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/genhd.h>
 #include <linux/mutex.h>
+#include <linux/printk.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -82,6 +83,24 @@ static struct kobj_type class_ktype = {
 	.child_ns_type	= class_child_ns_type,
 };
 
+static void glue_dirs_release_dummy(struct kobject *kobj)
+{
+	/*
+	 * The glue_dirs kset member of struct subsys_private is never
+	 * registered and thus, never unregistered.
+	 * This release function is a dummy to make kset_init() happy.
+	 */
+	pr_err(
+	"class (%p): unexpected kset_put() on glue_dirs, something is broken.",
+		container_of(kobj, struct subsys_private,
+				glue_dirs.kobj)->class);
+	dump_stack();
+}
+
+static struct kobj_type glue_dirs_ktype = {
+	.release = glue_dirs_release_dummy,
+};
+
 /* Hotplug events for classes go to the class subsys */
 static struct kset *class_kset;
 
@@ -175,18 +194,14 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 		return -ENOMEM;
 	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
 	INIT_LIST_HEAD(&cp->interfaces);
-	kset_init(&cp->glue_dirs);
+	kset_init(&cp->glue_dirs, &glue_dirs_ktype, NULL);
 	__mutex_init(&cp->mutex, "subsys mutex", key);
-	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
-	if (error) {
-		kfree(cp);
-		return error;
-	}
 
 	/* set the default /sys/dev directory for devices of this class */
 	if (!cls->dev_kobj)
 		cls->dev_kobj = sysfs_dev_char_kobj;
 
+	kset_init(&cp->subsys, &class_ktype, NULL);
 #if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
 	if (!sysfs_deprecated || cls != &block_class)
@@ -194,13 +209,19 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 #else
 	cp->subsys.kobj.kset = class_kset;
 #endif
-	cp->subsys.kobj.ktype = &class_ktype;
 	cp->class = cls;
 	cls->p = cp;
 
-	error = kset_register(&cp->subsys);
+	error = kset_register(&cp->subsys, cls->name, NULL);
 	if (error) {
-		kfree(cp);
+		/*
+		 * class->release() would be called by cp->subsys'
+		 * release function. Prevent this from happening in
+		 * the error case by zeroing cp->class out.
+		 */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);
 		return error;
 	}
 	error = add_class_attrs(class_get(cls));
fs/ext4/sysfs.c +6 -7
index 1b57c72..03703eb 100644
@@ -339,9 +339,7 @@ static struct kobj_type ext4_ktype = {
 	.sysfs_ops	= &ext4_attr_ops,
 };
 
-static struct kset ext4_kset = {
-	.kobj   = {.ktype = &ext4_ktype},
-};
+static struct kset ext4_kset;
 
 static struct kobj_type ext4_feat_ktype = {
 	.default_attrs	= ext4_feat_attrs,
@@ -423,11 +421,12 @@ int __init ext4_init_sysfs(void)
 {
 	int ret;
 
-	kobject_set_name(&ext4_kset.kobj, "ext4");
-	ext4_kset.kobj.parent = fs_kobj;
-	ret = kset_register(&ext4_kset);
-	if (ret)
+	kset_init(&ext4_kset, &ext4_ktype, NULL);
+	ret = kset_register(&ext4_kset, "ext4", fs_kobj);
+	if (ret) {
+		kset_unregister(&ext4_kset);
 		return ret;
+	}
 
 	ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype,
 				   NULL, "features");
fs/ocfs2/cluster/masklog.c +8 -5
index dfe162f..70c34ec 100644
@@ -164,13 +164,12 @@ static struct kobj_type mlog_ktype = {
 	.sysfs_ops     = &mlog_attr_ops,
 };
 
-static struct kset mlog_kset = {
-	.kobj   = {.ktype = &mlog_ktype},
-};
+static struct kset mlog_kset;
 
 int mlog_sys_init(struct kset *o2cb_kset)
 {
 	int i = 0;
+	int ret;
 
 	while (mlog_attrs[i].attr.mode) {
 		mlog_attr_ptrs[i] = &mlog_attrs[i].attr;
@@ -178,9 +177,13 @@ int mlog_sys_init(struct kset *o2cb_kset)
 	}
 	mlog_attr_ptrs[i] = NULL;
 
-	kobject_set_name(&mlog_kset.kobj, "logmask");
+	kset_init(&mlog_kset, &mlog_ktype, NULL);
 	mlog_kset.kobj.kset = o2cb_kset;
-	return kset_register(&mlog_kset);
+	ret = kset_register(&mlog_kset, "logmask", NULL);
+	if (ret)
+		kset_unregister(&mlog_kset);
+
+	return ret;
 }
 
 void mlog_sys_shutdown(void)
include/linux/kobject.h +4 -2
index e628459..d081817 100644
@@ -172,8 +172,10 @@ struct kset {
 	const struct kset_uevent_ops *uevent_ops;
 };
 
-extern void kset_init(struct kset *kset);
-extern int __must_check kset_register(struct kset *kset);
+extern void kset_init(struct kset *kset, struct kobj_type *ktype,
+		const struct kset_uevent_ops *uevent_ops);
+extern int __must_check kset_register(struct kset *kset, const char *name,
+				struct kobject *parent_kobj);
 extern void kset_unregister(struct kset *kset);
 extern struct kset * __must_check kset_create_and_add(const char *name,
 						const struct kset_uevent_ops *u,
lib/kobject.c +58 -36

150 lines not on this page · raw message

Signature · 1 line
2.6.3
#1 lore raw
Quoted 21 lines · Nicolai Stange

In kset_create_and_add(), the name duped into the kset's kobject by kset_create() gets leaked if the call to kset_register() fails.

Indeed, triggering failure by invoking kset_create_and_add() with a duplicate name makes kmemleak reporting

unreferenced object 0xffff8800b4a1f428 (size 16):

    comm "insmod", pid 682, jiffies 4294745489 (age 50.477s)
    hex dump (first 16 bytes):
      64 75 70 6c 69 63 61 74 65 00 6b 6b 6b 6b 6b a5  duplicate.kkkkk.
    backtrace:
      [<ffffffff814380ee>] kmemleak_alloc+0x4e/0xb0
      [<ffffffff811aab01>] __kmalloc_track_caller+0x2b1/0x390
      [<ffffffff811797f1>] kstrdup+0x31/0x60
      [<ffffffff81179843>] kstrdup_const+0x23/0x30
      [<ffffffff81290254>] kvasprintf_const+0x54/0x90
      [<ffffffff81284d21>] kobject_set_name_vargs+0x21/0xa0
      [<ffffffff81284dee>] kobject_set_name+0x4e/0x70
      [<ffffffff812854f5>] kset_create_and_add+0x45/0xa0
      [...]
Quoted 2 lines

Similar problems exist at all call sites of kset_register(), that is in drivers/base, fs/ext4 and in fs/ocfs2.

Yes, but those calls all succeed, so this isn't a problem in the "real" world :)

Quoted 96 lines

The deeper cause behind this are the current semantics of the kset initialization, creation and registration functions which differ from the ones of their corresponding kobject counterparts.
Namely,
- there is no _exported_ kset initialization function,
- the (not exported) kset_create() creates a halfway initialized kset object,
- and the kset_register() finishes a kset object's initialization but expects its name to already have been set at its entry.

To fix this:
- Export kset_init() and let it mimic the semantics of kobject_init(). Especially it takes and sets a kobj_type which makes the kset object kset_put()able upon return.
- Let the internal kset_create() do the complete initialization by means of kset_init().
- Remove any kset initialization from kset_register(): it expects a readily initialized kset object now. Furthermore, let kset_register() take and set the kset object's name. This resembles the behaviour of kobject_add(). In analogy to the latter, require the caller to call kset_put() or kset_unregister() unconditionally, even on failure.

At the call sites of kset_register():
- Replace the open coded kset object initialization by a call to kset_init().
- Remove the explicit name setting and let the kset_register() call do that work.
- Replace any kfree()s by kset_put()s where appropriate.

---
To the maintainers of ext4 and ocfs2: although several subsystems are touched, the changes come in one single patch in order to keep them bisectable.

 drivers/base/bus.c         | 14 ++-----
 drivers/base/class.c       | 39 ++++++++++++++-----
 fs/ext4/sysfs.c            | 13 +++----
 fs/ocfs2/cluster/masklog.c | 13 ++++---
 include/linux/kobject.h    |  6 ++-
 lib/kobject.c              | 94 ++++++++++++++++++++++++++++------------------
 6 files changed, 110 insertions(+), 69 deletions(-)
drivers/base/bus.c +4 -10
index 5005924..a81227c 100644
@@ -900,15 +900,11 @@ int bus_register(struct bus_type *bus)
 
 	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
 
-	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
-	if (retval)
-		goto out;
-
-	priv->subsys.kobj.kset = bus_kset;
-	priv->subsys.kobj.ktype = &bus_ktype;
 	priv->drivers_autoprobe = 1;
 
-	retval = kset_register(&priv->subsys);
+	kset_init(&priv->subsys, &bus_ktype, NULL);
+	priv->subsys.kobj.kset = bus_kset;
+	retval = kset_register(&priv->subsys, bus->name, NULL);
 	if (retval)
 		goto out;
 
@@ -955,10 +951,8 @@ bus_drivers_fail:
 bus_devices_fail:
 	bus_remove_file(bus, &bus_attr_uevent);
 bus_uevent_fail:
-	kset_unregister(&bus->p->subsys);
 out:
-	kfree(bus->p);
-	bus->p = NULL;
+	kset_unregister(&bus->p->subsys);
 	return retval;
 }
 EXPORT_SYMBOL_GPL(bus_register);
drivers/base/class.c +3 -0
index 71059e3..94a5b040 100644
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/genhd.h>
 #include <linux/mutex.h>
+#include <linux/printk.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -82,6 +83,24 @@ static struct kobj_type class_ktype = {
 	.child_ns_type	= class_child_ns_type,
 };
 
+static void glue_dirs_release_dummy(struct kobject *kobj)
+{

drivers/base/class.c static struct kobj_type class_ktype = { · line 97

Quoted 10 lines
drivers/base/class.c +10 -0
+	/*
+	 * The glue_dirs kset member of struct subsys_private is never
+	 * registered and thus, never unregistered.
+	 * This release function is a dummy to make kset_init() happy.
+	 */
+	pr_err(
+	"class (%p): unexpected kset_put() on glue_dirs, something is broken.",
+		container_of(kobj, struct subsys_private,
+				glue_dirs.kobj)->class);
+	dump_stack();

How can this ever happen?

Quoted 40 lines
drivers/base/class.c +9 -8
+}
+
+static struct kobj_type glue_dirs_ktype = {
+	.release = glue_dirs_release_dummy,
+};
+
 /* Hotplug events for classes go to the class subsys */
 static struct kset *class_kset;
 
@@ -175,18 +194,14 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 		return -ENOMEM;
 	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
 	INIT_LIST_HEAD(&cp->interfaces);
-	kset_init(&cp->glue_dirs);
+	kset_init(&cp->glue_dirs, &glue_dirs_ktype, NULL);
 	__mutex_init(&cp->mutex, "subsys mutex", key);
-	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
-	if (error) {
-		kfree(cp);
-		return error;
-	}
 
 	/* set the default /sys/dev directory for devices of this class */
 	if (!cls->dev_kobj)
 		cls->dev_kobj = sysfs_dev_char_kobj;
 
+	kset_init(&cp->subsys, &class_ktype, NULL);
 #if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
 	if (!sysfs_deprecated || cls != &block_class)
@@ -194,13 +209,19 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 #else
 	cp->subsys.kobj.kset = class_kset;
 #endif
-	cp->subsys.kobj.ktype = &class_ktype;
 	cp->class = cls;
 	cls->p = cp;
 
-	error = kset_register(&cp->subsys);
+	error = kset_register(&cp->subsys, cls->name, NULL);

drivers/base/class.c int __class_register(struct class *cls, struct lock_class_key *key) · line 224

Quoted 10 lines
drivers/base/class.c +8 -1
 	if (error) {
-		kfree(cp);
+		/*
+		 * class->release() would be called by cp->subsys'
+		 * release function. Prevent this from happening in
+		 * the error case by zeroing cp->class out.
+		 */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);

That seems pretty messy, why can't we allow the release to be called? I don't think this is really correct :(

But overall I like the patch, nice job. Any way to fix this last bit up?

thanks,

greg k-h

#2 lore raw
Quoted 7 lines · Greg Kroah-Hartman
Quoted 2 lines · Nicolai Stange

Similar problems exist at all call sites of kset_register(), that is in drivers/base, fs/ext4 and in fs/ocfs2.

Yes, but those calls all succeed, so this isn't a problem in the "real" world :)

No, it is not an issue at runtime. It's more about puzzling code readers like me.

Quoted 94 lines
Quoted 94 lines

The deeper cause behind this are the current semantics of the kset initialization, creation and registration functions which differ from the ones of their corresponding kobject counterparts.
Namely,
- there is no _exported_ kset initialization function,
- the (not exported) kset_create() creates a halfway initialized kset object,
- and the kset_register() finishes a kset object's initialization but expects its name to already have been set at its entry.

To fix this:
- Export kset_init() and let it mimic the semantics of kobject_init(). Especially it takes and sets a kobj_type which makes the kset object kset_put()able upon return.
- Let the internal kset_create() do the complete initialization by means of kset_init().
- Remove any kset initialization from kset_register(): it expects a readily initialized kset object now. Furthermore, let kset_register() take and set the kset object's name. This resembles the behaviour of kobject_add(). In analogy to the latter, require the caller to call kset_put() or kset_unregister() unconditionally, even on failure.

At the call sites of kset_register():
- Replace the open coded kset object initialization by a call to kset_init().
- Remove the explicit name setting and let the kset_register() call do that work.
- Replace any kfree()s by kset_put()s where appropriate.

---
To the maintainers of ext4 and ocfs2: although several subsystems are touched, the changes come in one single patch in order to keep them bisectable.

 drivers/base/bus.c         | 14 ++-----
 drivers/base/class.c       | 39 ++++++++++++++-----
 fs/ext4/sysfs.c            | 13 +++----
 fs/ocfs2/cluster/masklog.c | 13 ++++---
 include/linux/kobject.h    |  6 ++-
 lib/kobject.c              | 94 ++++++++++++++++++++++++++++------------------
 6 files changed, 110 insertions(+), 69 deletions(-)
drivers/base/bus.c +4 -10
index 5005924..a81227c 100644
@@ -900,15 +900,11 @@ int bus_register(struct bus_type *bus)
 
 	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
 
-	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
-	if (retval)
-		goto out;
-
-	priv->subsys.kobj.kset = bus_kset;
-	priv->subsys.kobj.ktype = &bus_ktype;
 	priv->drivers_autoprobe = 1;
 
-	retval = kset_register(&priv->subsys);
+	kset_init(&priv->subsys, &bus_ktype, NULL);
+	priv->subsys.kobj.kset = bus_kset;
+	retval = kset_register(&priv->subsys, bus->name, NULL);
 	if (retval)
 		goto out;
 
@@ -955,10 +951,8 @@ bus_drivers_fail:
 bus_devices_fail:
 	bus_remove_file(bus, &bus_attr_uevent);
 bus_uevent_fail:
-	kset_unregister(&bus->p->subsys);
 out:
-	kfree(bus->p);
-	bus->p = NULL;
+	kset_unregister(&bus->p->subsys);
 	return retval;
 }
 EXPORT_SYMBOL_GPL(bus_register);
drivers/base/class.c +1 -0
index 71059e3..94a5b040 100644
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/genhd.h>
 #include <linux/mutex.h>
+#include <linux/printk.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -82,6 +83,24 @@ static struct kobj_type class_ktype = {
 	.child_ns_type	= class_child_ns_type,
 };
 
Quoted 15 lines

drivers/base/class.c static struct kobj_type class_ktype = { · line 97

Quoted 12 lines
drivers/base/class.c +12 -0
+static void glue_dirs_release_dummy(struct kobject *kobj)
+{
+	/*
+	 * The glue_dirs kset member of struct subsys_private is never
+	 * registered and thus, never unregistered.
+	 * This release function is a dummy to make kset_init() happy.
+	 */
+	pr_err(
+	"class (%p): unexpected kset_put() on glue_dirs, something is broken.",
+		container_of(kobj, struct subsys_private,
+				glue_dirs.kobj)->class);
+	dump_stack();

How can this ever happen?

Actually it can't.

To quote you from Documentation/kobject.txt:

Do not try to get rid of this warning by providing an "empty" release function; you will be mocked mercilessly by the kobject maintainer if you attempt this.

Well, the glue_dirs_release_dummy() is quite empty, but my reasoning was like this:
1. It is a good thing to initialize glue_dirs by kset_init().
2. In the current patch's version, kset_init() does not allow for NULL ktype's, just as kobject_init() doesn't. Thus, I need some dummy kobj_ktype for the glue_dirs().
3. From the usually harsh reactions against BUG(), I conclude that crashing the kernel due to logic errors is not a good thing to do. -> If all of the above is true, it certainly would be better to provide some sort of release() for the kobj_ktype.

I do agree, that a simple WARN() would have been better than the above dummy's implementation.

On the other hand, I'm not exactly sure whether requiring a non-NULL ktype at kset_init() is a good idea at all. Given that there is currently only one single use of kset_init() not providing a non-trivial kobj_ktype and that kobject_init() does require them all to be non-NULL, I let kset_init() require this, too.

Summarizing, the options are either of
- do not use kset_init() for the glue_dirs initialization, but revert to the open coding.
- make kset_init() accept NULL ktype's.
- introduce another initialization function, maybe "kset_init_internal()" which accepts NULL for the ktype. I had to export this internal function though.
- keep the above dummy release function, but make it even more clear that it is a dummy. Furthermore, use WARN() instead of pr_err()/dump_stack().

Just tell me which of the options to pick and I will do that.

Quoted 38 lines
Quoted 38 lines
drivers/base/class.c +8 -7
+}
+
+static struct kobj_type glue_dirs_ktype = {
+	.release = glue_dirs_release_dummy,
+};
+
 /* Hotplug events for classes go to the class subsys */
 static struct kset *class_kset;
 
@@ -175,18 +194,14 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 		return -ENOMEM;
 	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
 	INIT_LIST_HEAD(&cp->interfaces);
-	kset_init(&cp->glue_dirs);
+	kset_init(&cp->glue_dirs, &glue_dirs_ktype, NULL);
 	__mutex_init(&cp->mutex, "subsys mutex", key);
-	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
-	if (error) {
-		kfree(cp);
-		return error;
-	}
 
 	/* set the default /sys/dev directory for devices of this class */
 	if (!cls->dev_kobj)
 		cls->dev_kobj = sysfs_dev_char_kobj;
 
+	kset_init(&cp->subsys, &class_ktype, NULL);
 #if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
 	if (!sysfs_deprecated || cls != &block_class)
@@ -194,13 +209,19 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 #else
 	cp->subsys.kobj.kset = class_kset;
 #endif
-	cp->subsys.kobj.ktype = &class_ktype;
 	cp->class = cls;
 	cls->p = cp;
 
Quoted 15 lines

drivers/base/class.c int __class_register(struct class *cls, struct lock_class_key *key) · line 224

Quoted 12 lines
drivers/base/class.c +9 -2
-	error = kset_register(&cp->subsys);
+	error = kset_register(&cp->subsys, cls->name, NULL);
 	if (error) {
-		kfree(cp);
+		/*
+		 * class->release() would be called by cp->subsys'
+		 * release function. Prevent this from happening in
+		 * the error case by zeroing cp->class out.
+		 */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);

That seems pretty messy, why can't we allow the release to be called? I don't think this is really correct :(

I don't know whether it is actually correct, but before the introduction of this patch, the class->release() would not have been called on error either. I did not want to change that behaviour and thus, I have put this "messy" and admittedly ugly clear-the-class-pointer code into the error handling above.

I will check whether calling class->release() on error would be a problem for the callers of class_register() (there are 64 of them). If it turns out not to be one, I could simply remove the above class pointer purging.

However, for bisectability, I suggest to send this as a separate patch, if any: this would change class_register()'s behaviour and is quite unrelated to the kset stuff.

If you do not agree, please tell me.

Quoted 2 lines

But overall I like the patch, nice job. Any way to fix this last bit up?

Thank you very much for your feedback. I will wait for your input on the two questions above regarding
- the dummy implementation of the glue_dirs' ktype and
- the unmessing of class_register() in a separate patch
and resend this patch accordingly then.

Thank you,

Nicolai Stange

#3 lore raw
Quoted 63 lines · Nicolai Stange
Quoted 39 lines · Greg Kroah-Hartman
Quoted 38 lines · Nicolai Stange
drivers/base/class.c +8 -7
+}
+
+static struct kobj_type glue_dirs_ktype = {
+	.release = glue_dirs_release_dummy,
+};
+
 /* Hotplug events for classes go to the class subsys */
 static struct kset *class_kset;
@@ -175,18 +194,14 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 		return -ENOMEM;
 	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
 	INIT_LIST_HEAD(&cp->interfaces);
-	kset_init(&cp->glue_dirs);
+	kset_init(&cp->glue_dirs, &glue_dirs_ktype, NULL);
 	__mutex_init(&cp->mutex, "subsys mutex", key);
-	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
-	if (error) {
-		kfree(cp);
-		return error;
-	}
 
 	/* set the default /sys/dev directory for devices of this class */
 	if (!cls->dev_kobj)
 		cls->dev_kobj = sysfs_dev_char_kobj;
 
+	kset_init(&cp->subsys, &class_ktype, NULL);
 #if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
 	if (!sysfs_deprecated || cls != &block_class)
@@ -194,13 +209,19 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 #else
 	cp->subsys.kobj.kset = class_kset;
 #endif
-	cp->subsys.kobj.ktype = &class_ktype;
 	cp->class = cls;
 	cls->p = cp;
 
Quoted 15 lines

drivers/base/class.c int __class_register(struct class *cls, struct lock_class_key *key) · line 224

Quoted 12 lines
drivers/base/class.c +9 -2
-	error = kset_register(&cp->subsys);
+	error = kset_register(&cp->subsys, cls->name, NULL);
 	if (error) {
-		kfree(cp);
+		/*
+		 * class->release() would be called by cp->subsys'
+		 * release function. Prevent this from happening in
+		 * the error case by zeroing cp->class out.
+		 */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);

That seems pretty messy, why can't we allow the release to be called? I don't think this is really correct :(

I don't know whether it is actually correct, but before the introduction of this patch, the class->release() would not have been called on error either. I did not want to change that behaviour and thus, I have put this "messy" and admittedly ugly clear-the-class-pointer code into the error handling above.

Quoted 4 lines

I will check whether calling class->release() on error would be a problem for the callers of class_register() (there are 64 of them). If it turns out not to be one, I could simply remove the above class pointer purging.

The very first candidate I've looked at, __class_create() from drivers/base/class.c, relies on class_register() not to call class->release() on error: upon a non-zero return from __class_register() it explicitly kfree()s the struct class instance. Together with the kfree() in class_create_release(), this would result in a double free. Thus, as it stands, class_create_release() must not get called upon encountering an error in __class_register() and the messy clearance of cp->class before the call to kset_put() is necessary.

The current semantics of __class_register() seem to be:
- if the call succeeds, the registered class' release function will eventually get called by the kobject system.
- if it doesn't succeed, the registered class' release function won't ever be called: clean up after yourself.

One could change this behaviour and indeed it might make sense. But in my opinion, this should be done in a different patch. After all, there are ~64 call sites involved which would have to get changed accordingly.

As a sidenote, note that __class_register()'s error behaviour is a little bit inconsistent: if the final add_class_attrs() call fails, the cp->subsys won't get deregistered by __class_register() itsef. Upon encountering a non-zero return value from __class_register(), a caller would not be able to decide whether kset_register() or add_class_attrs() failed and thus, it can't tell whether a class_unregister() is necessary/allowed or not. I think the place to fix this should be a separate patch, too. It would be a straight forward one though:
add_class_attrs() has got all-or-nothing semantics already and thus, furnishing __class_register() with similiar behaviour is easy.

#4 lore raw

PATCH v2 1/1 kset- and class-registration cleanups

In reply to Greg Kroah-Hartman

In order to have something to base further discussion on, here comes the second version.

In addition to some changes to the inital patch (now [1/3]), two additional ones have been introduced.

The three patches depend on one another in sequence.

For a detailed changelist, see the end of this mail.

Quoted 3 lines · Greg Kroah-Hartman

On Tue, Nov 17, 2015 at 01:04:19AM +0100, Nicolai Stange wrote:
Yes, but those calls all succeed, so this isn't a problem in the "real" world :)

I added a word about non-impact in the commit message of [1/3].

Quoted 6 lines
Quoted 6 lines
drivers/base/class.c +6 -0
+static void glue_dirs_release_dummy(struct kobject *kobj)
+{
+	/*
+	 * The glue_dirs kset member of struct subsys_private is never
+	 * registered and thus, never unregistered.
+	 * This release function is a dummy to make kset_init() happy.
Quoted 8 lines

drivers/base/class.c static struct kobj_type class_ktype = { · line 97

Quoted 6 lines
drivers/base/class.c +6 -0
+	 */
+	pr_err(
+	"class (%p): unexpected kset_put() on glue_dirs, something is broken.",
+		container_of(kobj, struct subsys_private,
+				glue_dirs.kobj)->class);
+	dump_stack();

How can this ever happen?

Not at all. I'm not sure I understand you correctly here.
Do you strictly want to abandon the dummy releaser, or more specifically, the dummy kobj_type?
For the moment, I turned the pr_err()/dump_stack() into a WARN() for the sake of better style.

Quoted 5 lines
Quoted 5 lines
drivers/base/class.c +3 -1
 	if (error) {
-		kfree(cp);
+		/*
+		 * class->release() would be called by cp->subsys'
+		 * release function. Prevent this from happening in
Quoted 8 lines

drivers/base/class.c int __class_register(struct class *cls, struct lock_class_key *key) · line 224

Quoted 5 lines
drivers/base/class.c +5 -0
+		 * the error case by zeroing cp->class out.
+		 */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);

That seems pretty messy, why can't we allow the release to be called? I don't think this is really correct :(

At the moment, it is necessary. I've added [3/3] for the case that you want cls->class_release() to get called from __class_register() on error. In [3/3] you will also find the (few) callers expecting the behaviour as it currently is.

Detailed changes from initial version to v2:
[1/3] lib/kobject: fix memory leak in error path of kset_create_and_add() This one is the original patch with a few changes:
- added a word of non-impact to commit message
- use WARN() instead of open coded pr_error()/dump_stack() pair in struct class' glue_dirs' dummy class releaser.
- follow my own advice in the docstring of kset_register() and use kset_put() instead of kset_unregister() on error of kset_register() in ext4's ext4_init_sysfs() and ocfs2's mlog_sys_init().

[2/3] drivers/base/class: __class_register(): make error behaviour consistent This one is new and quite unrelated to the original patch. Following the sidenote made in my last mail, it makes __class_register() properly clean up after itself on error.

[3/3] drivers/base/class: __class_register(): invoke class' releaser on failure This one is new.
It addresses Greg K-H's comment on the initial version about the messiness of avoiding to call class->class_release() from __class_register() on error. Given the fact that I had to introduce an explicit cls->class_release() in the early part when there is no kset object available yet, I'm by no means sure that it is much less messy now and that this patch is worth the trouble.
-> It is up to you to judge.
As there are enough people bothered already, I did not CC the people suggested for this one by get_maintainer.pl: all of them are maintainers of external subsystems and probably not particularly interested in __class_register() and friends. I will do this as soon as
a decision for this patch has been made, perhaps in a separate thread.

#5 lore raw

PATCH v2 1/3 lib/kobject: fix memory leak in error path of kset_create_and_add()

In kset_create_and_add(), the name duped into the kset's kobject by kset_create() gets leaked if the call to kset_register() fails.

Indeed, triggering failure by invoking kset_create_and_add() with a duplicate name makes kmemleak reporting

unreferenced object 0xffff8800b4a1f428 (size 16):

    comm "insmod", pid 682, jiffies 4294745489 (age 50.477s)
    hex dump (first 16 bytes):
      64 75 70 6c 69 63 61 74 65 00 6b 6b 6b 6b 6b a5  duplicate.kkkkk.
    backtrace:
      [<ffffffff814380ee>] kmemleak_alloc+0x4e/0xb0
      [<ffffffff811aab01>] __kmalloc_track_caller+0x2b1/0x390
      [<ffffffff811797f1>] kstrdup+0x31/0x60
      [<ffffffff81179843>] kstrdup_const+0x23/0x30
      [<ffffffff81290254>] kvasprintf_const+0x54/0x90
      [<ffffffff81284d21>] kobject_set_name_vargs+0x21/0xa0
      [<ffffffff81284dee>] kobject_set_name+0x4e/0x70
      [<ffffffff812854f5>] kset_create_and_add+0x45/0xa0
      [...]

Similar problems exist at all call sites of kset_register(), that is in drivers/base, fs/ext4 and in fs/ocfs2.

However, since class registration usually does not fail, there is virtually no real world impact.

The deeper cause behind this are the current semantics of the kset initialization, creation and registration functions which differ from the ones of their corresponding kobject counterparts.
Namely,
- there is no _exported_ kset initialization function,
- the (not exported) kset_create() creates a halfway initialized kset object,
- and the kset_register() finishes a kset object's initialization but expects its name to already have been set at its entry.

To fix this:
- Export kset_init() and let it mimic the semantics of kobject_init(). Especially it takes and sets a kobj_type which makes the kset object kset_put()able upon return.
- Let the internal kset_create() do the complete initialization by means of kset_init().
- Remove any kset initialization from kset_register(): it expects a readily initialized kset object now. Furthermore, let kset_register() take and set the kset object's name. This resembles the behaviour of kobject_add(). In analogy to the latter, require the caller to call kset_put() or kset_unregister() unconditionally, even on failure.

At the call sites of kset_register():
- Replace the open coded kset object initialization by a call to kset_init().
- Remove the explicit name setting and let the kset_register() call do that work.
- Replace any kfree()s by kset_put()s where appropriate.

---
 drivers/base/bus.c         | 14 ++-----
 drivers/base/class.c       | 38 ++++++++++++++-----
 fs/ext4/sysfs.c            | 13 +++----
 fs/ocfs2/cluster/masklog.c | 13 ++++---
 include/linux/kobject.h    |  6 ++-
 lib/kobject.c              | 94 ++++++++++++++++++++++++++++------------------
 6 files changed, 109 insertions(+), 69 deletions(-)
drivers/base/bus.c +4 -10
index 5005924..a81227c 100644
@@ -900,15 +900,11 @@ int bus_register(struct bus_type *bus)
 
 	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
 
-	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
-	if (retval)
-		goto out;
-
-	priv->subsys.kobj.kset = bus_kset;
-	priv->subsys.kobj.ktype = &bus_ktype;
 	priv->drivers_autoprobe = 1;
 
-	retval = kset_register(&priv->subsys);
+	kset_init(&priv->subsys, &bus_ktype, NULL);
+	priv->subsys.kobj.kset = bus_kset;
+	retval = kset_register(&priv->subsys, bus->name, NULL);
 	if (retval)
 		goto out;
 
@@ -955,10 +951,8 @@ bus_drivers_fail:
 bus_devices_fail:
 	bus_remove_file(bus, &bus_attr_uevent);
 bus_uevent_fail:
-	kset_unregister(&bus->p->subsys);
 out:
-	kfree(bus->p);
-	bus->p = NULL;
+	kset_unregister(&bus->p->subsys);
 	return retval;
 }
 EXPORT_SYMBOL_GPL(bus_register);
drivers/base/class.c +29 -9
index 71059e3..c9683cf 100644
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/genhd.h>
 #include <linux/mutex.h>
+#include <linux/bug.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -82,6 +83,23 @@ static struct kobj_type class_ktype = {
 	.child_ns_type	= class_child_ns_type,
 };
 
+static void glue_dirs_release_dummy(struct kobject *kobj)
+{
+	/*
+	 * The glue_dirs kset member of struct subsys_private is never
+	 * registered and thus, never unregistered.
+	 * This release function is a dummy to make kset_init() happy.
+	 */
+	WARN(1,
+	"class (%p): unexpected kset_put() on glue_dirs, something is broken.",
+		container_of(kobj, struct subsys_private,
+				glue_dirs.kobj)->class);
+}
+
+static struct kobj_type glue_dirs_ktype = {
+	.release = glue_dirs_release_dummy,
+};
+
 /* Hotplug events for classes go to the class subsys */
 static struct kset *class_kset;
 
@@ -175,18 +193,14 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 		return -ENOMEM;
 	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
 	INIT_LIST_HEAD(&cp->interfaces);
-	kset_init(&cp->glue_dirs);
+	kset_init(&cp->glue_dirs, &glue_dirs_ktype, NULL);
 	__mutex_init(&cp->mutex, "subsys mutex", key);
-	error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
-	if (error) {
-		kfree(cp);
-		return error;
-	}
 
 	/* set the default /sys/dev directory for devices of this class */
 	if (!cls->dev_kobj)
 		cls->dev_kobj = sysfs_dev_char_kobj;
 
+	kset_init(&cp->subsys, &class_ktype, NULL);
 #if defined(CONFIG_BLOCK)
 	/* let the block class directory show up in the root of sysfs */
 	if (!sysfs_deprecated || cls != &block_class)
@@ -194,13 +208,19 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 #else
 	cp->subsys.kobj.kset = class_kset;
 #endif
-	cp->subsys.kobj.ktype = &class_ktype;
 	cp->class = cls;
 	cls->p = cp;
 
-	error = kset_register(&cp->subsys);
+	error = kset_register(&cp->subsys, cls->name, NULL);
 	if (error) {
-		kfree(cp);
+		/*
+		 * class->release() would be called by cp->subsys'
+		 * release function. Prevent this from happening in
+		 * the error case by zeroing cp->class out.
+		 */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);
 		return error;
 	}
 	error = add_class_attrs(class_get(cls));
fs/ext4/sysfs.c +6 -7
index 1b57c72..4011dd4 100644
@@ -339,9 +339,7 @@ static struct kobj_type ext4_ktype = {
 	.sysfs_ops	= &ext4_attr_ops,
 };
 
-static struct kset ext4_kset = {
-	.kobj   = {.ktype = &ext4_ktype},
-};
+static struct kset ext4_kset;
 
 static struct kobj_type ext4_feat_ktype = {
 	.default_attrs	= ext4_feat_attrs,
@@ -423,11 +421,12 @@ int __init ext4_init_sysfs(void)
 {
 	int ret;
 
-	kobject_set_name(&ext4_kset.kobj, "ext4");
-	ext4_kset.kobj.parent = fs_kobj;
-	ret = kset_register(&ext4_kset);
-	if (ret)
+	kset_init(&ext4_kset, &ext4_ktype, NULL);
+	ret = kset_register(&ext4_kset, "ext4", fs_kobj);
+	if (ret) {
+		kset_put(&ext4_kset);
 		return ret;
+	}
 
 	ret = kobject_init_and_add(&ext4_feat, &ext4_feat_ktype,
 				   NULL, "features");
fs/ocfs2/cluster/masklog.c +8 -5
index dfe162f..5763407 100644
@@ -164,13 +164,12 @@ static struct kobj_type mlog_ktype = {
 	.sysfs_ops     = &mlog_attr_ops,
 };
 
-static struct kset mlog_kset = {
-	.kobj   = {.ktype = &mlog_ktype},
-};
+static struct kset mlog_kset;
 
 int mlog_sys_init(struct kset *o2cb_kset)
 {
 	int i = 0;
+	int ret;
 
 	while (mlog_attrs[i].attr.mode) {
 		mlog_attr_ptrs[i] = &mlog_attrs[i].attr;
@@ -178,9 +177,13 @@ int mlog_sys_init(struct kset *o2cb_kset)
 	}
 	mlog_attr_ptrs[i] = NULL;
 
-	kobject_set_name(&mlog_kset.kobj, "logmask");
+	kset_init(&mlog_kset, &mlog_ktype, NULL);
 	mlog_kset.kobj.kset = o2cb_kset;
-	return kset_register(&mlog_kset);
+	ret = kset_register(&mlog_kset, "logmask", NULL);
+	if (ret)
+		kset_put(&mlog_kset);
+
+	return ret;
 }
 
 void mlog_sys_shutdown(void)
include/linux/kobject.h +4 -2
index e628459..d081817 100644
@@ -172,8 +172,10 @@ struct kset {
 	const struct kset_uevent_ops *uevent_ops;
 };
 
-extern void kset_init(struct kset *kset);
-extern int __must_check kset_register(struct kset *kset);
+extern void kset_init(struct kset *kset, struct kobj_type *ktype,
+		const struct kset_uevent_ops *uevent_ops);
+extern int __must_check kset_register(struct kset *kset, const char *name,
+				struct kobject *parent_kobj);
 extern void kset_unregister(struct kset *kset);
 extern struct kset * __must_check kset_create_and_add(const char *name,
 						const struct kset_uevent_ops *u,
lib/kobject.c +58 -36

150 lines not on this page · raw message

Signature · 1 line
2.6.3
#6 lore raw

PATCH v2 2/3 drivers/base/class: __class_register(): make error behaviour consistent

In reply to Nicolai Stange

If a class attribute's sysfs creation fails at the very end of __class_register(), the kset object already registered for the class itself is not unregistered again.

This is not consistent with the other possible failures of __class_register() for which nothing is left over to be manually released by the caller.

Since class attribute creation does not fail in the real world, the impact is minimal -- this patch is a cosmetic one.

Make __class_register() follow all-or-nothing semantics, i.e. unregister the already registered cp->subsys kset object on attribute creation failure.

---
 drivers/base/class.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/base/class.c +6 -0
index c9683cf..fc663d0 100644
@@ -225,6 +225,12 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 	}
 	error = add_class_attrs(class_get(cls));
 	class_put(cls);
+	if (error) {
+		/* as above, clear cp->class on error */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);
+	}
 	return error;
 }
 EXPORT_SYMBOL_GPL(__class_register);
Signature · 1 line
2.6.3
#7 lore raw

PATCH v2 3/3 drivers/base/class: __class_register(): invoke class' releaser on failure

In reply to Nicolai Stange

Currently, upon failure, __class_register() does not call the class_release member of the struct class object handed over to it. This leads to potentially duplicated cleanup code at the call sites: once for the error path handling a failed __class_register() and once for an orderly class deregistration.

Note however, that the impact is _very_ low: currently there are only five clients of __class_register() passing class objects with a non-trivial class_release member.
This patch is more about consolidating the __class_register() interface as well as slightly cleaning up the latter's implementation, i.e. cosmetic in nature.

The call sites of __class_register handing in a non-NULL class_release member are:
- drivers/base/class.c
- drivers/block/osdblk.c
- drivers/block/pktcdvd.c
- drivers/media/usb/pvrusb2/pvrusb2-sysfs.c
- drivers/pcmcia/cs.c
- drivers/isdn/mISDN/core.c

The first four just invoke a kfree() on the struct class object on failure of __class_register() as well as in their class_release functions.

The next to last one from the PCMCIA subsystem is special as it completes a condition variable in its class releaser pcmcia_release_socket_class(). This condition variable is waited on exclusively right after a call to class_unregister() in the module_exit handler. Despite the fact that the module_exit handler gets never executed if the __class_register() invocation from the module init handler fails, there would be no harm if it would.

Finally, the last candidate, the mISDN core, passes an empty class_release implementation to __class_register().

Make __class_register() invoke the class_release member of the given struct class object upon failure.
Adapt the callers to not do any cleanup as part of their error handling if already handled by their respective class releaser.

---
 drivers/base/class.c                      | 14 ++++----------
 drivers/block/osdblk.c                    |  1 -
 drivers/block/pktcdvd.c                   |  1 -
 drivers/media/usb/pvrusb2/pvrusb2-sysfs.c |  1 -
 4 files changed, 4 insertions(+), 13 deletions(-)
drivers/base/class.c +4 -10
index fc663d0..6f89ee5 100644
@@ -189,8 +189,11 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 	pr_debug("device class '%s': registering\n", cls->name);
 
 	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
-	if (!cp)
+	if (!cp) {
+		if (cls->class_release)
+			cls->class_release(cls);
 		return -ENOMEM;
+	}
 	klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
 	INIT_LIST_HEAD(&cp->interfaces);
 	kset_init(&cp->glue_dirs, &glue_dirs_ktype, NULL);
@@ -213,12 +216,6 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 
 	error = kset_register(&cp->subsys, cls->name, NULL);
 	if (error) {
-		/*
-		 * class->release() would be called by cp->subsys'
-		 * release function. Prevent this from happening in
-		 * the error case by zeroing cp->class out.
-		 */
-		cp->class = NULL;
 		cls->p = NULL;
 		kset_put(&cp->subsys);
 		return error;
@@ -226,8 +223,6 @@ int __class_register(struct class *cls, struct lock_class_key *key)
 	error = add_class_attrs(class_get(cls));
 	class_put(cls);
 	if (error) {
-		/* as above, clear cp->class on error */
-		cp->class = NULL;
 		cls->p = NULL;
 		kset_put(&cp->subsys);
 	}
@@ -285,7 +280,6 @@ struct class *__class_create(struct module *owner, const char *name,
 	return cls;
 
 error:
-	kfree(cls);
 	return ERR_PTR(retval);
 }
 EXPORT_SYMBOL_GPL(__class_create);
drivers/block/osdblk.c +0 -1
index 1b709a4..59d3fa3 100644
@@ -662,7 +662,6 @@ static int osdblk_sysfs_init(void)
 
 	ret = class_register(class_osdblk);
 	if (ret) {
-		kfree(class_osdblk);
 		class_osdblk = NULL;
 		printk(PFX "failed to create class osdblk\n");
 		return ret;
drivers/block/pktcdvd.c +0 -1
index d06c62e..34693ac 100644
@@ -429,7 +429,6 @@ static int pkt_sysfs_init(void)
 	class_pktcdvd->class_attrs = class_pktcdvd_attrs;
 	ret = class_register(class_pktcdvd);
 	if (ret) {
-		kfree(class_pktcdvd);
 		class_pktcdvd = NULL;
 		pr_err("failed to create class pktcdvd\n");
 		return ret;
drivers/media/usb/pvrusb2/pvrusb2-sysfs.c +0 -1
index 06fe63c..de7aca2 100644
@@ -797,7 +797,6 @@ struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
 	if (class_register(&clp->class)) {
 		pvr2_sysfs_trace(
 			"Registration failed for pvr2_sysfs_class id=%p",clp);
-		kfree(clp);
 		clp = NULL;
 	}
 	return clp;
Signature · 1 line
2.6.3
#8 lore raw

Re: [PATCH v2] kset- and class-registration cleanups

In reply to Nicolai Stange
Quoted 3 lines · Nicolai Stange

In order to have something to base further discussion on, here comes the second version.

Hi Greg,

I'd like to ask whether this is still in your review queue or did it slip through?

Should I resend?

Thank you,

Nicolai

Quoted 84 lines

In addition to some changes to the inital patch (now [1/3]), two additional ones have been introduced.

The three patches depend on one another in sequence.

For a detailed changelist, see the end of this mail.

Quoted 3 lines · Greg Kroah-Hartman

On Tue, Nov 17, 2015 at 01:04:19AM +0100, Nicolai Stange wrote:
Yes, but those calls all succeed, so this isn't a problem in the "real" world :)

I added a word about non-impact in the commit message of [1/3].

Quoted 6 lines
Quoted 6 lines
drivers/base/class.c +6 -0
+static void glue_dirs_release_dummy(struct kobject *kobj)
+{
+	/*
+	 * The glue_dirs kset member of struct subsys_private is never
+	 * registered and thus, never unregistered.
+	 * This release function is a dummy to make kset_init() happy.
Quoted 8 lines

drivers/base/class.c static struct kobj_type class_ktype = { · line 97

Quoted 6 lines
drivers/base/class.c +6 -0
+	 */
+	pr_err(
+	"class (%p): unexpected kset_put() on glue_dirs, something is broken.",
+		container_of(kobj, struct subsys_private,
+				glue_dirs.kobj)->class);
+	dump_stack();

How can this ever happen?

Not at all. I'm not sure I understand you correctly here.
Do you strictly want to abandon the dummy releaser, or more specifically, the dummy kobj_type?
For the moment, I turned the pr_err()/dump_stack() into a WARN() for the sake of better style.

Quoted 5 lines
Quoted 5 lines
drivers/base/class.c +3 -1
 	if (error) {
-		kfree(cp);
+		/*
+		 * class->release() would be called by cp->subsys'
+		 * release function. Prevent this from happening in
Quoted 8 lines

drivers/base/class.c int __class_register(struct class *cls, struct lock_class_key *key) · line 224

Quoted 5 lines
drivers/base/class.c +5 -0
+		 * the error case by zeroing cp->class out.
+		 */
+		cp->class = NULL;
+		cls->p = NULL;
+		kset_put(&cp->subsys);

That seems pretty messy, why can't we allow the release to be called? I don't think this is really correct :(

At the moment, it is necessary. I've added [3/3] for the case that you want cls->class_release() to get called from __class_register() on error. In [3/3] you will also find the (few) callers expecting the behaviour as it currently is.

Detailed changes from initial version to v2:
[1/3] lib/kobject: fix memory leak in error path of kset_create_and_add() This one is the original patch with a few changes:
- added a word of non-impact to commit message
- use WARN() instead of open coded pr_error()/dump_stack() pair in struct class' glue_dirs' dummy class releaser.
- follow my own advice in the docstring of kset_register() and use kset_put() instead of kset_unregister() on error of kset_register() in ext4's ext4_init_sysfs() and ocfs2's mlog_sys_init().

[2/3] drivers/base/class: __class_register(): make error behaviour consistent This one is new and quite unrelated to the original patch. Following the sidenote made in my last mail, it makes __class_register() properly clean up after itself on error.

[3/3] drivers/base/class: __class_register(): invoke class' releaser on failure This one is new.
It addresses Greg K-H's comment on the initial version about the messiness of avoiding to call class->class_release() from __class_register() on error. Given the fact that I had to introduce an explicit cls->class_release() in the early part when there is no kset object available yet, I'm by no means sure that it is much less messy now and that this patch is worth the trouble.
-> It is up to you to judge.
As there are enough people bothered already, I did not CC the people suggested for this one by get_maintainer.pl: all of them are maintainers of external subsystems and probably not particularly interested in __class_register() and friends. I will do this as soon as
a decision for this patch has been made, perhaps in a separate thread.