From: Jan Kara jack@suse.cz
mainline inclusion from mainline-v6.7-rc1 commit b3856da7906257a80a764d3dfc6b25e876a4403c category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8KPBR CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h...
-------------------------------------------
Coverity has noticed that the printing of error message in register_cache() uses already freed bdev_handle to get to bdev. In fact the problem has been there even before commit "bcache: Convert to bdev_open_by_path()" just a bit more subtle one - cache object itself could have been freed by the time we looked at ca->bdev and we don't hold any reference to bdev either so even that could in principle go away (due to device unplug or similar). Fix all these problems by printing the error message before closing the bdev.
Fixes: dc893f51d24a ("bcache: Convert to bdev_open_by_path()") Signed-off-by: Jan Kara jack@suse.cz Link: https://lore.kernel.org/r/20231004093757.11560-1-jack@suse.cz Asked-by: Coly Li colyli@suse.de Signed-off-by: Christian Brauner brauner@kernel.org Signed-off-by: Li Lingfeng lilingfeng3@huawei.com --- drivers/md/bcache/super.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index c11ac86be72b..a30c8d4f2ac8 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -2354,6 +2354,13 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
ret = cache_alloc(ca); if (ret != 0) { + if (ret == -ENOMEM) + err = "cache_alloc(): -ENOMEM"; + else if (ret == -EPERM) + err = "cache_alloc(): cache device is too small"; + else + err = "cache_alloc(): unknown error"; + pr_notice("error %pg: %s\n", bdev_handle->bdev, err); /* * If we failed here, it means ca->kobj is not initialized yet, * kobject_put() won't be called and there is no chance to @@ -2361,17 +2368,12 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk, * we explicitly call bdev_release() here. */ bdev_release(bdev_handle); - if (ret == -ENOMEM) - err = "cache_alloc(): -ENOMEM"; - else if (ret == -EPERM) - err = "cache_alloc(): cache device is too small"; - else - err = "cache_alloc(): unknown error"; - goto err; + return ret; }
if (kobject_add(&ca->kobj, bdev_kobj(bdev_handle->bdev), "bcache")) { - err = "error calling kobject_add"; + pr_notice("error %pg: error calling kobject_add\n", + bdev_handle->bdev); ret = -ENOMEM; goto out; } @@ -2389,11 +2391,6 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
out: kobject_put(&ca->kobj); - -err: - if (err) - pr_notice("error %pg: %s\n", ca->bdev_handle->bdev, err); - return ret; }