Skip to content

Commit 9e23acf

Browse files
committed
Merge tag 'for-6.12/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mikulas Patocka: - fix memory safety bugs in dm-cache - fix restart/panic logic in dm-verity - fix 32-bit unsigned integer overflow in dm-unstriped - fix a device mapper crash if blk_alloc_disk fails * tag 'for-6.12/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm cache: fix potential out-of-bounds access on the first resume dm cache: optimize dirty bit checking with find_next_bit when resizing dm cache: fix out-of-bounds access to the dirty bitset when resizing dm cache: fix flushing uninitialized delayed_work on cache_ctr error dm cache: correct the number of origin blocks to match the target length dm-verity: don't crash if panic_on_corruption is not selected dm-unstriped: cast an operand to sector_t to prevent potential uint32_t overflow dm: fix a crash if blk_alloc_disk fails
2 parents 0951fed + c0ade5d commit 9e23acf

File tree

5 files changed

+42
-35
lines changed

5 files changed

+42
-35
lines changed

drivers/md/dm-cache-target.c

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,16 +1905,13 @@ static void check_migrations(struct work_struct *ws)
19051905
* This function gets called on the error paths of the constructor, so we
19061906
* have to cope with a partially initialised struct.
19071907
*/
1908-
static void destroy(struct cache *cache)
1908+
static void __destroy(struct cache *cache)
19091909
{
1910-
unsigned int i;
1911-
19121910
mempool_exit(&cache->migration_pool);
19131911

19141912
if (cache->prison)
19151913
dm_bio_prison_destroy_v2(cache->prison);
19161914

1917-
cancel_delayed_work_sync(&cache->waker);
19181915
if (cache->wq)
19191916
destroy_workqueue(cache->wq);
19201917

@@ -1942,13 +1939,22 @@ static void destroy(struct cache *cache)
19421939
if (cache->policy)
19431940
dm_cache_policy_destroy(cache->policy);
19441941

1942+
bioset_exit(&cache->bs);
1943+
1944+
kfree(cache);
1945+
}
1946+
1947+
static void destroy(struct cache *cache)
1948+
{
1949+
unsigned int i;
1950+
1951+
cancel_delayed_work_sync(&cache->waker);
1952+
19451953
for (i = 0; i < cache->nr_ctr_args ; i++)
19461954
kfree(cache->ctr_args[i]);
19471955
kfree(cache->ctr_args);
19481956

1949-
bioset_exit(&cache->bs);
1950-
1951-
kfree(cache);
1957+
__destroy(cache);
19521958
}
19531959

19541960
static void cache_dtr(struct dm_target *ti)
@@ -2003,7 +2009,6 @@ struct cache_args {
20032009
sector_t cache_sectors;
20042010

20052011
struct dm_dev *origin_dev;
2006-
sector_t origin_sectors;
20072012

20082013
uint32_t block_size;
20092014

@@ -2084,6 +2089,7 @@ static int parse_cache_dev(struct cache_args *ca, struct dm_arg_set *as,
20842089
static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as,
20852090
char **error)
20862091
{
2092+
sector_t origin_sectors;
20872093
int r;
20882094

20892095
if (!at_least_one_arg(as, error))
@@ -2096,8 +2102,8 @@ static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as,
20962102
return r;
20972103
}
20982104

2099-
ca->origin_sectors = get_dev_size(ca->origin_dev);
2100-
if (ca->ti->len > ca->origin_sectors) {
2105+
origin_sectors = get_dev_size(ca->origin_dev);
2106+
if (ca->ti->len > origin_sectors) {
21012107
*error = "Device size larger than cached device";
21022108
return -EINVAL;
21032109
}
@@ -2407,7 +2413,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
24072413

24082414
ca->metadata_dev = ca->origin_dev = ca->cache_dev = NULL;
24092415

2410-
origin_blocks = cache->origin_sectors = ca->origin_sectors;
2416+
origin_blocks = cache->origin_sectors = ti->len;
24112417
origin_blocks = block_div(origin_blocks, ca->block_size);
24122418
cache->origin_blocks = to_oblock(origin_blocks);
24132419

@@ -2561,7 +2567,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
25612567
*result = cache;
25622568
return 0;
25632569
bad:
2564-
destroy(cache);
2570+
__destroy(cache);
25652571
return r;
25662572
}
25672573

@@ -2612,7 +2618,7 @@ static int cache_ctr(struct dm_target *ti, unsigned int argc, char **argv)
26122618

26132619
r = copy_ctr_args(cache, argc - 3, (const char **)argv + 3);
26142620
if (r) {
2615-
destroy(cache);
2621+
__destroy(cache);
26162622
goto out;
26172623
}
26182624

@@ -2895,19 +2901,19 @@ static dm_cblock_t get_cache_dev_size(struct cache *cache)
28952901
static bool can_resize(struct cache *cache, dm_cblock_t new_size)
28962902
{
28972903
if (from_cblock(new_size) > from_cblock(cache->cache_size)) {
2898-
if (cache->sized) {
2899-
DMERR("%s: unable to extend cache due to missing cache table reload",
2900-
cache_device_name(cache));
2901-
return false;
2902-
}
2904+
DMERR("%s: unable to extend cache due to missing cache table reload",
2905+
cache_device_name(cache));
2906+
return false;
29032907
}
29042908

29052909
/*
29062910
* We can't drop a dirty block when shrinking the cache.
29072911
*/
2908-
while (from_cblock(new_size) < from_cblock(cache->cache_size)) {
2909-
new_size = to_cblock(from_cblock(new_size) + 1);
2910-
if (is_dirty(cache, new_size)) {
2912+
if (cache->loaded_mappings) {
2913+
new_size = to_cblock(find_next_bit(cache->dirty_bitset,
2914+
from_cblock(cache->cache_size),
2915+
from_cblock(new_size)));
2916+
if (new_size != cache->cache_size) {
29112917
DMERR("%s: unable to shrink cache; cache block %llu is dirty",
29122918
cache_device_name(cache),
29132919
(unsigned long long) from_cblock(new_size));
@@ -2943,20 +2949,15 @@ static int cache_preresume(struct dm_target *ti)
29432949
/*
29442950
* Check to see if the cache has resized.
29452951
*/
2946-
if (!cache->sized) {
2947-
r = resize_cache_dev(cache, csize);
2948-
if (r)
2949-
return r;
2950-
2951-
cache->sized = true;
2952-
2953-
} else if (csize != cache->cache_size) {
2952+
if (!cache->sized || csize != cache->cache_size) {
29542953
if (!can_resize(cache, csize))
29552954
return -EINVAL;
29562955

29572956
r = resize_cache_dev(cache, csize);
29582957
if (r)
29592958
return r;
2959+
2960+
cache->sized = true;
29602961
}
29612962

29622963
if (!cache->loaded_mappings) {

drivers/md/dm-unstripe.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ static int unstripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
8585
}
8686
uc->physical_start = start;
8787

88-
uc->unstripe_offset = uc->unstripe * uc->chunk_size;
89-
uc->unstripe_width = (uc->stripes - 1) * uc->chunk_size;
88+
uc->unstripe_offset = (sector_t)uc->unstripe * uc->chunk_size;
89+
uc->unstripe_width = (sector_t)(uc->stripes - 1) * uc->chunk_size;
9090
uc->chunk_shift = is_power_of_2(uc->chunk_size) ? fls(uc->chunk_size) - 1 : 0;
9191

9292
tmp_len = ti->len;

drivers/md/dm-verity-target.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,9 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
356356
else if (verity_handle_err(v,
357357
DM_VERITY_BLOCK_TYPE_METADATA,
358358
hash_block)) {
359-
struct bio *bio =
360-
dm_bio_from_per_bio_data(io,
361-
v->ti->per_io_data_size);
359+
struct bio *bio;
360+
io->had_mismatch = true;
361+
bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
362362
dm_audit_log_bio(DM_MSG_PREFIX, "verify-metadata", bio,
363363
block, 0);
364364
r = -EIO;
@@ -482,6 +482,7 @@ static int verity_handle_data_hash_mismatch(struct dm_verity *v,
482482
return -EIO; /* Error correction failed; Just return error */
483483

484484
if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA, blkno)) {
485+
io->had_mismatch = true;
485486
dm_audit_log_bio(DM_MSG_PREFIX, "verify-data", bio, blkno, 0);
486487
return -EIO;
487488
}
@@ -606,6 +607,7 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
606607

607608
if (unlikely(status != BLK_STS_OK) &&
608609
unlikely(!(bio->bi_opf & REQ_RAHEAD)) &&
610+
!io->had_mismatch &&
609611
!verity_is_system_shutting_down()) {
610612
if (v->error_mode == DM_VERITY_MODE_PANIC) {
611613
panic("dm-verity device has I/O error");
@@ -779,6 +781,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
779781
io->orig_bi_end_io = bio->bi_end_io;
780782
io->block = bio->bi_iter.bi_sector >> (v->data_dev_block_bits - SECTOR_SHIFT);
781783
io->n_blocks = bio->bi_iter.bi_size >> v->data_dev_block_bits;
784+
io->had_mismatch = false;
782785

783786
bio->bi_end_io = verity_end_io;
784787
bio->bi_private = io;

drivers/md/dm-verity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct dm_verity_io {
9292
sector_t block;
9393
unsigned int n_blocks;
9494
bool in_bh;
95+
bool had_mismatch;
9596

9697
struct work_struct work;
9798
struct work_struct bh_work;

drivers/md/dm.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2290,8 +2290,10 @@ static struct mapped_device *alloc_dev(int minor)
22902290
* override accordingly.
22912291
*/
22922292
md->disk = blk_alloc_disk(NULL, md->numa_node_id);
2293-
if (IS_ERR(md->disk))
2293+
if (IS_ERR(md->disk)) {
2294+
md->disk = NULL;
22942295
goto bad;
2296+
}
22952297
md->queue = md->disk->queue;
22962298

22972299
init_waitqueue_head(&md->wait);

0 commit comments

Comments
 (0)