libf2fs: don't allow mkfs / fsck on non power-of-2 zoned devices

commit 6afcf6493578e77528abe65ab8b12f3e1c16749f
category: bugfix
issue: #I6VAS0
CVE: NA

Signed-off-by: DongSenhao <dongsenhao2@huawei.com>
---------------------------------------

f2fs currently only work with zoned storage devices with a zone
size which is a power of 2 (PO2). So check if a non-power of 2
zoned device is found, and if so disallow its use. This prevents
users from incorrectly using these devices.

This is a non-issue today given today's kernel does not allow NPO2
zoned devices to exist as a block device. But NPO2 zoned devices do exist
so proactively put a stop-gap measure in place to prevent it from being
incorrectly used.

Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
Signed-off-by: Pankaj Raghav <p.raghav@samsung.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: dongsenhao <dongsenhao2@huawei.com>
This commit is contained in:
Luis Chamberlain 2022-04-13 14:29:40 +02:00 committed by dongsenhao
parent b0e910c695
commit e5e0cf64a2
3 changed files with 38 additions and 14 deletions

View File

@ -389,6 +389,7 @@ struct device_info {
u_int32_t nr_zones;
u_int32_t nr_rnd_zones;
size_t zone_blocks;
uint64_t zone_size;
size_t *zone_cap_blocks;
};

View File

@ -884,6 +884,11 @@ static int open_check_fs(char *path, int flag)
return open(path, O_RDONLY | flag);
}
static int is_power_of_2(unsigned long n)
{
return (n != 0 && ((n & (n - 1)) == 0));
}
int get_device_info(int i)
{
int32_t fd = 0;
@ -1045,6 +1050,13 @@ int get_device_info(int i)
return -1;
}
if (!is_power_of_2(dev->zone_size)) {
MSG(0, "\tError: zoned: illegal zone size %lu (not a power of 2)\n",
dev->zone_size);
free(stat_buf);
return -1;
}
/*
* Check zone configuration: for the first disk of a
* multi-device volume, conventional zones are needed.
@ -1057,8 +1069,9 @@ int get_device_info(int i)
MSG(0, "Info: Host-%s zoned block device:\n",
(dev->zoned_model == F2FS_ZONED_HA) ?
"aware" : "managed");
MSG(0, " %u zones, %u randomly writeable zones\n",
dev->nr_zones, dev->nr_rnd_zones);
MSG(0, " %u zones, %lu zone size(bytes), %u randomly writeable zones\n",
dev->nr_zones, dev->zone_size,
dev->nr_rnd_zones);
MSG(0, " %lu blocks per zone\n",
dev->zone_blocks);
}

View File

@ -148,40 +148,50 @@ int f2fs_get_zoned_model(int i)
return 0;
}
int f2fs_get_zone_blocks(int i)
uint32_t f2fs_get_zone_chunk_sectors(struct device_info *dev)
{
struct device_info *dev = c.devices + i;
uint64_t sectors;
uint32_t sectors;
char str[PATH_MAX];
FILE *file;
int res;
/* Get zone size */
dev->zone_blocks = 0;
res = get_sysfs_path(dev, "queue/chunk_sectors", str, sizeof(str));
if (res != 0) {
MSG(0, "\tError: Failed to get device sysfs attribute path\n");
return -1;
return 0;
}
file = fopen(str, "r");
if (!file)
return -1;
return 0;
memset(str, 0, sizeof(str));
res = fscanf(file, "%s", str);
fclose(file);
if (res != 1)
return -1;
return 0;
sectors = atol(str);
sectors = atoi(str);
return sectors;
}
int f2fs_get_zone_blocks(int i)
{
struct device_info *dev = c.devices + i;
uint64_t sectors;
/* Get zone size */
dev->zone_blocks = 0;
sectors = f2fs_get_zone_chunk_sectors(dev);
if (!sectors)
return -1;
dev->zone_blocks = sectors >> (F2FS_BLKSIZE_BITS - 9);
sectors = (sectors << 9) / c.sector_size;
dev->zone_size = sectors << SECTOR_SHIFT;
dev->zone_blocks = sectors >> (F2FS_BLKSIZE_BITS - SECTOR_SHIFT);
sectors = dev->zone_size / c.sector_size;
/*
* Total number of zones: there may