]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
block: fix zones_cond memory leak on zone revalidation error paths
authorJackie Liu <liuyun01@kylinos.cn>
Tue, 31 Mar 2026 11:12:16 +0000 (19:12 +0800)
committerJens Axboe <axboe@kernel.dk>
Tue, 31 Mar 2026 13:05:49 +0000 (07:05 -0600)
When blk_revalidate_disk_zones() fails after disk_revalidate_zone_resources()
has allocated args.zones_cond, the memory is leaked because no error path
frees it.

Fixes: 6e945ffb6555 ("block: use zone condition to determine conventional zones")
Suggested-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Jackie Liu <liuyun01@kylinos.cn>
Link: https://patch.msgid.link/20260331111216.24242-1-liu.yun@linux.dev
Signed-off-by: Jens Axboe <axboe@kernel.dk>
block/blk-zoned.c

index e1a23c8b676d55d663dc1502a28671c6c5503875..bfd9733ebd3196471e15b076b2153f184df4e965 100644 (file)
@@ -2016,6 +2016,7 @@ static int disk_revalidate_zone_resources(struct gendisk *disk,
 {
        struct queue_limits *lim = &disk->queue->limits;
        unsigned int pool_size;
+       int ret = 0;
 
        args->disk = disk;
        args->nr_zones =
@@ -2038,10 +2039,13 @@ static int disk_revalidate_zone_resources(struct gendisk *disk,
                pool_size =
                        min(BLK_ZONE_WPLUG_DEFAULT_POOL_SIZE, args->nr_zones);
 
-       if (!disk->zone_wplugs_hash)
-               return disk_alloc_zone_resources(disk, pool_size);
+       if (!disk->zone_wplugs_hash) {
+               ret = disk_alloc_zone_resources(disk, pool_size);
+               if (ret)
+                       kfree(args->zones_cond);
+       }
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -2073,6 +2077,7 @@ static int disk_update_zone_resources(struct gendisk *disk,
        disk->zone_capacity = args->zone_capacity;
        disk->last_zone_capacity = args->last_zone_capacity;
        disk_set_zones_cond_array(disk, args->zones_cond);
+       args->zones_cond = NULL;
 
        /*
         * Some devices can advertise zone resource limits that are larger than
@@ -2353,21 +2358,30 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
        }
        memalloc_noio_restore(noio_flag);
 
+       if (ret <= 0)
+               goto free_resources;
+
        /*
         * If zones where reported, make sure that the entire disk capacity
         * has been checked.
         */
-       if (ret > 0 && args.sector != capacity) {
+       if (args.sector != capacity) {
                pr_warn("%s: Missing zones from sector %llu\n",
                        disk->disk_name, args.sector);
                ret = -ENODEV;
+               goto free_resources;
        }
 
-       if (ret > 0)
-               return disk_update_zone_resources(disk, &args);
+       ret = disk_update_zone_resources(disk, &args);
+       if (ret)
+               goto free_resources;
+
+       return 0;
 
+free_resources:
        pr_warn("%s: failed to revalidate zones\n", disk->disk_name);
 
+       kfree(args.zones_cond);
        memflags = blk_mq_freeze_queue(q);
        disk_free_zone_resources(disk);
        blk_mq_unfreeze_queue(q, memflags);