Skip to content

Commit 3a653b2

Browse files
Ye Binsnitm
authored andcommitted
dm thin metadata: Fix use-after-free in dm_bm_set_read_only
The following error ocurred when testing disk online/offline: [ 301.798344] device-mapper: thin: 253:5: aborting current metadata transaction [ 301.848441] device-mapper: thin: 253:5: failed to abort metadata transaction [ 301.849206] Aborting journal on device dm-26-8. [ 301.850489] EXT4-fs error (device dm-26) in __ext4_new_inode:943: Journal has aborted [ 301.851095] EXT4-fs (dm-26): Delayed block allocation failed for inode 398742 at logical offset 181 with max blocks 19 with error 30 [ 301.854476] BUG: KASAN: use-after-free in dm_bm_set_read_only+0x3a/0x40 [dm_persistent_data] Reason is: metadata_operation_failed abort_transaction dm_pool_abort_metadata __create_persistent_data_objects r = __open_or_format_metadata if (r) --> If failed will free pmd->bm but pmd->bm not set NULL dm_block_manager_destroy(pmd->bm); set_pool_mode dm_pool_metadata_read_only(pool->pmd); dm_bm_set_read_only(pmd->bm); --> use-after-free Add checks to see if pmd->bm is NULL in dm_bm_set_read_only and dm_bm_set_read_write functions. If bm is NULL it means creating the bm failed and so dm_bm_is_read_only must return true. Signed-off-by: Ye Bin <[email protected]> Cc: [email protected] Signed-off-by: Mike Snitzer <[email protected]>
1 parent 219403d commit 3a653b2

File tree

2 files changed

+9
-7
lines changed

2 files changed

+9
-7
lines changed

drivers/md/dm-thin-metadata.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ int dm_pool_metadata_close(struct dm_pool_metadata *pmd)
958958
}
959959

960960
pmd_write_lock_in_core(pmd);
961-
if (!dm_bm_is_read_only(pmd->bm) && !pmd->fail_io) {
961+
if (!pmd->fail_io && !dm_bm_is_read_only(pmd->bm)) {
962962
r = __commit_transaction(pmd);
963963
if (r < 0)
964964
DMWARN("%s: __commit_transaction() failed, error = %d",

drivers/md/persistent-data/dm-block-manager.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ int dm_bm_write_lock(struct dm_block_manager *bm,
493493
void *p;
494494
int r;
495495

496-
if (bm->read_only)
496+
if (dm_bm_is_read_only(bm))
497497
return -EPERM;
498498

499499
p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result);
@@ -562,7 +562,7 @@ int dm_bm_write_lock_zero(struct dm_block_manager *bm,
562562
struct buffer_aux *aux;
563563
void *p;
564564

565-
if (bm->read_only)
565+
if (dm_bm_is_read_only(bm))
566566
return -EPERM;
567567

568568
p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result);
@@ -602,7 +602,7 @@ EXPORT_SYMBOL_GPL(dm_bm_unlock);
602602

603603
int dm_bm_flush(struct dm_block_manager *bm)
604604
{
605-
if (bm->read_only)
605+
if (dm_bm_is_read_only(bm))
606606
return -EPERM;
607607

608608
return dm_bufio_write_dirty_buffers(bm->bufio);
@@ -616,19 +616,21 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b)
616616

617617
bool dm_bm_is_read_only(struct dm_block_manager *bm)
618618
{
619-
return bm->read_only;
619+
return (bm ? bm->read_only : true);
620620
}
621621
EXPORT_SYMBOL_GPL(dm_bm_is_read_only);
622622

623623
void dm_bm_set_read_only(struct dm_block_manager *bm)
624624
{
625-
bm->read_only = true;
625+
if (bm)
626+
bm->read_only = true;
626627
}
627628
EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
628629

629630
void dm_bm_set_read_write(struct dm_block_manager *bm)
630631
{
631-
bm->read_only = false;
632+
if (bm)
633+
bm->read_only = false;
632634
}
633635
EXPORT_SYMBOL_GPL(dm_bm_set_read_write);
634636

0 commit comments

Comments
 (0)