Re: [PATCH] lib/kobject: fix memory leak in error path of kset_create_and_add()

2015-11-17 Thread Nicolai Stange
Nicolai Stange  writes:

> Greg Kroah-Hartman  writes:
>
>> On Tue, Nov 17, 2015 at 01:04:19AM +0100, Nicolai Stange wrote:
>>> +}
>>> +
>>> +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);
>>
>> 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.

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.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] lib/kobject: fix memory leak in error path of kset_create_and_add()

2015-11-17 Thread Nicolai Stange
Greg Kroah-Hartman  writes:

> On Tue, Nov 17, 2015 at 01:04:19AM +0100, Nicolai Stange wrote:
>> 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.

>> 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.
>> 
>> Signed-off-by: Nicolai Stange 
>> ---
>> 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(-)
>> 
>> diff --git a/drivers/base/bus.c b/drivers/base/bus.c
>> index 5005924..a81227c 100644
>> --- a/drivers/base/bus.c
>> +++ b/drivers/base/bus.c
>> @@ -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);
>> diff --git a/drivers/base/class.c b/drivers/base/class.c
>> index 71059e3..94a5b040 100644
>> --- a/drivers/base/class.c
>> +++ b/drivers/base/class.c
>> @@ -19,6 +19,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #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();
>
> 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
   

Re: [PATCH] lib/kobject: fix memory leak in error path of kset_create_and_add()

2015-11-16 Thread Greg Kroah-Hartman
On Tue, Nov 17, 2015 at 01:04:19AM +0100, Nicolai Stange wrote:
> 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 0x8800b4a1f428 (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.k.
> backtrace:
>   [] kmemleak_alloc+0x4e/0xb0
>   [] __kmalloc_track_caller+0x2b1/0x390
>   [] kstrdup+0x31/0x60
>   [] kstrdup_const+0x23/0x30
>   [] kvasprintf_const+0x54/0x90
>   [] kobject_set_name_vargs+0x21/0xa0
>   [] kobject_set_name+0x4e/0x70
>   [] 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.

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

> 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.
> 
> Signed-off-by: Nicolai Stange 
> ---
> 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(-)
> 
> diff --git a/drivers/base/bus.c b/drivers/base/bus.c
> index 5005924..a81227c 100644
> --- a/drivers/base/bus.c
> +++ b/drivers/base/bus.c
> @@ -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);
> diff --git a/drivers/base/class.c b/drivers/base/class.c
> index 71059e3..94a5b040 100644
> --- a/drivers/base/class.c
> +++ b/drivers/base/class.c
> @@ -19,6 +19,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #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.",
> + 

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

2015-11-16 Thread 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 0x8800b4a1f428 (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.k.
backtrace:
  [] kmemleak_alloc+0x4e/0xb0
  [] __kmalloc_track_caller+0x2b1/0x390
  [] kstrdup+0x31/0x60
  [] kstrdup_const+0x23/0x30
  [] kvasprintf_const+0x54/0x90
  [] kobject_set_name_vargs+0x21/0xa0
  [] kobject_set_name+0x4e/0x70
  [] 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.

Signed-off-by: Nicolai Stange 
---
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(-)

diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 5005924..a81227c 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -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);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 71059e3..94a5b040 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #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 __