Skip to content

Commit

Permalink
[PATCH] Driver core: class_device_add needs error checks
Browse files Browse the repository at this point in the history
class_device_add needs to check the return value of all the setup it
does. It doesn't handle out of memory well. This is not complete, probably
more needs to be done.

Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Stephen Hemminger authored and Greg Kroah-Hartman committed Jun 21, 2006
1 parent 3dda4e3 commit b7fe4a6
Showing 1 changed file with 54 additions and 18 deletions.
72 changes: 54 additions & 18 deletions drivers/base/class.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,60 +535,79 @@ int class_device_add(struct class_device *class_dev)
return -EINVAL;

if (!strlen(class_dev->class_id))
goto register_done;
goto out1;

parent_class = class_get(class_dev->class);
if (!parent_class)
goto register_done;
goto out1;

parent_class_dev = class_device_get(class_dev->parent);

pr_debug("CLASS: registering class device: ID = '%s'\n",
class_dev->class_id);

/* first, register with generic layer. */
kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
if (error)
goto out2;

if (parent_class_dev)
class_dev->kobj.parent = &parent_class_dev->kobj;
else
class_dev->kobj.parent = &parent_class->subsys.kset.kobj;

error = kobject_add(&class_dev->kobj);
if (error)
goto register_done;
goto out2;

/* add the needed attributes to this device */
class_dev->uevent_attr.attr.name = "uevent";
class_dev->uevent_attr.attr.mode = S_IWUSR;
class_dev->uevent_attr.attr.owner = parent_class->owner;
class_dev->uevent_attr.store = store_uevent;
class_device_create_file(class_dev, &class_dev->uevent_attr);
error = class_device_create_file(class_dev, &class_dev->uevent_attr);
if (error)
goto out3;

if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
kobject_del(&class_dev->kobj);
goto register_done;
goto out4;
}
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
attr->attr.owner = parent_class->owner;
attr->show = show_dev;
class_device_create_file(class_dev, attr);
error = class_device_create_file(class_dev, attr);
if (error) {
kfree(attr);
goto out4;
}

class_dev->devt_attr = attr;
}

class_device_add_attrs(class_dev);
error = class_device_add_attrs(class_dev);
if (error)
goto out5;

if (class_dev->dev) {
class_name = make_class_name(class_dev);
sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
class_name);
error = sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
if (error)
goto out6;
error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
class_name);
if (error)
goto out7;
}

class_device_add_groups(class_dev);
error = class_device_add_groups(class_dev);
if (error)
goto out8;

kobject_uevent(&class_dev->kobj, KOBJ_ADD);

Expand All @@ -601,11 +620,28 @@ int class_device_add(struct class_device *class_dev)
}
up(&parent_class->sem);

register_done:
if (error) {
class_put(parent_class);
goto out1;

out8:
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, class_name);
out7:
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device");
out6:
class_device_remove_attrs(class_dev);
out5:
if (class_dev->devt_attr)
class_device_remove_file(class_dev, class_dev->devt_attr);
out4:
class_device_remove_file(class_dev, &class_dev->uevent_attr);
out3:
kobject_del(&class_dev->kobj);
out2:
if(parent_class_dev)
class_device_put(parent_class_dev);
}
class_put(parent_class);
out1:
class_device_put(class_dev);
kfree(class_name);
return error;
Expand Down

0 comments on commit b7fe4a6

Please sign in to comment.