Skip to content

Commit cb65b28

Browse files
Li LingfengMike Snitzer
authored andcommitted
dm thin metadata: check fail_io before using data_sm
Must check pmd->fail_io before using pmd->data_sm since pmd->data_sm may be destroyed by other processes. P1(kworker) P2(message) do_worker process_prepared process_prepared_discard_passdown_pt2 dm_pool_dec_data_range pool_message commit dm_pool_commit_metadata ↓ // commit failed metadata_operation_failed abort_transaction dm_pool_abort_metadata __open_or_format_metadata ↓ dm_sm_disk_open ↓ // open failed // pmd->data_sm is NULL dm_sm_dec_blocks ↓ // try to access pmd->data_sm --> UAF As shown above, if dm_pool_commit_metadata() and dm_pool_abort_metadata() fail in pool_message process, kworker may trigger UAF. Fixes: be500ed ("dm space maps: improve performance with inc/dec on ranges of blocks") Cc: [email protected] Signed-off-by: Li Lingfeng <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 2760904 commit cb65b28

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

drivers/md/dm-thin-metadata.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,35 +1756,39 @@ int dm_thin_remove_range(struct dm_thin_device *td,
17561756

17571757
int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
17581758
{
1759-
int r;
1759+
int r = -EINVAL;
17601760
uint32_t ref_count;
17611761

17621762
down_read(&pmd->root_lock);
1763-
r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
1764-
if (!r)
1765-
*result = (ref_count > 1);
1763+
if (!pmd->fail_io) {
1764+
r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
1765+
if (!r)
1766+
*result = (ref_count > 1);
1767+
}
17661768
up_read(&pmd->root_lock);
17671769

17681770
return r;
17691771
}
17701772

17711773
int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e)
17721774
{
1773-
int r = 0;
1775+
int r = -EINVAL;
17741776

17751777
pmd_write_lock(pmd);
1776-
r = dm_sm_inc_blocks(pmd->data_sm, b, e);
1778+
if (!pmd->fail_io)
1779+
r = dm_sm_inc_blocks(pmd->data_sm, b, e);
17771780
pmd_write_unlock(pmd);
17781781

17791782
return r;
17801783
}
17811784

17821785
int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e)
17831786
{
1784-
int r = 0;
1787+
int r = -EINVAL;
17851788

17861789
pmd_write_lock(pmd);
1787-
r = dm_sm_dec_blocks(pmd->data_sm, b, e);
1790+
if (!pmd->fail_io)
1791+
r = dm_sm_dec_blocks(pmd->data_sm, b, e);
17881792
pmd_write_unlock(pmd);
17891793

17901794
return r;

0 commit comments

Comments
 (0)