RESEND - Update filename string sizes in block layer
v2 cover RESEND - Update filename string sizes in block layer
[ Note, my prior email to qemu-devel bounced, because I mistyped an address.
Resending ]
The block layer uses a mixture of 'PATH_MAX' and '1024' string sizes for filenames (and backing filenames).
This series consolidates all that usage to 'PATH_MAX'. Since most platforms (especially the most common platforms for QEMU) have a PATH_MAX larger than 1024 bytes, this series also changes stack allocations of PATH_MAX to be dynamically allocated.
Note: checkpatch.pl complains about an extra space in a printf in
patches 1 & 2. The lines complained about are in the diff context and not the actual changes, so I did not fix them up to satisfy checkpatch.
Changes from v2:
- Change stack allocations to dybnamic (Thanks Kevin)
- Update qcow/qcow2 ti perform safety checks for platforms that have a PATH_MAX < 1024 (thanks John, Kevin).
Jeff Cody (6):
block: vmdk - make ret variable usage clear
block: vmdk - move string allocations from stack to the heap
block: qapi - move string allocation from stack to the heap
block: move string allocation from stack to the heap
block: mirror - change string allocation to 2-bytes
block: update string sizes for filename,backing_file,exact_filename
block.c | 11 ++++--- block/mirror.c | 3 +- block/qapi.c | 8 +++-- block/qcow.c | 2 +- block/qcow2.c | 3 +- block/vmdk.c | 76 ++++++++++++++++++++++++++++------------------- block/vvfat.c | 4 +-- include/block/block_int.h | 8 ++--- qemu-img.c | 4 +-- 9 files changed, 70 insertions(+), 49 deletions(-)
Signature · 1 line
1.9.3
PATCH v2 2/6 block: vmdk - move string allocations from stack to the heap
Functions 'vmdk_parse_extents' and 'vmdk_create' allocate several PATH_MAX sized arrays on the stack. Make these dynamically allocated.
--- block/vmdk.c | 64 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 26 deletions(-)
block/vmdk.c +38 -26
@@ -784,7 +784,7 @@ static int vmdk_open_sparse(BlockDriverState *bs,static int vmdk_parse_extents (const char *desc,BlockDriverState *bs,const char *desc_file_path,Error **errp) { -int ret; +int ret =0 ;int matches;char access[11 ];char type[11 ];
@@ -792,12 +792,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,const char *p = desc;int64_t sectors =0 ;int64_t flat_offset; -char extent_path[PATH_MAX ]; +char *extent_path =g_malloc0 (PATH_MAX );BlockDriverState *extent_file;BDRVVmdkState *s = bs->opaque;VmdkExtent *extent; -while (*p) {/* parse extent line in one of below formats: *
@@ -814,18 +813,21 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, }else if (!strcmp (type,"FLAT" )) {if (matches !=5 || flat_offset <0 ) {error_setg (errp,"Invalid extent lines: \n%s" , p); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } }else if (!strcmp (type,"VMFS" )) {if (matches ==4 ) { flat_offset =0 ; }else {error_setg (errp,"Invalid extent lines:\n%s" , p); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } }else if (matches !=4 ) {error_setg (errp,"Invalid extent lines:\n%s" , p); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } if (sectors <= 0 ||
@@ -840,7 +842,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, {error_setg (errp,"Cannot use relative extent paths with VMDK " "descriptor file '%s'" , bs->file->filename); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } path_combine(extent_path, sizeof(extent_path),
@@ -849,7 +852,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, ret =bdrv_open (&extent_file, extent_path,NULL ,NULL , bs->open_flags |BDRV_O_PROTOCOL ,NULL , errp);if (ret) { -return ret; + goto exit; }/* save to extents array */
@@ -860,7 +863,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, 0, 0, 0, 0, 0, &extent, errp);if (ret <0 ) {bdrv_unref (extent_file); -return ret; + goto exit; } extent->flat_start_offset = flat_offset <<9 ; }else if (!strcmp (type,"SPARSE" ) || !strcmp (type,"VMFSSPARSE" )) {
@@ -874,13 +877,14 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,g_free (buf);if (ret) {bdrv_unref (extent_file); -return ret; + goto exit; } extent = &s->extents[s->num_extents -1 ]; }else {error_setg (errp,"Unsupported extent type '%s'" , type);bdrv_unref (extent_file); -return -ENOTSUP ; + ret = -ENOTSUP ; + goto exit; } extent->type =g_strdup (type); next_line:
@@ -893,7 +897,9 @@ next_line: p++; } } -return 0 ; +exit: +g_free (extent_path); +return ret; } static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,
@@ -1797,10 +1803,15 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)int ret =0 ;bool flat, split, compress;GString *ext_desc_lines; -char path[PATH_MAX ], prefix[PATH_MAX ], postfix[PATH_MAX ]; +char *path =g_malloc0 (PATH_MAX ); +char *prefix =g_malloc0 (PATH_MAX ); +char *postfix =g_malloc0 (PATH_MAX ); +char *desc_line =g_malloc0 (BUF_SIZE ); +char *ext_filename =g_malloc0 (PATH_MAX ); +char *desc_filename =g_malloc0 (PATH_MAX );const int64_t split_size =0x80000000 ;/* VMDK has constant split size */ const char *desc_extent_line; -char parent_desc_line[BUF_SIZE ] ="" ; +char *parent_desc_line =g_malloc0 (BUF_SIZE );uint32_t parent_cid =0xffffffff ;uint32_t number_heads =16 ;bool zeroed_grain = false;
@@ -1916,33 +1927,27 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) } parent_cid =vmdk_read_cid (bs,0 );bdrv_unref (bs); -snprintf (parent_desc_line,sizeof (parent_desc_line), +snprintf (parent_desc_line,BUF_SIZE ,"parentFileNameHint=\"%s\"" , backing_file); }/* Create extents */ filesize = total_size;while (filesize >0 ) { -char desc_line[BUF_SIZE ]; -char ext_filename[PATH_MAX ]; -char desc_filename[PATH_MAX ];int64_t size = filesize;if (split && size > split_size) { size = split_size; }if (split) { -snprintf (desc_filename,sizeof (desc_filename),"%s-%c%03d%s" , +snprintf (desc_filename,PATH_MAX ,"%s-%c%03d%s" , prefix, flat ?'f' :'s' , ++idx, postfix); }else if (flat) { -snprintf (desc_filename,sizeof (desc_filename),"%s-flat%s" , - prefix, postfix); +snprintf (desc_filename,PATH_MAX ,"%s-flat%s" , prefix, postfix); }else { -snprintf (desc_filename,sizeof (desc_filename),"%s%s" , - prefix, postfix); +snprintf (desc_filename,PATH_MAX ,"%s%s" , prefix, postfix); } -snprintf (ext_filename,sizeof (ext_filename),"%s%s" , - path, desc_filename); +snprintf (ext_filename,PATH_MAX ,"%s%s" , path, desc_filename);if (vmdk_create_extent (ext_filename, size, flat, compress, zeroed_grain, opts, errp)) {
@@ -1952,7 +1957,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) filesize -= size;/* Format description line */ -snprintf (desc_line,sizeof (desc_line), +snprintf (desc_line,BUF_SIZE , desc_extent_line, size /BDRV_SECTOR_SIZE , desc_filename);g_string_append (ext_desc_lines, desc_line); }
@@ -2007,6 +2012,13 @@ exit:g_free (backing_file);g_free (fmt);g_free (desc); +g_free (path); +g_free (prefix); +g_free (postfix); +g_free (desc_line); +g_free (ext_filename); +g_free (desc_filename); +g_free (parent_desc_line);g_string_free (ext_desc_lines, true);return ret; }
Signature · 1 line
1.9.3
PATCH v2 3/6 block: qapi - move string allocation from stack to the heap
In reply to Jeff CodyRather than declaring 'backing_filename2' on the stack in bdrv_quiery_image_info(), dynamically allocate it on the heap.
--- block/qapi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
block/qapi.c +5 -3
@@ -175,7 +175,7 @@ void bdrv_query_image_info(BlockDriverState *bs, {int64_t size;const char *backing_filename; -char backing_filename2[1024 ]; +char *backing_filename2 =NULL ;BlockDriverInfo bdi;int ret;Error *err =NULL ;
@@ -211,13 +211,14 @@ void bdrv_query_image_info(BlockDriverState *bs, backing_filename = bs->backing_file;if (backing_filename[0 ] !='\0' ) { + backing_filename2 =g_malloc0 (1024 ); info->backing_filename =g_strdup (backing_filename); info->has_backing_filename = true; -bdrv_get_full_backing_filename (bs, backing_filename2, -sizeof (backing_filename2), &err); +bdrv_get_full_backing_filename (bs, backing_filename2,1024 , &err);if (err) {error_propagate (errp, err);qapi_free_ImageInfo (info); +g_free (backing_filename2);return ; }
@@ -231,6 +232,7 @@ void bdrv_query_image_info(BlockDriverState *bs, info->backing_filename_format =g_strdup (bs->backing_format); info->has_backing_filename_format = true; } +g_free (backing_filename2); } ret =bdrv_query_snapshot_info_list (bs, &info->snapshots, &err);
Signature · 1 line
1.9.3
PATCH v2 4/6 block: move string allocation from stack to the heap
In reply to Jeff CodyRather than allocate PATH_MAX bytes on the stack, use g_strndup() to dynamically allocate the string, and add an exit label for cleanup.
--- block.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
block.c +7 -4
@@ -2207,7 +2207,7 @@ int bdrv_commit(BlockDriverState *bs)int n, ro, open_flags;int ret =0 ;uint8_t *buf =NULL ; -char filename[PATH_MAX ]; +char *filename =NULL ;if (!drv)return -ENOMEDIUM ;
@@ -2222,13 +2222,14 @@ int bdrv_commit(BlockDriverState *bs) } ro = bs->backing_hd->read_only; -/* Use pstrcpy (not strncpy): filename must be NUL-terminated. */ -pstrcpy (filename,sizeof (filename), bs->backing_hd->filename); +/* filename must be NUL-terminated. */ + filename =g_strndup (bs->backing_hd->filename,PATH_MAX -1 ); open_flags = bs->backing_hd->open_flags;if (ro) {if (bdrv_reopen (bs->backing_hd, open_flags |BDRV_O_RDWR ,NULL )) { -return -EACCES ; + ret = -EACCES ; + goto exit; } }
@@ -2307,6 +2308,8 @@ ro_cleanup:bdrv_reopen (bs->backing_hd, open_flags & ~BDRV_O_RDWR ,NULL ); } +exit: +g_free (filename);return ret; }
Signature · 1 line
1.9.3
PATCH v2 5/6 block: mirror - change string allocation to 2-bytes
In reply to Jeff CodyThe backing_filename string in mirror_run() is only used to check for a NULL string, so we don't need to allocate 1024 bytes (or, later, PATH_MAX bytes), when we only need to copy the first 2 characters.
We technically only need 1 byte, as we are just checking for NULL, but since backing_filename[] is populated by bdrv_get_backing_filename(), a string size of 1 will always only return '\0';
--- block/mirror.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
block/mirror.c +2 -1
@@ -378,7 +378,8 @@ static void coroutine_fn mirror_run(void *opaque)int64_t sector_num, end, sectors_per_chunk, length;uint64_t last_pause_ns;BlockDriverInfo bdi; -char backing_filename[1024 ]; +char backing_filename[2 ];/* we only need 2 characters because we are only +checking for a NULL string */ int ret =0 ;int n;
Signature · 1 line
1.9.3
PATCH v2 1/6 block: vmdk - make ret variable usage clear
In reply to Jeff CodyKeep the variable 'ret' something that is returned by the function it is defined in. For the return value of 'sscanf', use a more meaningful variable name.
--- block/vmdk.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
block/vmdk.c +8 -6
@@ -785,6 +785,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, const char *desc_file_path, Error **errp) { int ret; +int matches;char access[11 ];char type[11 ];char fname[512 ];
@@ -796,6 +797,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,BDRVVmdkState *s = bs->opaque;VmdkExtent *extent; +while (*p) {/* parse extent line in one of below formats: *
@@ -805,23 +807,23 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,* RW [size in sectors] VMFSSPARSE "file-name.vmdk" */ flat_offset =-1 ; - ret =sscanf (p,"%10s %" SCNd64" %10s \"%511[^\n\r\"]\" %" SCNd64, - access, §ors, type, fname, &flat_offset); -if (ret <4 ||strcmp (access,"RW" )) { + matches =sscanf (p,"%10s %" SCNd64" %10s \"%511[^\n\r\"]\" %" SCNd64, + access, §ors, type, fname, &flat_offset); +if (matches <4 ||strcmp (access,"RW" )) { goto next_line; }else if (!strcmp (type,"FLAT" )) { -if (ret !=5 || flat_offset <0 ) { +if (matches !=5 || flat_offset <0 ) {error_setg (errp,"Invalid extent lines: \n%s" , p);return -EINVAL ; } }else if (!strcmp (type,"VMFS" )) { -if (ret ==4 ) { +if (matches ==4 ) { flat_offset =0 ; }else {error_setg (errp,"Invalid extent lines:\n%s" , p);return -EINVAL ; } - }else if (ret !=4 ) { + }else if (matches !=4 ) {error_setg (errp,"Invalid extent lines:\n%s" , p);return -EINVAL ; }
Signature · 1 line
1.9.3
PATCH v2 6/6 block: update string sizes for filename, backing_file, exact_filename
In reply to Jeff CodyThe string field entries 'filename', 'backing_file', and 'exact_filename' in the BlockDriverState struct are defined as 1024 bytes.
However, many places that use these values accept a maximum of PATH_MAX bytes, so we have a mixture of 1024 byte and PATH_MAX byte allocations. This patch makes the BlockDriverStruct field string sizes match usage.
This patch also does a few fixes related to the size that needs to happen now:
* the block qapi driver is updated to use PATH_MAX bytes
* the qcow and qcow2 drivers have an additional safety check
* the block vvfat driver is updated to use PATH_MAX bytes for the size of backing_file, for systems where PATH_MAX is < 1024 bytes.
* qemu-img uses PATH_MAX rather than 1024. These instances were not changed to be dynamically allocated, however, as the extra temporary 3K in stack usage for qemu-img does not seem worrisome.
--- block/qapi.c | 4 ++-- block/qcow.c | 2 +- block/qcow2.c | 3 ++- block/vvfat.c | 4 ++-- include/block/block_int.h | 8 ++++---- qemu-img.c | 4 ++-- 6 files changed, 13 insertions(+), 12 deletions(-)
block/qapi.c +2 -2
@@ -211,10 +211,10 @@ void bdrv_query_image_info(BlockDriverState *bs, backing_filename = bs->backing_file;if (backing_filename[0 ] !='\0' ) { - backing_filename2 =g_malloc0 (1024 ); + backing_filename2 =g_malloc0 (PATH_MAX ); info->backing_filename =g_strdup (backing_filename); info->has_backing_filename = true; -bdrv_get_full_backing_filename (bs, backing_filename2,1024 , &err); +bdrv_get_full_backing_filename (bs, backing_filename2,PATH_MAX , &err);if (err) {error_propagate (errp, err);qapi_free_ImageInfo (info);
block/qcow.c +1 -1
@@ -215,7 +215,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,/* read the backing file name */ if (header.backing_file_offset !=0 ) { len = header.backing_file_size; -if (len >1023 ) { +if (len >1023 || len >sizeof (bs->backing_file)) {error_setg (errp,"Backing file name too long" ); ret = -EINVAL ; goto fail;
block/qcow2.c +2 -1
@@ -868,7 +868,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,/* read the backing file name */ if (header.backing_file_offset !=0 ) { len = header.backing_file_size; -if (len >MIN (1023 , s->cluster_size - header.backing_file_offset)) { +if (len >MIN (1023 , s->cluster_size - header.backing_file_offset) || + len >sizeof (bs->backing_file)) {error_setg (errp,"Backing file name too long" ); ret = -EINVAL ; goto fail;
block/vvfat.c +2 -2
@@ -2909,8 +2909,8 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)array_init (&(s->commits),sizeof (commit_t)); - s->qcow_filename =g_malloc (1024 ); - ret =get_tmp_filename (s->qcow_filename,1024 ); + s->qcow_filename =g_malloc (PATH_MAX ); + ret =get_tmp_filename (s->qcow_filename,PATH_MAX );if (ret <0 ) {error_setg_errno (errp, -ret,"can't create temporary file" ); goto err;
include/block/block_int.h +4 -4
@@ -339,13 +339,13 @@ struct BlockDriverState {* regarding this BDS's context */ QLIST_HEAD(, BdrvAioNotifier) aio_notifiers; -char filename[1024 ]; -char backing_file[1024 ];/* if non zero, the image is a diff of -this file image */ +char filename[PATH_MAX ]; +char backing_file[PATH_MAX ];/* if non zero, the image is a diff of +this file image */ char backing_format[16 ];/* if non-zero and backing_file exists */ QDict *full_open_options; -char exact_filename[1024 ]; +char exact_filename[PATH_MAX ];BlockDriverState *backing_hd;BlockDriverState *file;
qemu-img.c +2 -2
@@ -2556,7 +2556,7 @@ static int img_rebase(int argc, char **argv)/* For safe rebasing we need to compare old and new backing file */ if (!unsafe) { -char backing_name[1024 ]; +char backing_name[PATH_MAX ]; blk_old_backing =blk_new_with_bs ("old_backing" , &error_abort); bs_old_backing =blk_bs (blk_old_backing);
@@ -2614,7 +2614,7 @@ static int img_rebase(int argc, char **argv) } old_backing_num_sectors =bdrv_nb_sectors (bs_old_backing);if (old_backing_num_sectors <0 ) { -char backing_name[1024 ]; +char backing_name[PATH_MAX ];bdrv_get_backing_filename (bs, backing_name,sizeof (backing_name)); error_report("Could not get size of '%s': %s",
Signature · 1 line
1.9.3
Re: [Qemu-devel] [PATCH v2 1/6] block: vmdk - make ret variable usage clear
In reply to Jeff CodyQuoted 22 lines · Jeff Cody
Keep the variable 'ret' something that is returned by the function it is defined in. For the return value of 'sscanf', use a more meaningful variable name.
Signed-off-by Jeff Cody <[email protected]>--- block/vmdk.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)block/vmdk.c +1
-0@@ -785,6 +785,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, const char *desc_file_path, Error **errp) { int ret; +int matches;char access[11 ];char type[11 ];char fname[512 ];
block/vmdk.c static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, · line 800
Quoted 4 lines
block/vmdk.c +1
-0@@ -796,6 +797,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,BDRVVmdkState *s = bs->opaque;VmdkExtent *extent; +
Stray newline.
Quoted 24 lines
block/vmdk.c +5
-5while (*p) {/* parse extent line in one of below formats: * @@ -805,23 +807,23 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,* RW [size in sectors] VMFSSPARSE "file-name.vmdk" */ flat_offset =-1 ; - ret =sscanf (p,"%10s %" SCNd64" %10s \"%511[^\n\r\"]\" %" SCNd64, - access, §ors, type, fname, &flat_offset); -if (ret <4 ||strcmp (access,"RW" )) { + matches =sscanf (p,"%10s %" SCNd64" %10s \"%511[^\n\r\"]\" %" SCNd64, + access, §ors, type, fname, &flat_offset); +if (matches <4 ||strcmp (access,"RW" )) { goto next_line; }else if (!strcmp (type,"FLAT" )) { -if (ret !=5 || flat_offset <0 ) { +if (matches !=5 || flat_offset <0 ) {error_setg (errp,"Invalid extent lines: \n%s" , p);return -EINVAL ; } }else if (!strcmp (type,"VMFS" )) { -if (ret ==4 ) { +if (matches ==4 ) {
block/vmdk.c static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, · line 829
Quoted 10 lines
block/vmdk.c +1
-1flat_offset =0 ; }else {error_setg (errp,"Invalid extent lines:\n%s" , p);return -EINVAL ; } - }else if (ret !=4 ) { + }else if (matches !=4 ) {error_setg (errp,"Invalid extent lines:\n%s" , p);return -EINVAL ; }
Re: [Qemu-devel] [PATCH v2 2/6] block: vmdk - move string allocations from stack to the heap
In reply to Jeff CodyQuoted 22 lines · Jeff Cody
Functions '
vmdk_parse_extents' and 'vmdk_create' allocate severalPATH_MAXsized arrays on the stack. Make these dynamically allocated.Signed-off-by Jeff Cody <[email protected]>--- block/vmdk.c | 64 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 26 deletions(-)block/vmdk.c +1
-1@@ -784,7 +784,7 @@ static int vmdk_open_sparse(BlockDriverState *bs,static int vmdk_parse_extents (const char *desc,BlockDriverState *bs,const char *desc_file_path,Error **errp) { -int ret; +int ret =0 ;int matches;char access[11 ];char type[11 ];
block/vmdk.c static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, · line 800
Quoted 10 lines
block/vmdk.c +1
-2@@ -792,12 +792,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,const char *p = desc;int64_t sectors =0 ;int64_t flat_offset; -char extent_path[PATH_MAX ]; +char *extent_path =g_malloc0 (PATH_MAX );BlockDriverState *extent_file;BDRVVmdkState *s = bs->opaque;VmdkExtent *extent; -
The stray newline you added is now gone!
Quoted 155 lines
block/vmdk.c +29
-23while (*p) {/* parse extent line in one of below formats: * @@ -814,18 +813,21 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, }else if (!strcmp (type,"FLAT" )) {if (matches !=5 || flat_offset <0 ) {error_setg (errp,"Invalid extent lines: \n%s" , p); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } }else if (!strcmp (type,"VMFS" )) {if (matches ==4 ) { flat_offset =0 ; }else {error_setg (errp,"Invalid extent lines:\n%s" , p); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } }else if (matches !=4 ) {error_setg (errp,"Invalid extent lines:\n%s" , p); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } if (sectors <= 0 ||@@ -840,7 +842,8 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, {error_setg (errp,"Cannot use relative extent paths with VMDK " "descriptor file '%s'" , bs->file->filename); -return -EINVAL ; + ret = -EINVAL ; + goto exit; } path_combine(extent_path, sizeof(extent_path),@@ -849,7 +852,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, ret =bdrv_open (&extent_file, extent_path,NULL ,NULL , bs->open_flags |BDRV_O_PROTOCOL ,NULL , errp);if (ret) { -return ret; + goto exit; }/* save to extents array */ @@ -860,7 +863,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, 0, 0, 0, 0, 0, &extent, errp);if (ret <0 ) {bdrv_unref (extent_file); -return ret; + goto exit; } extent->flat_start_offset = flat_offset <<9 ; }else if (!strcmp (type,"SPARSE" ) || !strcmp (type,"VMFSSPARSE" )) {@@ -874,13 +877,14 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,g_free (buf);if (ret) {bdrv_unref (extent_file); -return ret; + goto exit; } extent = &s->extents[s->num_extents -1 ]; }else {error_setg (errp,"Unsupported extent type '%s'" , type);bdrv_unref (extent_file); -return -ENOTSUP ; + ret = -ENOTSUP ; + goto exit; } extent->type =g_strdup (type); next_line:@@ -893,7 +897,9 @@ next_line: p++; } } -return 0 ; +exit: +g_free (extent_path); +return ret; } static int vmdk_open_desc_file(BlockDriverState *bs, int flags, char *buf,@@ -1797,10 +1803,15 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp)int ret =0 ;bool flat, split, compress;GString *ext_desc_lines; -char path[PATH_MAX ], prefix[PATH_MAX ], postfix[PATH_MAX ]; +char *path =g_malloc0 (PATH_MAX ); +char *prefix =g_malloc0 (PATH_MAX ); +char *postfix =g_malloc0 (PATH_MAX ); +char *desc_line =g_malloc0 (BUF_SIZE ); +char *ext_filename =g_malloc0 (PATH_MAX ); +char *desc_filename =g_malloc0 (PATH_MAX );const int64_t split_size =0x80000000 ;/* VMDK has constant split size */ const char *desc_extent_line; -char parent_desc_line[BUF_SIZE ] ="" ; +char *parent_desc_line =g_malloc0 (BUF_SIZE );uint32_t parent_cid =0xffffffff ;uint32_t number_heads =16 ;bool zeroed_grain = false;@@ -1916,33 +1927,27 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) } parent_cid =vmdk_read_cid (bs,0 );bdrv_unref (bs); -snprintf (parent_desc_line,sizeof (parent_desc_line), +snprintf (parent_desc_line,BUF_SIZE ,"parentFileNameHint=\"%s\"" , backing_file); }/* Create extents */ filesize = total_size;while (filesize >0 ) { -char desc_line[BUF_SIZE ]; -char ext_filename[PATH_MAX ]; -char desc_filename[PATH_MAX ];int64_t size = filesize;if (split && size > split_size) { size = split_size; }if (split) { -snprintf (desc_filename,sizeof (desc_filename),"%s-%c%03d%s" , +snprintf (desc_filename,PATH_MAX ,"%s-%c%03d%s" , prefix, flat ?'f' :'s' , ++idx, postfix); }else if (flat) { -snprintf (desc_filename,sizeof (desc_filename),"%s-flat%s" , - prefix, postfix); +snprintf (desc_filename,PATH_MAX ,"%s-flat%s" , prefix, postfix); }else { -snprintf (desc_filename,sizeof (desc_filename),"%s%s" , - prefix, postfix); +snprintf (desc_filename,PATH_MAX ,"%s%s" , prefix, postfix); } -snprintf (ext_filename,sizeof (ext_filename),"%s%s" , - path, desc_filename); +snprintf (ext_filename,PATH_MAX ,"%s%s" , path, desc_filename);if (vmdk_create_extent (ext_filename, size, flat, compress, zeroed_grain, opts, errp)) {@@ -1952,7 +1957,7 @@ static int vmdk_create(const char *filename, QemuOpts *opts, Error **errp) filesize -= size;/* Format description line */ -snprintf (desc_line,sizeof (desc_line), +snprintf (desc_line,BUF_SIZE , desc_extent_line, size /BDRV_SECTOR_SIZE , desc_filename);g_string_append (ext_desc_lines, desc_line); }@@ -2007,6 +2012,13 @@ exit:g_free (backing_file);g_free (fmt);g_free (desc);
block/vmdk.c exit: · line 2024
Quoted 10 lines
block/vmdk.c +7
-0+g_free (path); +g_free (prefix); +g_free (postfix); +g_free (desc_line); +g_free (ext_filename); +g_free (desc_filename); +g_free (parent_desc_line);g_string_free (ext_desc_lines, true);return ret; }
Re: [Qemu-devel] [PATCH v2 3/6] block: qapi - move string allocation from stack to the heap
In reply to Jeff CodyQuoted 40 lines · Jeff Cody
Rather than declaring '
backing_filename2' on the stack inbdrv_quiery_image_info(), dynamically allocate it on the heap.Signed-off-by Jeff Cody <[email protected]>--- block/qapi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)block/qapi.c +4
-3@@ -175,7 +175,7 @@ void bdrv_query_image_info(BlockDriverState *bs, {int64_t size;const char *backing_filename; -char backing_filename2[1024 ]; +char *backing_filename2 =NULL ;BlockDriverInfo bdi;int ret;Error *err =NULL ;@@ -211,13 +211,14 @@ void bdrv_query_image_info(BlockDriverState *bs, backing_filename = bs->backing_file;if (backing_filename[0 ] !='\0' ) { + backing_filename2 =g_malloc0 (1024 ); info->backing_filename =g_strdup (backing_filename); info->has_backing_filename = true; -bdrv_get_full_backing_filename (bs, backing_filename2, -sizeof (backing_filename2), &err); +bdrv_get_full_backing_filename (bs, backing_filename2,1024 , &err);if (err) {error_propagate (errp, err);qapi_free_ImageInfo (info); +g_free (backing_filename2);return ; }
block/qapi.c void bdrv_query_image_info(BlockDriverState *bs, · line 238
Quoted 7 lines
block/qapi.c +1
-0@@ -231,6 +232,7 @@ void bdrv_query_image_info(BlockDriverState *bs, info->backing_filename_format =g_strdup (bs->backing_format); info->has_backing_filename_format = true; } +g_free (backing_filename2); } ret =bdrv_query_snapshot_info_list (bs, &info->snapshots, &err);
Re: [Qemu-devel] [PATCH v2 4/6] block: move string allocation from stack to the heap
In reply to Jeff CodyQuoted 41 lines · Jeff Cody
Rather than allocate
PATH_MAXbytes on the stack, useg_strndup()to dynamically allocate the string, and add an exit label for cleanup.Signed-off-by Jeff Cody <[email protected]>--- block.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)block.c +5
-4@@ -2207,7 +2207,7 @@ int bdrv_commit(BlockDriverState *bs)int n, ro, open_flags;int ret =0 ;uint8_t *buf =NULL ; -char filename[PATH_MAX ]; +char *filename =NULL ;if (!drv)return -ENOMEDIUM ;@@ -2222,13 +2222,14 @@ int bdrv_commit(BlockDriverState *bs) } ro = bs->backing_hd->read_only; -/* Use pstrcpy (not strncpy): filename must be NUL-terminated. */ -pstrcpy (filename,sizeof (filename), bs->backing_hd->filename); +/* filename must be NUL-terminated. */ + filename =g_strndup (bs->backing_hd->filename,PATH_MAX -1 ); open_flags = bs->backing_hd->open_flags;if (ro) {if (bdrv_reopen (bs->backing_hd, open_flags |BDRV_O_RDWR ,NULL )) { -return -EACCES ; + ret = -EACCES ; + goto exit; } }
block.c ro_cleanup: · line 2315
Quoted 8 lines
block.c +2
-0@@ -2307,6 +2308,8 @@ ro_cleanup:bdrv_reopen (bs->backing_hd, open_flags & ~BDRV_O_RDWR ,NULL ); } +exit: +g_free (filename);return ret; }
Re: [Qemu-devel] [PATCH v2 5/6] block: mirror - change string allocation to 2-bytes
In reply to Jeff CodyQuoted 19 lines · Jeff Cody
The
backing_filenamestring inmirror_run()is only used to check for a NULL string, so we don't need to allocate 1024 bytes (or, later,PATH_MAXbytes), when we only need to copy the first 2 characters.We technically only need 1 byte, as we are just checking for NULL, but since backing_filename[] is populated by
bdrv_get_backing_filename(), a string size of 1 will always only return '\0';Signed-off-by Jeff Cody <[email protected]>--- block/mirror.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)block/mirror.c +0
-0
block/mirror.c static void coroutine_fn mirror_run(void *opaque) · line 385
Quoted 9 lines
block/mirror.c +2
-1@@ -378,7 +378,8 @@ static void coroutine_fn mirror_run(void *opaque)int64_t sector_num, end, sectors_per_chunk, length;uint64_t last_pause_ns;BlockDriverInfo bdi; -char backing_filename[1024 ]; +char backing_filename[2 ];/* we only need 2 characters because we are only +checking for a NULL string */ int ret =0 ;int n;
Re: [Qemu-devel] [PATCH v2 6/6] block: update string sizes for filename, backing_file, exact_filename
In reply to Jeff CodyQuoted 126 lines · Jeff Cody
The string field entries 'filename', '
backing_file', and 'exact_filename' in the BlockDriverState struct are defined as 1024 bytes.However, many places that use these values accept a maximum of
PATH_MAXbytes, so we have a mixture of 1024 byte andPATH_MAXbyte allocations. This patch makes the BlockDriverStruct field string sizes match usage.This patch also does a few fixes related to the size that needs to happen now:
* the block qapi driver is updated to use
PATH_MAXbytes
* the qcow and qcow2 drivers have an additional safety check
* the block vvfat driver is updated to usePATH_MAXbytes for the size ofbacking_file, for systems wherePATH_MAXis < 1024 bytes.
* qemu-img usesPATH_MAXrather than 1024. These instances were not changed to be dynamically allocated, however, as the extra temporary 3K in stack usage for qemu-img does not seem worrisome.Signed-off-by Jeff Cody <[email protected]>--- block/qapi.c | 4 ++-- block/qcow.c | 2 +- block/qcow2.c | 3 ++- block/vvfat.c | 4 ++-- include/block/block_int.h | 8 ++++---- qemu-img.c | 4 ++-- 6 files changed, 13 insertions(+), 12 deletions(-)block/qapi.c +2
-2@@ -211,10 +211,10 @@ void bdrv_query_image_info(BlockDriverState *bs, backing_filename = bs->backing_file;if (backing_filename[0 ] !='\0' ) { - backing_filename2 =g_malloc0 (1024 ); + backing_filename2 =g_malloc0 (PATH_MAX ); info->backing_filename =g_strdup (backing_filename); info->has_backing_filename = true; -bdrv_get_full_backing_filename (bs, backing_filename2,1024 , &err); +bdrv_get_full_backing_filename (bs, backing_filename2,PATH_MAX , &err);if (err) {error_propagate (errp, err);qapi_free_ImageInfo (info);block/qcow.c +1
-1@@ -215,7 +215,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,/* read the backing file name */ if (header.backing_file_offset !=0 ) { len = header.backing_file_size; -if (len >1023 ) { +if (len >1023 || len >sizeof (bs->backing_file)) {error_setg (errp,"Backing file name too long" ); ret = -EINVAL ; goto fail;block/qcow2.c +2
-1@@ -868,7 +868,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,/* read the backing file name */ if (header.backing_file_offset !=0 ) { len = header.backing_file_size; -if (len >MIN (1023 , s->cluster_size - header.backing_file_offset)) { +if (len >MIN (1023 , s->cluster_size - header.backing_file_offset) || + len >sizeof (bs->backing_file)) {error_setg (errp,"Backing file name too long" ); ret = -EINVAL ; goto fail;block/vvfat.c +2
-2@@ -2909,8 +2909,8 @@ static int enable_write_target(BDRVVVFATState *s, Error **errp)array_init (&(s->commits),sizeof (commit_t)); - s->qcow_filename =g_malloc (1024 ); - ret =get_tmp_filename (s->qcow_filename,1024 ); + s->qcow_filename =g_malloc (PATH_MAX ); + ret =get_tmp_filename (s->qcow_filename,PATH_MAX );if (ret <0 ) {error_setg_errno (errp, -ret,"can't create temporary file" ); goto err;include/block/block_int.h +4
-4@@ -339,13 +339,13 @@ struct BlockDriverState {* regarding this BDS's context */ QLIST_HEAD(, BdrvAioNotifier) aio_notifiers; -char filename[1024 ]; -char backing_file[1024 ];/* if non zero, the image is a diff of -this file image */ +char filename[PATH_MAX ]; +char backing_file[PATH_MAX ];/* if non zero, the image is a diff of +this file image */ char backing_format[16 ];/* if non-zero and backing_file exists */ QDict *full_open_options; -char exact_filename[1024 ]; +char exact_filename[PATH_MAX ];BlockDriverState *backing_hd;BlockDriverState *file;qemu-img.c +1
-1@@ -2556,7 +2556,7 @@ static int img_rebase(int argc, char **argv)/* For safe rebasing we need to compare old and new backing file */ if (!unsafe) { -char backing_name[1024 ]; +char backing_name[PATH_MAX ]; blk_old_backing =blk_new_with_bs ("old_backing" , &error_abort); bs_old_backing =blk_bs (blk_old_backing);
qemu-img.c static int img_rebase(int argc, char **argv) · line 2620
Quoted 8 lines
qemu-img.c +1
-1@@ -2614,7 +2614,7 @@ static int img_rebase(int argc, char **argv) } old_backing_num_sectors =bdrv_nb_sectors (bs_old_backing);if (old_backing_num_sectors <0 ) { -char backing_name[1024 ]; +char backing_name[PATH_MAX ];bdrv_get_backing_filename (bs, backing_name,sizeof (backing_name)); error_report("Could not get size of '%s': %s",
Re: [Qemu-devel] [PATCH v2 1/6] block: vmdk - make ret variable usage clear
In reply to Jeff CodyQuoted 8 lines · Jeff Cody
Keep the variable 'ret' something that is returned by the function it is defined in. For the return value of 'sscanf', use a more meaningful variable name.
Signed-off-by Jeff Cody <[email protected]>--- block/vmdk.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
Re: [Qemu-devel] [PATCH v2 2/6] block: vmdk - move string allocations from stack to the heap
In reply to Jeff Codyblock/vmdk.c static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, · line 795
Quoted 6 lines · Jeff Cody
block/vmdk.c +1
-1@@ -792,12 +792,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,const char *p = desc;int64_t sectors =0 ;int64_t flat_offset; -char extent_path[PATH_MAX ]; +char *extent_path =g_malloc0 (PATH_MAX );
Simpler alternative that has no risk of memory leaks:
extent_path = g_malloc0(PATH_MAX);
path_combine(extent_path, sizeof(extent_path),
desc_file_path, fname);
extent_file = NULL;
ret = bdrv_open(&extent_file, extent_path, NULL, NULL,
bs->open_flags | BDRV_O_PROTOCOL, NULL, errp);
g_free(extent_path);
if (ret) {
goto exit;
}Re: [Qemu-devel] [PATCH v2 2/6] block: vmdk - move string allocations from stack to the heap
Quoted 10 lines · Stefan Hajnoczi
block/vmdk.c static int vmdk_parse_extents(const char *desc, BlockDriverState *bs, · line 795
Quoted 6 lines · Jeff Cody
block/vmdk.c +1
-1@@ -792,12 +792,11 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,const char *p = desc;int64_t sectors =0 ;int64_t flat_offset; -char extent_path[PATH_MAX ]; +char *extent_path =g_malloc0 (PATH_MAX );Simpler alternative that has no risk of memory leaks:
Quoted 7 lines
extent_path = g_malloc0(PATH_MAX);
path_combine(extent_path, sizeof(extent_path),
desc_file_path, fname);
extent_file = NULL;
ret = bdrv_open(&extent_file, extent_path, NULL, NULL,
bs->open_flags | BDRV_O_PROTOCOL, NULL, errp);
g_free(extent_path);Much better would be to change path_combine so it doesn't need to have the destination alloc done by the caller. Just have it allocate the right sized string buffer directly & return that and avoid the madness of PATH_MAX entirely.
Regards,
Daniel
Signature · 4 lines
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
Re: [Qemu-devel] [PATCH v2 3/6] block: qapi - move string allocation from stack to the heap
In reply to Jeff CodyQuoted 2 lines · Jeff Cody
Rather than declaring '
backing_filename2' on the stack inbdrv_quiery_image_info(), dynamically allocate it on the heap.
s/quiery/query/
Quoted 20 lines
Signed-off-by Jeff Cody <[email protected]>--- block/qapi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)block/qapi.c +1
-1@@ -175,7 +175,7 @@ void bdrv_query_image_info(BlockDriverState *bs, {int64_t size;const char *backing_filename; -char backing_filename2[1024 ]; +char *backing_filename2 =NULL ;BlockDriverInfo bdi;int ret;Error *err =NULL ;
block/qapi.c void bdrv_query_image_info(BlockDriverState *bs, · line 214
Quoted 4 lines
block/qapi.c +1
-0@@ -211,13 +211,14 @@ void bdrv_query_image_info(BlockDriverState *bs, backing_filename = bs->backing_file;if (backing_filename[0 ] !='\0' ) { + backing_filename2 =g_malloc0 (1024 );
backing_filename2 is only used inside the body of this if statement. Please move the declaration in here to avoid initializing with NULL (that value is never used but I had to check the surrounding code to figure that out).
Re: [Qemu-devel] [PATCH v2 4/6] block: move string allocation from stack to the heap
In reply to Jeff CodyQuoted 7 lines · Jeff Cody
Rather than allocate
PATH_MAXbytes on the stack, useg_strndup()to dynamically allocate the string, and add an exit label for cleanup.Signed-off-by Jeff Cody <[email protected]>--- block.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
Zombie alert!
This is a funny:
Since September 2012 in commit 0bce597d6ec34b2af802799eb53ebc863c704d05 ("block: convert bdrv_commit() to use bdrv_reopen()") the filename variable has not been used.
We continued to maintain this variable faithfully, for example, to fix a buffer overflow in commit c2cba3d9314f972dfaf724d0ec2d018eb54c95f1 ("block: avoid buffer overrun by using pstrcpy, not strncpy").
Please kill the zombie filename variable instead of switching to heap allocation :-).
Re: [Qemu-devel] [PATCH v2 5/6] block: mirror - change string allocation to 2-bytes
In reply to Jeff CodyQuoted 4 lines · Jeff Cody
The
backing_filenamestring inmirror_run()is only used to check for a NULL string, so we don't need to allocate 1024 bytes (or, later,PATH_MAXbytes), when we only need to copy the first 2 characters.
Quoted 8 lines
We technically only need 1 byte, as we are just checking for NULL, but since backing_filename[] is populated by
bdrv_get_backing_filename(), a string size of 1 will always only return '\0';Signed-off-by Jeff Cody <[email protected]>--- block/mirror.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
Re: [Qemu-devel] [PATCH v2 6/6] block: update string sizes for filename, backing_file, exact_filename
In reply to Jeff CodyQuoted 21 lines · Jeff Cody
The string field entries 'filename', '
backing_file', and 'exact_filename' in the BlockDriverState struct are defined as 1024 bytes.However, many places that use these values accept a maximum of
PATH_MAXbytes, so we have a mixture of 1024 byte andPATH_MAXbyte allocations. This patch makes the BlockDriverStruct field string sizes match usage.This patch also does a few fixes related to the size that needs to happen now:
* the block qapi driver is updated to use
PATH_MAXbytes
* the qcow and qcow2 drivers have an additional safety check
* the block vvfat driver is updated to usePATH_MAXbytes for the size ofbacking_file, for systems wherePATH_MAXis < 1024 bytes.
* qemu-img usesPATH_MAXrather than 1024. These instances were not changed to be dynamically allocated, however, as the extra temporary 3K in stack usage for qemu-img does not seem worrisome.Signed-off-by Jeff Cody <[email protected]>
Quoted 8 lines
--- block/qapi.c | 4 ++-- block/qcow.c | 2 +- block/qcow2.c | 3 ++- block/vvfat.c | 4 ++-- include/block/block_int.h | 8 ++++---- qemu-img.c | 4 ++-- 6 files changed, 13 insertions(+), 12 deletions(-)
Re: [Qemu-devel] [PATCH v2 4/6] block: move string allocation from stack to the heap
In reply to Stefan HajnocziQuoted 17 lines · Stefan Hajnoczi
Quoted 7 lines · Jeff Cody
Rather than allocate
PATH_MAXbytes on the stack, useg_strndup()to dynamically allocate the string, and add an exit label for cleanup.Signed-off-by Jeff Cody <[email protected]>--- block.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)Zombie alert!
This is a funny:
Since September 2012 in commit
0bce597d6ec34b2af802799eb53ebc863c704d05("block: convertbdrv_commit()to usebdrv_reopen()") the filename variable has not been used.
Quoted 6 lines
We continued to maintain this variable faithfully, for example, to fix a buffer overflow in commit
c2cba3d9314f972dfaf724d0ec2d018eb54c95f1("block: avoid buffer overrun by using pstrcpy, not strncpy").Please kill the zombie filename variable instead of switching to heap allocation :-).
Ha! OK, will kill the zombie :)