lkml.org 
[lkml]   [2018]   [Jun]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 23/39] driver core: Dont ignore class_dir_create_and_add() failure.
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

    commit 84d0c27d6233a9ba0578b20f5a09701eb66cee42 upstream.

    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>

    ---
    drivers/base/core.c | 14 ++++++++++++--
    1 file changed, 12 insertions(+), 2 deletions(-)

    --- a/drivers/base/core.c
    +++ b/drivers/base/core.c
    @@ -759,7 +759,7 @@ class_dir_create_and_add(struct class *c

    dir = kzalloc(sizeof(*dir), GFP_KERNEL);
    if (!dir)
    - return NULL;
    + return ERR_PTR(-ENOMEM);

    dir->class = class;
    kobject_init(&dir->kobj, &class_dir_ktype);
    @@ -769,7 +769,7 @@ class_dir_create_and_add(struct class *c
    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;
    }
    @@ -1076,6 +1076,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;

    @@ -1174,6 +1178,7 @@ done:
    kobject_del(&dev->kobj);
    Error:
    cleanup_glue_dir(dev, glue_dir);
    +parent_error:
    put_device(parent);
    name_error:
    kfree(dev->p);
    @@ -1991,6 +1996,11 @@ int device_move(struct device *dev, stru
    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>");

    \
     
     \ /
      Last update: 2018-06-24 17:55    [W:4.378 / U:1.124 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site