zram: avoid race between zram_remove and disksize_store
Hello Ming Lei,
The patch 5a4b653655d5: "zram: avoid race between zram_remove and disksize_store" from Oct 25, 2021, leads to the following Smatch static checker warning:
drivers/block/zram/zram_drv.c:2044 zram_remove() warn: 'zram->mem_pool' double freed
drivers/block/zram/zram_drv.c
2002 static int zram_remove(struct zram *zram)
2003 {
2004 struct block_device *bdev = zram->disk->part0;
2005 bool claimed;
2006
2007 mutex_lock(&bdev->bd_disk->open_mutex);
2008 if (bdev->bd_openers) {
2009 mutex_unlock(&bdev->bd_disk->open_mutex);
2010 return -EBUSY;
2011 }
2012
2013 claimed = zram->claim;
2014 if (!claimed)
2015 zram->claim = true;
2016 mutex_unlock(&bdev->bd_disk->open_mutex);
2017
2018 zram_debugfs_unregister(zram);
2019
2020 if (claimed) {
2021 /*
2022 * If we were claimed by reset_store(), del_gendisk() will
2023 * wait until reset_store() is done, so nothing need to do.
2024 */
2025 ;
2026 } else {
2027 /* Make sure all the pending I/O are finished */
2028 sync_blockdev(bdev);
2029 zram_reset_device(zram);
^^^^^^^^^^^^^^^^^^^^^^^^This frees zram->mem_pool in zram_meta_free().
2030 }
2031
2032 pr_info("Removed device: %s\n", zram->disk->disk_name);
2033
2034 del_gendisk(zram->disk);
2035
2036 /* del_gendisk drains pending reset_store */
2037 WARN_ON_ONCE(claimed && zram->claim);
2038
2039 /*
2040 * disksize_store() may be called in between zram_reset_device()
2041 * and del_gendisk(), so run the last reset to avoid leaking
2042 * anything allocated with disksize_store()
2043 */--> 2044 zram_reset_device(zram);
This double frees it.
2045
2046 blk_cleanup_disk(zram->disk);
2047 kfree(zram);
2048 return 0;
2049 }regards,
dan carpenter
Quoted 55 lines · Dan Carpenter
Hello Ming Lei,
The patch
5a4b653655d5: "zram: avoid race betweenzram_removeanddisksize_store" from Oct 25, 2021, leads to the following Smatch static checker warning:drivers/block/zram/zram_drv.c:2044 zram_remove() warn: 'zram->mem_pool' double freed
drivers/block/zram/zram_drv.c2002 static int zram_remove(struct zram *zram) 2003 { 2004 struct block_device *bdev = zram->disk->part0; 2005 bool claimed; 2006 2007 mutex_lock(&bdev->bd_disk->open_mutex); 2008 if (bdev->bd_openers) { 2009 mutex_unlock(&bdev->bd_disk->open_mutex); 2010 return -EBUSY; 2011 } 2012 2013 claimed = zram->claim; 2014 if (!claimed) 2015 zram->claim = true; 2016 mutex_unlock(&bdev->bd_disk->open_mutex); 2017 2018 zram_debugfs_unregister(zram); 2019 2020 if (claimed) { 2021 /* 2022 * If we were claimed by reset_store(), del_gendisk() will 2023 * wait until reset_store() is done, so nothing need to do. 2024 */ 2025 ; 2026 } else { 2027 /* Make sure all the pending I/O are finished */ 2028 sync_blockdev(bdev); 2029 zram_reset_device(zram); ^^^^^^^^^^^^^^^^^^^^^^^^This frees
zram->mem_poolinzram_meta_free().2030 } 2031 2032 pr_info("Removed device: %s\n", zram->disk->disk_name); 2033 2034 del_gendisk(zram->disk); 2035 2036 /* del_gendisk drains pending reset_store */ 2037 WARN_ON_ONCE(claimed && zram->claim); 2038 2039 /* 2040 * disksize_store() may be called in between zram_reset_device() 2041 * and del_gendisk(), so run the last reset to avoid leaking 2042 * anything allocated with disksize_store() 2043 */
Quoted 3 lines
--> 2044
zram_reset_device(zram);This double frees it.
I should have included all three warnings:
drivers/block/zram/zram_drv.c:2044 zram_remove() warn: 'zram->mem_pool' double freed drivers/block/zram/zram_drv.c:2044 zram_remove() warn: 'zram->mem_pool->name' double freed drivers/block/zram/zram_drv.c:2044 zram_remove() warn: 'zram->table' double freed
regards,
dan carpenter
Hello Dan,
Quoted 55 lines · Dan Carpenter
Hello Ming Lei,
The patch
5a4b653655d5: "zram: avoid race betweenzram_removeanddisksize_store" from Oct 25, 2021, leads to the following Smatch static checker warning:drivers/block/zram/zram_drv.c:2044 zram_remove() warn: 'zram->mem_pool' double freed
drivers/block/zram/zram_drv.c2002 static int zram_remove(struct zram *zram) 2003 { 2004 struct block_device *bdev = zram->disk->part0; 2005 bool claimed; 2006 2007 mutex_lock(&bdev->bd_disk->open_mutex); 2008 if (bdev->bd_openers) { 2009 mutex_unlock(&bdev->bd_disk->open_mutex); 2010 return -EBUSY; 2011 } 2012 2013 claimed = zram->claim; 2014 if (!claimed) 2015 zram->claim = true; 2016 mutex_unlock(&bdev->bd_disk->open_mutex); 2017 2018 zram_debugfs_unregister(zram); 2019 2020 if (claimed) { 2021 /* 2022 * If we were claimed by reset_store(), del_gendisk() will 2023 * wait until reset_store() is done, so nothing need to do. 2024 */ 2025 ; 2026 } else { 2027 /* Make sure all the pending I/O are finished */ 2028 sync_blockdev(bdev); 2029 zram_reset_device(zram); ^^^^^^^^^^^^^^^^^^^^^^^^This frees
zram->mem_poolinzram_meta_free().2030 } 2031 2032 pr_info("Removed device: %s\n", zram->disk->disk_name); 2033 2034 del_gendisk(zram->disk); 2035 2036 /* del_gendisk drains pending reset_store */ 2037 WARN_ON_ONCE(claimed && zram->claim); 2038 2039 /* 2040 * disksize_store() may be called in between zram_reset_device() 2041 * and del_gendisk(), so run the last reset to avoid leaking 2042 * anything allocated with disksize_store() 2043 */
Quoted 3 lines
--> 2044
zram_reset_device(zram);This double frees it.
No.
Inside zram_reset_device(), if init_done()(zram->disksize) is zero, zram_reset_device() returns immediately, otherwise zram->disksize is cleared and zram_meta_free() is run in zram_reset_device(). Meantime zram->init_lock protects the reset and disksize_store().
The 2nd zram_reset_device() can only reset device if disksize_store() sets new zram->disksize and allocates new meta after the 1st zram_reset_device().
Seems smatch static checker need to be improved to cover this case?
Thanks,
Ming
Quoted 11 lines · Ming Lei
Quoted 3 lines
--> 2044
zram_reset_device(zram);This double frees it.
No.
Inside
zram_reset_device(), if init_done()(zram->disksize) is zero,zram_reset_device()returns immediately, otherwisezram->disksizeis cleared andzram_meta_free()is run inzram_reset_device(). Meantimezram->init_lockprotects the reset anddisksize_store().
Quoted 4 lines
The 2nd
zram_reset_device()can only reset device ifdisksize_store()sets newzram->disksizeand allocates new meta after the 1stzram_reset_device().Seems smatch static checker need to be improved to cover this case?
Yep. It's a bug in Smatch. It's supposed to parse this correctly.
I will investigate. Thanks!
regards,
dan carpenter