qemu-io: add cvtnum() error handling for zone commands

cvtnum() parses positive int64_t values and returns a negative errno on
failure. Print errors and return early when cvtnum() fails.

While we're at it, also reject nr_zones values greater or equal to 2^32
since they cannot be represented.

Reported-by: Peter Maydell <peter.maydell@linaro.org>
Cc: Sam Li <faithilikerun@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20240507180558.377233-1-stefanha@redhat.com>
Reviewed-by: Sam Li <faithilikerun@gmail.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2024-05-07 14:05:58 -04:00 committed by Kevin Wolf
parent e669e800fc
commit 365911b182

View File

@ -1739,12 +1739,26 @@ static int zone_report_f(BlockBackend *blk, int argc, char **argv)
{
int ret;
int64_t offset;
int64_t val;
unsigned int nr_zones;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
print_cvtnum_err(offset, argv[optind]);
return offset;
}
++optind;
nr_zones = cvtnum(argv[optind]);
val = cvtnum(argv[optind]);
if (val < 0) {
print_cvtnum_err(val, argv[optind]);
return val;
}
if (val > UINT_MAX) {
printf("Number of zones must be less than 2^32\n");
return -ERANGE;
}
nr_zones = val;
g_autofree BlockZoneDescriptor *zones = NULL;
zones = g_new(BlockZoneDescriptor, nr_zones);
@ -1780,8 +1794,16 @@ static int zone_open_f(BlockBackend *blk, int argc, char **argv)
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
print_cvtnum_err(offset, argv[optind]);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
print_cvtnum_err(len, argv[optind]);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_OPEN, offset, len);
if (ret < 0) {
printf("zone open failed: %s\n", strerror(-ret));
@ -1805,8 +1827,16 @@ static int zone_close_f(BlockBackend *blk, int argc, char **argv)
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
print_cvtnum_err(offset, argv[optind]);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
print_cvtnum_err(len, argv[optind]);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_CLOSE, offset, len);
if (ret < 0) {
printf("zone close failed: %s\n", strerror(-ret));
@ -1830,8 +1860,16 @@ static int zone_finish_f(BlockBackend *blk, int argc, char **argv)
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
print_cvtnum_err(offset, argv[optind]);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
print_cvtnum_err(len, argv[optind]);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_FINISH, offset, len);
if (ret < 0) {
printf("zone finish failed: %s\n", strerror(-ret));
@ -1855,8 +1893,16 @@ static int zone_reset_f(BlockBackend *blk, int argc, char **argv)
int64_t offset, len;
++optind;
offset = cvtnum(argv[optind]);
if (offset < 0) {
print_cvtnum_err(offset, argv[optind]);
return offset;
}
++optind;
len = cvtnum(argv[optind]);
if (len < 0) {
print_cvtnum_err(len, argv[optind]);
return len;
}
ret = blk_zone_mgmt(blk, BLK_ZO_RESET, offset, len);
if (ret < 0) {
printf("zone reset failed: %s\n", strerror(-ret));