Skip to contentSkip to conversation

drivers: base: core: do not put noninitialized devices

PATCH In review Vasiliy Kulikov 2 participants 6 messages Nov 19, 2010 – Nov 20, 2010

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

PATCH 1/1 drivers: base: core: do not put noninitialized devices

If kobject_set_name_vargs() fails then put_device() frees device with zero kobj->state_initialized. This leads to WARN(). Divide device_register() call to device_initialize() call before kobject_set_name_vargs() and device_add() call after it.

---
Compile tested only.

 drivers/base/core.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
drivers/base/core.c +2 -1
index 46ff6c2..833ccf3 100644
@@ -1424,11 +1424,12 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
 	dev->release = device_create_release;
 	dev_set_drvdata(dev, drvdata);
 
+	device_initialize(dev);
 	retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
 	if (retval)
 		goto error;
 
-	retval = device_register(dev);
+	retval = device_add(dev);
 	if (retval)
 		goto error;
 
Signature · 1 line
1.7.0.4
#1 lore raw
Quoted 2 lines · Vasiliy Kulikov

If kobject_set_name_vargs() fails then put_device() frees device with zero kobj->state_initialized. This leads to WARN().

Have you seen this happen?

Quoted 6 lines

Divide device_register() call to device_initialize() call before kobject_set_name_vargs() and device_add() call after it.

---
Compile tested only.

I'd prefer not to change this unless you are seeing problems with the current code.

How did kobject_set_name_vargs() fail for you?

thanks,

greg k-h

#2 lore raw

Hi Greg,

Quoted 5 lines · Greg KH
Quoted 2 lines · Vasiliy Kulikov

If kobject_set_name_vargs() fails then put_device() frees device with zero kobj->state_initialized. This leads to WARN().

Have you seen this happen?

No, I've just analized the code. Without device_initialize() ->kobj is not initialized:

	kobject_init(&dev->kobj, &device_ktype) calls

	kobject_init_internal(kobj) calls

	kobj->state_initialized = 1;

kobject_put() calls WARN if state_initialized = 0:

    void kobject_put(struct kobject *kobj)
    {
        if (kobj) {
            if (!kobj->state_initialized)
                WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
                       "initialized, yet kobject_put() is being "
                       "called.\n", kobject_name(kobj), kobj);

I got the stack dump with similar code:

    struct device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    put_device(dev);
Quoted 4 lines

I'd prefer not to change this unless you are seeing problems with the current code.

How did kobject_set_name_vargs() fail for you?

int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
va_list vargs)

{
    [...]
	kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
	if (!kobj->name)
		return -ENOMEM;

char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)

{
    [...]
	p = kmalloc(len+1, gfp);
	if (!p)
		return NULL;

Unlikely, but may fail in OOM situation.

Thanks,

Signature · 2 lines
Vasiliy Kulikov
http://www.openwall.com - bringing security into open computing environments
#3 lore raw
Quoted 2 lines · Vasiliy Kulikov

No, I've just analized the code. Without device_initialize() ->kobj is not initialized:

I mean 'not set' instead of 'not initialized' - it is already kzalloc()'ed :)

Thanks,

Signature · 2 lines
Vasiliy Kulikov
http://www.openwall.com - bringing security into open computing environments
#4 lore raw
In reply to Vasiliy Kulikov
Quoted 29 lines · Vasiliy Kulikov

Hi Greg,

Quoted 5 lines · Greg KH
Quoted 2 lines · Vasiliy Kulikov

If kobject_set_name_vargs() fails then put_device() frees device with zero kobj->state_initialized. This leads to WARN().

Have you seen this happen?

No, I've just analized the code. Without device_initialize() ->kobj is not initialized:

	kobject_init(&dev->kobj, &device_ktype) calls

	kobject_init_internal(kobj) calls

	kobj->state_initialized = 1;

kobject_put() calls WARN if state_initialized = 0:

    void kobject_put(struct kobject *kobj)
    {
        if (kobj) {
            if (!kobj->state_initialized)
                WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
                       "initialized, yet kobject_put() is being "
                       "called.\n", kobject_name(kobj), kobj);
Quoted 4 lines

I got the stack dump with similar code:

    struct device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    put_device(dev);

Sure, that's illegal code, and we want to warn about that. So I would say, if an error happens, we want to see this message so the code should stay as-is.

thanks,

greg k-h

#5 lore raw
Quoted 12 lines · Greg KH
Quoted 11 lines · Vasiliy Kulikov

kobject_put() calls WARN if state_initialized = 0:

    void kobject_put(struct kobject *kobj)
    {
        if (kobj) {
            if (!kobj->state_initialized)
                WARN(1, KERN_WARNING "kobject: '%s' (%p): is not "
                       "initialized, yet kobject_put() is being "
                       "called.\n", kobject_name(kobj), kobj);
Quoted 6 lines
Quoted 4 lines

I got the stack dump with similar code:

    struct device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    put_device(dev);

Sure, that's illegal code,

You might misunderstood me, see this part of device_create_vargs():

struct device *device_create_vargs(...)

{
    ...
	dev = kzalloc(sizeof(*dev), GFP_KERNEL); <<<
	if (!dev)
        ...

	dev->devt = devt;
	dev->class = class;
	dev->parent = parent;
	dev->release = device_create_release;
	dev_set_drvdata(dev, drvdata);

	retval = kobject_set_name_vargs(&dev->kobj, fmt, args); <<<
	if (retval)
		goto error; <<<
    ...

error:

	put_device(dev); <<<
    ...
}

It is device_create_vargs()'s mistake, not the caller.

Quoted 3 lines

and we want to warn about that. So I would
say, if an error happens, we want to see this message so the code should stay as-is.

If you mean "if memomy allocation for name fails then we want to see message about allocation failure" then maybe use pr_err("No mem for device name\n") instead of confusing "kobject is not initialized, yet kobject_put() is being called"?

Thanks,

Signature · 2 lines
Vasiliy Kulikov
http://www.openwall.com - bringing security into open computing environments