mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
driver core: Don't ignore class_dir_create_and_add() failure.
syzbot is hitting WARN() at kernfs_add_one() [1]. This is because kernfs_create_link() is confused by previous device_add() call which continued without setting dev->kobj.parent field when get_device_parent() failed by memory allocation fault injection. Fix this by propagating the error from class_dir_create_and_add() to the calllers of get_device_parent(). [1] https://syzkaller.appspot.com/bug?id=fae0fb607989ea744526d1c082a5b8de6529116f Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Reported-by: syzbot <syzbot+df47f81c226b31d89fb1@syzkaller.appspotmail.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cd4846c5a6
commit
84d0c27d62
@ -1467,7 +1467,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj)
|
||||
|
||||
dir = kzalloc(sizeof(*dir), GFP_KERNEL);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
dir->class = class;
|
||||
kobject_init(&dir->kobj, &class_dir_ktype);
|
||||
@ -1477,7 +1477,7 @@ class_dir_create_and_add(struct class *class, struct kobject *parent_kobj)
|
||||
retval = kobject_add(&dir->kobj, parent_kobj, "%s", class->name);
|
||||
if (retval < 0) {
|
||||
kobject_put(&dir->kobj);
|
||||
return NULL;
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
return &dir->kobj;
|
||||
}
|
||||
@ -1784,6 +1784,10 @@ int device_add(struct device *dev)
|
||||
|
||||
parent = get_device(dev->parent);
|
||||
kobj = get_device_parent(dev, parent);
|
||||
if (IS_ERR(kobj)) {
|
||||
error = PTR_ERR(kobj);
|
||||
goto parent_error;
|
||||
}
|
||||
if (kobj)
|
||||
dev->kobj.parent = kobj;
|
||||
|
||||
@ -1882,6 +1886,7 @@ done:
|
||||
kobject_del(&dev->kobj);
|
||||
Error:
|
||||
cleanup_glue_dir(dev, glue_dir);
|
||||
parent_error:
|
||||
put_device(parent);
|
||||
name_error:
|
||||
kfree(dev->p);
|
||||
@ -2701,6 +2706,11 @@ int device_move(struct device *dev, struct device *new_parent,
|
||||
device_pm_lock();
|
||||
new_parent = get_device(new_parent);
|
||||
new_parent_kobj = get_device_parent(dev, new_parent);
|
||||
if (IS_ERR(new_parent_kobj)) {
|
||||
error = PTR_ERR(new_parent_kobj);
|
||||
put_device(new_parent);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_debug("device: '%s': %s: moving to '%s'\n", dev_name(dev),
|
||||
__func__, new_parent ? dev_name(new_parent) : "<NULL>");
|
||||
|
Loading…
Reference in New Issue
Block a user