Message ID | 20210909222513.2184795-13-arequipeno@gmail.com |
---|---|
State | New |
Headers | show |
Series | Introduce block device LED trigger | expand |
Hi Ian, url: https://github.com/0day-ci/linux/commits/Ian-Pilcher/Introduce-block-device-LED-trigger/20210910-062756 base: a3fa7a101dcff93791d1b1bdb3affcad1410c8c1 config: i386-randconfig-m021-20210912 (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> smatch warnings: drivers/leds/trigger/ledtrig-blkdev.c:410 blkdev_disk_unlink_locked() error: dereferencing freed memory 'disk' vim +/disk +410 drivers/leds/trigger/ledtrig-blkdev.c 66cb682de7e8bd Ian Pilcher 2021-09-09 388 static void blkdev_disk_unlink_locked(struct ledtrig_blkdev_led *const led, 66cb682de7e8bd Ian Pilcher 2021-09-09 389 struct ledtrig_blkdev_link *const link, 66cb682de7e8bd Ian Pilcher 2021-09-09 390 struct ledtrig_blkdev_disk *const disk) 66cb682de7e8bd Ian Pilcher 2021-09-09 391 { 66cb682de7e8bd Ian Pilcher 2021-09-09 392 --ledtrig_blkdev_count; 66cb682de7e8bd Ian Pilcher 2021-09-09 393 66cb682de7e8bd Ian Pilcher 2021-09-09 394 if (ledtrig_blkdev_count == 0) 66cb682de7e8bd Ian Pilcher 2021-09-09 395 WARN_ON(!cancel_delayed_work_sync(&ledtrig_blkdev_work)); 66cb682de7e8bd Ian Pilcher 2021-09-09 396 66cb682de7e8bd Ian Pilcher 2021-09-09 397 sysfs_remove_link(led->dir, disk->gd->disk_name); 66cb682de7e8bd Ian Pilcher 2021-09-09 398 sysfs_remove_link(disk->dir, led->led_dev->name); 66cb682de7e8bd Ian Pilcher 2021-09-09 399 kobject_put(disk->dir); 66cb682de7e8bd Ian Pilcher 2021-09-09 400 66cb682de7e8bd Ian Pilcher 2021-09-09 401 hlist_del(&link->led_disks_node); 66cb682de7e8bd Ian Pilcher 2021-09-09 402 hlist_del(&link->disk_leds_node); 66cb682de7e8bd Ian Pilcher 2021-09-09 403 kfree(link); 66cb682de7e8bd Ian Pilcher 2021-09-09 404 66cb682de7e8bd Ian Pilcher 2021-09-09 405 if (hlist_empty(&disk->leds)) { 66cb682de7e8bd Ian Pilcher 2021-09-09 406 disk->gd->ledtrig = NULL; 66cb682de7e8bd Ian Pilcher 2021-09-09 407 kfree(disk); ^^^^ Freed. 66cb682de7e8bd Ian Pilcher 2021-09-09 408 } 66cb682de7e8bd Ian Pilcher 2021-09-09 409 66cb682de7e8bd Ian Pilcher 2021-09-09 @410 put_disk(disk->gd); ^^^^^^^^ Dereference after free. 66cb682de7e8bd Ian Pilcher 2021-09-09 411 } --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/drivers/leds/trigger/ledtrig-blkdev.c b/drivers/leds/trigger/ledtrig-blkdev.c index 26509837f037..fff67ebd28f2 100644 --- a/drivers/leds/trigger/ledtrig-blkdev.c +++ b/drivers/leds/trigger/ledtrig-blkdev.c @@ -379,6 +379,62 @@ static ssize_t link_device_store(struct device *const dev, static DEVICE_ATTR_WO(link_device); +/* + * + * unlink_device sysfs attribute - disassociate a device from this LED + * + */ + +static void blkdev_disk_unlink_locked(struct ledtrig_blkdev_led *const led, + struct ledtrig_blkdev_link *const link, + struct ledtrig_blkdev_disk *const disk) +{ + --ledtrig_blkdev_count; + + if (ledtrig_blkdev_count == 0) + WARN_ON(!cancel_delayed_work_sync(&ledtrig_blkdev_work)); + + sysfs_remove_link(led->dir, disk->gd->disk_name); + sysfs_remove_link(disk->dir, led->led_dev->name); + kobject_put(disk->dir); + + hlist_del(&link->led_disks_node); + hlist_del(&link->disk_leds_node); + kfree(link); + + if (hlist_empty(&disk->leds)) { + disk->gd->ledtrig = NULL; + kfree(disk); + } + + put_disk(disk->gd); +} + +static ssize_t unlink_device_store(struct device *const dev, + struct device_attribute *const attr, + const char *const buf, const size_t count) +{ + struct ledtrig_blkdev_led *const led = led_trigger_get_drvdata(dev); + struct ledtrig_blkdev_link *link; + + mutex_lock(&ledtrig_blkdev_mutex); + + hlist_for_each_entry(link, &led->disks, led_disks_node) { + + if (sysfs_streq(link->disk->gd->disk_name, buf)) { + blkdev_disk_unlink_locked(led, link, link->disk); + break; + } + } + + mutex_unlock(&ledtrig_blkdev_mutex); + + return count; +} + +static DEVICE_ATTR_WO(unlink_device); + + /* * * Initialization - register the trigger @@ -387,6 +443,7 @@ static DEVICE_ATTR_WO(link_device); static struct attribute *ledtrig_blkdev_attrs[] = { &dev_attr_link_device.attr, + &dev_attr_unlink_device.attr, NULL };
Add /sys/class/leds/<led>/unlink_device sysfs attribute Remove symlinks in /sys/class/leds/<led>/block_devices and /sys/block/<disk>/blkdev_leds Decrement reference count on /sys/block/<disk>/blkdev_leds directory (removes directory when empty) Cancel delayed work if no devices are associated with *any* LEDs Signed-off-by: Ian Pilcher <arequipeno@gmail.com> --- drivers/leds/trigger/ledtrig-blkdev.c | 57 +++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)