forked from luck/tmp_suning_uos_patched
dm zoned: Fix reference counter initial value of chunk works
Dm-zoned initializes reference counters of new chunk works with zero value and refcount_inc() is called to increment the counter. However, the refcount_inc() function handles the addition to zero value as an error and triggers the warning as follows: refcount_t: addition on 0; use-after-free. WARNING: CPU: 7 PID: 1506 at lib/refcount.c:25 refcount_warn_saturate+0x68/0xf0 ... CPU: 7 PID: 1506 Comm: systemd-udevd Not tainted 5.4.0+ #134 ... Call Trace: dmz_map+0x2d2/0x350 [dm_zoned] __map_bio+0x42/0x1a0 __split_and_process_non_flush+0x14a/0x1b0 __split_and_process_bio+0x83/0x240 ? kmem_cache_alloc+0x165/0x220 dm_process_bio+0x90/0x230 ? generic_make_request_checks+0x2e7/0x680 dm_make_request+0x3e/0xb0 generic_make_request+0xcf/0x320 ? memcg_drain_all_list_lrus+0x1c0/0x1c0 submit_bio+0x3c/0x160 ? guard_bio_eod+0x2c/0x130 mpage_readpages+0x182/0x1d0 ? bdev_evict_inode+0xf0/0xf0 read_pages+0x6b/0x1b0 __do_page_cache_readahead+0x1ba/0x1d0 force_page_cache_readahead+0x93/0x100 generic_file_read_iter+0x83a/0xe40 ? __seccomp_filter+0x7b/0x670 new_sync_read+0x12a/0x1c0 vfs_read+0x9d/0x150 ksys_read+0x5f/0xe0 do_syscall_64+0x5b/0x180 entry_SYSCALL_64_after_hwframe+0x44/0xa9 ... After this warning, following refcount API calls for the counter all fail to change the counter value. Fix this by setting the initial reference counter value not zero but one for the new chunk works. Instead, do not call refcount_inc() via dmz_get_chunk_work() for the new chunks works. The failure was observed with linux version 5.4 with CONFIG_REFCOUNT_FULL enabled. Refcount rework was merged to linux version 5.5 by the commit168829ad09
("Merge branch 'locking-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip"). After this commit, CONFIG_REFCOUNT_FULL was removed and the failure was observed regardless of kernel configuration. Linux version 4.20 merged the commit092b564876
("dm zoned: target: use refcount_t for dm zoned reference counters"). Before this commit, dm zoned used atomic_t APIs which does not check addition to zero, then this fix is not necessary. Fixes:092b564876
("dm zoned: target: use refcount_t for dm zoned reference counters") Cc: stable@vger.kernel.org # 5.4+ Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
41c526c5af
commit
ee63634bae
|
@ -533,8 +533,9 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
|
|||
|
||||
/* Get the BIO chunk work. If one is not active yet, create one */
|
||||
cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk);
|
||||
if (!cw) {
|
||||
|
||||
if (cw) {
|
||||
dmz_get_chunk_work(cw);
|
||||
} else {
|
||||
/* Create a new chunk work */
|
||||
cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO);
|
||||
if (unlikely(!cw)) {
|
||||
|
@ -543,7 +544,7 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
|
|||
}
|
||||
|
||||
INIT_WORK(&cw->work, dmz_chunk_work);
|
||||
refcount_set(&cw->refcount, 0);
|
||||
refcount_set(&cw->refcount, 1);
|
||||
cw->target = dmz;
|
||||
cw->chunk = chunk;
|
||||
bio_list_init(&cw->bio_list);
|
||||
|
@ -556,7 +557,6 @@ static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio)
|
|||
}
|
||||
|
||||
bio_list_add(&cw->bio_list, bio);
|
||||
dmz_get_chunk_work(cw);
|
||||
|
||||
dmz_reclaim_bio_acc(dmz->reclaim);
|
||||
if (queue_work(dmz->chunk_wq, &cw->work))
|
||||
|
|
Loading…
Reference in New Issue
Block a user