Thank you for your contribution! Sashiko AI review found 1 potential issue(s) 
to consider:
- [High] dm: double free and kobject re-init on dm_setup_md_queue() retry
--

commit ade936ffb3a2324034883b5668b49bcb6d404c6d
Author: Wentao Liang <[email protected]>

dm: release the sysfs kobject when its initialization fails

This commit calls dm_sysfs_exit() on the error path of dm_setup_md_queue()
when dm_sysfs_init() fails, so that the initialized kobject is released and
waited on before unwinding the disk and holder links.

> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
> index 1881d86111fb2..08b87fd6f955c 100644
> --- a/drivers/md/dm.c
> +++ b/drivers/md/dm.c
> @@ -2647,8 +2647,10 @@ int dm_setup_md_queue(struct mapped_device *md, struct 
> dm_table *t)
>       mutex_unlock(&md->table_devices_lock);
>  
>       r = dm_sysfs_init(md);
> -     if (r)
> +     if (r) {
> +             dm_sysfs_exit(md);
>               goto lock_out_undo_holders;
> +     }

[Severity: High]
What happens if dm_setup_md_queue() is retried on the same mapped_device
after dm_sysfs_init() fails and dm_sysfs_exit() runs?

In dm_sysfs_init(), kobject_init_and_add() calls kobject_init(), which sets
kobj->state_initialized = 1, and kobject_set_name_vargs(), which sets
kobj->name (heap-allocated via kstrdup() when dm-mod is built as a module,
since the string literal "dm" is in module rodata rather than core kernel
rodata).

If adding the kobject to sysfs fails, dm_sysfs_exit() calls kobject_put() and
waits for completion:

lib/kobject.c:kobject_cleanup() {
        ...
        /* free name if we allocated it */
        if (name) {
                pr_debug("'%s': free name\n", name);
                kfree_const(name);
        }
}

kobject_cleanup() frees kobj->name via kfree_const(), but neither
kobject_cleanup() nor dm_sysfs_exit() clears kobj->name or
kobj->state_initialized.

Because dm_setup_md_queue() returns before setting md->type, md remains alive
with md->type == DM_TYPE_NONE:

drivers/md/dm-ioctl.c:table_load() {
        ...
        if (dm_get_md_type(md) == DM_TYPE_NONE) {
                /* setup md->queue to reflect md's type (may block) */
                r = dm_setup_md_queue(md, t);
                if (r) {
                        DMERR("unable to set up device queue for new table.");
                        goto err_unlock_md_type;
                }
        }
}

If userspace retries DM_TABLE_LOAD on the same mapped_device, table_load()
calls dm_setup_md_queue() -> dm_sysfs_init() -> kobject_init_and_add() on the
same embedded md->kobj_holder.kobj.

Won't kobject_init() complain that kobj->state_initialized is already 1 and
dump a stack trace, followed by kobject_set_name_vargs() calling
kfree_const(kobj->name) on the dangling pointer that was already freed during
the first dm_sysfs_exit()?

-- 
Sashiko AI review ยท 
https://sashiko.dev/#/patchset/[email protected]?part=1

Reply via email to