mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 15:29:16 +00:00
regmap: Fix possible double-free in regcache_rbtree_exit()
In regcache_rbtree_insert_to_block(), when 'present' realloc failed, the 'blk' which is supposed to assign to 'rbnode->block' will be freed, so 'rbnode->block' points a freed memory, in the error handling path of regcache_rbtree_init(), 'rbnode->block' will be freed again in regcache_rbtree_exit(), KASAN will report double-free as follows: BUG: KASAN: double-free or invalid-free in kfree+0xce/0x390 Call Trace: slab_free_freelist_hook+0x10d/0x240 kfree+0xce/0x390 regcache_rbtree_exit+0x15d/0x1a0 regcache_rbtree_init+0x224/0x2c0 regcache_init+0x88d/0x1310 __regmap_init+0x3151/0x4a80 __devm_regmap_init+0x7d/0x100 madera_spi_probe+0x10f/0x333 [madera_spi] spi_probe+0x183/0x210 really_probe+0x285/0xc30 To fix this, moving up the assignment of rbnode->block to immediately after the reallocation has succeeded so that the data structure stays valid even if the second reallocation fails. Reported-by: Hulk Robot <hulkci@huawei.com> Fixes: 3f4ff561bc88b ("regmap: rbtree: Make cache_present bitmap per node") Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Link: https://lore.kernel.org/r/20211012023735.1632786-1-yangyingliang@huawei.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
d287801c49
commit
55e6d80378
@ -281,14 +281,14 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
|
|||||||
if (!blk)
|
if (!blk)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rbnode->block = blk;
|
||||||
|
|
||||||
if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) {
|
if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) {
|
||||||
present = krealloc(rbnode->cache_present,
|
present = krealloc(rbnode->cache_present,
|
||||||
BITS_TO_LONGS(blklen) * sizeof(*present),
|
BITS_TO_LONGS(blklen) * sizeof(*present),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!present) {
|
if (!present)
|
||||||
kfree(blk);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
memset(present + BITS_TO_LONGS(rbnode->blklen), 0,
|
memset(present + BITS_TO_LONGS(rbnode->blklen), 0,
|
||||||
(BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen))
|
(BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen))
|
||||||
@ -305,7 +305,6 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* update the rbnode block, its size and the base register */
|
/* update the rbnode block, its size and the base register */
|
||||||
rbnode->block = blk;
|
|
||||||
rbnode->blklen = blklen;
|
rbnode->blklen = blklen;
|
||||||
rbnode->base_reg = base_reg;
|
rbnode->base_reg = base_reg;
|
||||||
rbnode->cache_present = present;
|
rbnode->cache_present = present;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user