Compare commits
	
		
			No commits in common. "c8-beta-stream-rhel" and "c8-stream-rhel" have entirely different histories.
		
	
	
		
			c8-beta-st
			...
			c8-stream-
		
	
		
| @ -0,0 +1,36 @@ | |||||||
|  | From a707eff49800045d07afbcd8a74617c50b960151 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: German Maglione <gmaglione@redhat.com> | ||||||
|  | Date: Thu, 10 Oct 2024 13:23:25 +0200 | ||||||
|  | Subject: [PATCH] Fix thread-pool-size default value in the man page | ||||||
|  | 
 | ||||||
|  | RH-Author: German Maglione <None> | ||||||
|  | RH-MergeRequest: 417: Fix thread-pool-size default value in the man page | ||||||
|  | RH-Jira: RHEL-26197 | ||||||
|  | RH-Acked-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  | RH-Acked-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-Commit: [1/1] bdf22ed4600ac7f02a4b08c54f162b1f89c44a99 | ||||||
|  | 
 | ||||||
|  | The current --thread-pool-size default value is 0, let's reflect it | ||||||
|  | in the man page. | ||||||
|  | 
 | ||||||
|  | Signed-off-by: German Maglione <gmaglione@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  docs/tools/virtiofsd.rst | 2 +- | ||||||
|  |  1 file changed, 1 insertion(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst
 | ||||||
|  | index 07ac0be551..fb3d59c449 100644
 | ||||||
|  | --- a/docs/tools/virtiofsd.rst
 | ||||||
|  | +++ b/docs/tools/virtiofsd.rst
 | ||||||
|  | @@ -120,7 +120,7 @@ Options
 | ||||||
|  |  .. option:: --thread-pool-size=NUM | ||||||
|  |   | ||||||
|  |    Restrict the number of worker threads per request queue to NUM.  The default | ||||||
|  | -  is 64.
 | ||||||
|  | +  is 0.
 | ||||||
|  |   | ||||||
|  |  .. option:: --cache=none|auto|always | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.45.2 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,260 @@ | |||||||
|  | From c4ba1f1755031a0ac2f600ed8c17e7dcb6b2b857 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||||||
|  | Subject: [PATCH 5/5] block: Parse filenames only when explicitly requested | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||||||
|  | RH-Jira: RHEL-35616 | ||||||
|  | RH-CVE: CVE-2024-4467 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [5/5] a3e197add64fc6950c4ac576e34d833dfae7ee34 | ||||||
|  | 
 | ||||||
|  | Conflicts: - brdv_open_child_common(): bdrv_graph_wrlock/unlock() | ||||||
|  |              don't exist in this code version. We ignore them. | ||||||
|  | 	     bdrv_open_inherit(): no_coroutine_fn/GRAPH_UNLOCKED | ||||||
|  |              doesn't exist. We ignore it. | ||||||
|  |            - Changes to bdrv_open_file_child() didn't apply cleanly, | ||||||
|  |              but fixing it is straight-forward. | ||||||
|  |            - GLOBAL_STATE_CODE() not present in this code. Ignoring it. | ||||||
|  |            - bdrv_open_file_child(): Need to continue setting of | ||||||
|  | 	     parent->file. | ||||||
|  | 
 | ||||||
|  | commit f44c2941d4419e60f16dea3e9adca164e75aa78d | ||||||
|  | Author: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | Date:   Thu Apr 25 14:56:02 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     block: Parse filenames only when explicitly requested | ||||||
|  | 
 | ||||||
|  |     When handling image filenames from legacy options such as -drive or from | ||||||
|  |     tools, these filenames are parsed for protocol prefixes, including for | ||||||
|  |     the json:{} pseudo-protocol. | ||||||
|  | 
 | ||||||
|  |     This behaviour is intended for filenames that come directly from the | ||||||
|  |     command line and for backing files, which may come from the image file | ||||||
|  |     itself. Higher level management tools generally take care to verify that | ||||||
|  |     untrusted images don't contain a bad (or any) backing file reference; | ||||||
|  |     'qemu-img info' is a suitable tool for this. | ||||||
|  | 
 | ||||||
|  |     However, for other files that can be referenced in images, such as | ||||||
|  |     qcow2 data files or VMDK extents, the string from the image file is | ||||||
|  |     usually not verified by management tools - and 'qemu-img info' wouldn't | ||||||
|  |     be suitable because in contrast to backing files, it already opens these | ||||||
|  |     other referenced files. So here the string should be interpreted as a | ||||||
|  |     literal local filename. More complex configurations need to be specified | ||||||
|  |     explicitly on the command line or in QMP. | ||||||
|  | 
 | ||||||
|  |     This patch changes bdrv_open_inherit() so that it only parses filenames | ||||||
|  |     if a new parameter parse_filename is true. It is set for the top level | ||||||
|  |     in bdrv_open(), for the file child and for the backing file child. All | ||||||
|  |     other callers pass false and disable filename parsing this way. | ||||||
|  | 
 | ||||||
|  |     Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  |     Reviewed-by: Eric Blake <eblake@redhat.com> | ||||||
|  |     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  |     Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  |     Upstream: N/A, embargoed | ||||||
|  |     Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  block.c | 81 +++++++++++++++++++++++++++++++++++++++------------------ | ||||||
|  |  1 file changed, 56 insertions(+), 25 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/block.c b/block.c
 | ||||||
|  | index 889f878565..ddebf50efa 100644
 | ||||||
|  | --- a/block.c
 | ||||||
|  | +++ b/block.c
 | ||||||
|  | @@ -82,6 +82,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
 | ||||||
|  |                                             BlockDriverState *parent, | ||||||
|  |                                             const BdrvChildClass *child_class, | ||||||
|  |                                             BdrvChildRole child_role, | ||||||
|  | +                                           bool parse_filename,
 | ||||||
|  |                                             Error **errp); | ||||||
|  |   | ||||||
|  |  static bool bdrv_recurse_has_child(BlockDriverState *bs, | ||||||
|  | @@ -1926,7 +1927,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
 | ||||||
|  |   * block driver has been specified explicitly. | ||||||
|  |   */ | ||||||
|  |  static int bdrv_fill_options(QDict **options, const char *filename, | ||||||
|  | -                             int *flags, Error **errp)
 | ||||||
|  | +                             int *flags, bool allow_parse_filename,
 | ||||||
|  | +                             Error **errp)
 | ||||||
|  |  { | ||||||
|  |      const char *drvname; | ||||||
|  |      bool protocol = *flags & BDRV_O_PROTOCOL; | ||||||
|  | @@ -1966,7 +1968,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
 | ||||||
|  |      if (protocol && filename) { | ||||||
|  |          if (!qdict_haskey(*options, "filename")) { | ||||||
|  |              qdict_put_str(*options, "filename", filename); | ||||||
|  | -            parse_filename = true;
 | ||||||
|  | +            parse_filename = allow_parse_filename;
 | ||||||
|  |          } else { | ||||||
|  |              error_setg(errp, "Can't specify 'file' and 'filename' options at " | ||||||
|  |                               "the same time"); | ||||||
|  | @@ -3439,7 +3441,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, | ||||||
|  | -                                   &child_of_bds, bdrv_backing_role(bs), errp);
 | ||||||
|  | +                                   &child_of_bds, bdrv_backing_role(bs), true,
 | ||||||
|  | +                                   errp);
 | ||||||
|  |      if (!backing_hd) { | ||||||
|  |          bs->open_flags |= BDRV_O_NO_BACKING; | ||||||
|  |          error_prepend(errp, "Could not open backing file: "); | ||||||
|  | @@ -3472,7 +3475,8 @@ free_exit:
 | ||||||
|  |  static BlockDriverState * | ||||||
|  |  bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, | ||||||
|  |                     BlockDriverState *parent, const BdrvChildClass *child_class, | ||||||
|  | -                   BdrvChildRole child_role, bool allow_none, Error **errp)
 | ||||||
|  | +                   BdrvChildRole child_role, bool allow_none,
 | ||||||
|  | +                   bool parse_filename, Error **errp)
 | ||||||
|  |  { | ||||||
|  |      BlockDriverState *bs = NULL; | ||||||
|  |      QDict *image_options; | ||||||
|  | @@ -3503,7 +3507,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      bs = bdrv_open_inherit(filename, reference, image_options, 0, | ||||||
|  | -                           parent, child_class, child_role, errp);
 | ||||||
|  | +                           parent, child_class, child_role, parse_filename,
 | ||||||
|  | +                           errp);
 | ||||||
|  |      if (!bs) { | ||||||
|  |          goto done; | ||||||
|  |      } | ||||||
|  | @@ -3513,6 +3518,29 @@ done:
 | ||||||
|  |      return bs; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static BdrvChild *bdrv_open_child_common(const char *filename,
 | ||||||
|  | +                                         QDict *options, const char *bdref_key,
 | ||||||
|  | +                                         BlockDriverState *parent,
 | ||||||
|  | +                                         const BdrvChildClass *child_class,
 | ||||||
|  | +                                         BdrvChildRole child_role,
 | ||||||
|  | +                                         bool allow_none, bool parse_filename,
 | ||||||
|  | +                                         Error **errp)
 | ||||||
|  | +{
 | ||||||
|  | +    BlockDriverState *bs;
 | ||||||
|  | +    BdrvChild *child;
 | ||||||
|  | +
 | ||||||
|  | +    bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
 | ||||||
|  | +                            child_role, allow_none, parse_filename, errp);
 | ||||||
|  | +    if (bs == NULL) {
 | ||||||
|  | +        return NULL;
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
 | ||||||
|  | +                              errp);
 | ||||||
|  | +
 | ||||||
|  | +    return child;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  /* | ||||||
|  |   * Opens a disk image whose options are given as BlockdevRef in another block | ||||||
|  |   * device's options. | ||||||
|  | @@ -3534,20 +3562,17 @@ BdrvChild *bdrv_open_child(const char *filename,
 | ||||||
|  |                             BdrvChildRole child_role, | ||||||
|  |                             bool allow_none, Error **errp) | ||||||
|  |  { | ||||||
|  | -    BlockDriverState *bs;
 | ||||||
|  | -
 | ||||||
|  | -    bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
 | ||||||
|  | -                            child_role, allow_none, errp);
 | ||||||
|  | -    if (bs == NULL) {
 | ||||||
|  | -        return NULL;
 | ||||||
|  | -    }
 | ||||||
|  | -
 | ||||||
|  | -    return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
 | ||||||
|  | -                             errp);
 | ||||||
|  | +    return bdrv_open_child_common(filename, options, bdref_key, parent,
 | ||||||
|  | +                                  child_class, child_role, allow_none, false,
 | ||||||
|  | +                                  errp);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | - * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
 | ||||||
|  | + * This does mostly the same as bdrv_open_child(), but for opening the primary
 | ||||||
|  | + * child of a node. A notable difference from bdrv_open_child() is that it
 | ||||||
|  | + * enables filename parsing for protocol names (including json:).
 | ||||||
|  | + *
 | ||||||
|  | + * @parent can move to a different AioContext in this function.
 | ||||||
|  |   */ | ||||||
|  |  int bdrv_open_file_child(const char *filename, | ||||||
|  |                           QDict *options, const char *bdref_key, | ||||||
|  | @@ -3558,8 +3583,9 @@ int bdrv_open_file_child(const char *filename,
 | ||||||
|  |      role = parent->drv->is_filter ? | ||||||
|  |          (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; | ||||||
|  |   | ||||||
|  | -    parent->file = bdrv_open_child(filename, options, bdref_key, parent,
 | ||||||
|  | -                                   &child_of_bds, role, false, errp);
 | ||||||
|  | +    parent->file = bdrv_open_child_common(filename, options, bdref_key, parent,
 | ||||||
|  | +                                          &child_of_bds, role, false, true,
 | ||||||
|  | +                                          errp);
 | ||||||
|  |   | ||||||
|  |      return parent->file ? 0 : -EINVAL; | ||||||
|  |  } | ||||||
|  | @@ -3599,7 +3625,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
 | ||||||
|  |   | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
 | ||||||
|  | +    bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
 | ||||||
|  | +                           errp);
 | ||||||
|  |      obj = NULL; | ||||||
|  |      qobject_unref(obj); | ||||||
|  |      visit_free(v); | ||||||
|  | @@ -3690,6 +3717,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
 | ||||||
|  |                                             BlockDriverState *parent, | ||||||
|  |                                             const BdrvChildClass *child_class, | ||||||
|  |                                             BdrvChildRole child_role, | ||||||
|  | +                                           bool parse_filename,
 | ||||||
|  |                                             Error **errp) | ||||||
|  |  { | ||||||
|  |      int ret; | ||||||
|  | @@ -3733,9 +3761,11 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      /* json: syntax counts as explicit options, as if in the QDict */ | ||||||
|  | -    parse_json_protocol(options, &filename, &local_err);
 | ||||||
|  | -    if (local_err) {
 | ||||||
|  | -        goto fail;
 | ||||||
|  | +    if (parse_filename) {
 | ||||||
|  | +        parse_json_protocol(options, &filename, &local_err);
 | ||||||
|  | +        if (local_err) {
 | ||||||
|  | +            goto fail;
 | ||||||
|  | +        }
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      bs->explicit_options = qdict_clone_shallow(options); | ||||||
|  | @@ -3760,7 +3790,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
 | ||||||
|  |                                       parent->open_flags, parent->options); | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    ret = bdrv_fill_options(&options, filename, &flags, &local_err);
 | ||||||
|  | +    ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
 | ||||||
|  | +                            &local_err);
 | ||||||
|  |      if (ret < 0) { | ||||||
|  |          goto fail; | ||||||
|  |      } | ||||||
|  | @@ -3829,7 +3860,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
 | ||||||
|  |   | ||||||
|  |          file_bs = bdrv_open_child_bs(filename, options, "file", bs, | ||||||
|  |                                       &child_of_bds, BDRV_CHILD_IMAGE, | ||||||
|  | -                                     true, &local_err);
 | ||||||
|  | +                                     true, true, &local_err);
 | ||||||
|  |          if (local_err) { | ||||||
|  |              goto fail; | ||||||
|  |          } | ||||||
|  | @@ -3974,7 +4005,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
 | ||||||
|  |                              QDict *options, int flags, Error **errp) | ||||||
|  |  { | ||||||
|  |      return bdrv_open_inherit(filename, reference, options, flags, NULL, | ||||||
|  | -                             NULL, 0, errp);
 | ||||||
|  | +                             NULL, 0, true, errp);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* Return true if the NULL-terminated @list contains @str */ | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
							
								
								
									
										566
									
								
								SOURCES/kvm-block-introduce-bdrv_open_file_child-helper.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										566
									
								
								SOURCES/kvm-block-introduce-bdrv_open_file_child-helper.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,566 @@ | |||||||
|  | From 996680dd6d5afd51918e600126dbfed4dfe89e05 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Sun, 9 Jun 2024 23:08:39 -0400 | ||||||
|  | Subject: [PATCH 4/5] block: introduce bdrv_open_file_child() helper | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||||||
|  | RH-Jira: RHEL-35616 | ||||||
|  | RH-CVE: CVE-2024-4467 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [4/5] 9f582a9aff740eb9ec6f64bfec94854038d8545f | ||||||
|  | 
 | ||||||
|  | Conflicts: - copy-before-write.c::cbw_copy() is an older version than | ||||||
|  |              upstream, but introduction of the new function is | ||||||
|  | 	     straight-forward. | ||||||
|  |            - include/block/block-global-state.h doesn't exist in this | ||||||
|  |              code version. Adding the prototype to | ||||||
|  |              include/block/block.h instead. | ||||||
|  |            - struct BlockDriver has no field 'filtered_child_is_backing' | ||||||
|  |              We remove the corresponding assert() in the new function. | ||||||
|  | 
 | ||||||
|  | commit 83930780325b144a5908c45b3957b9b6457b3831 | ||||||
|  | Author: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | ||||||
|  | Date:   Tue Jul 26 23:11:21 2022 +0300 | ||||||
|  | 
 | ||||||
|  |     block: introduce bdrv_open_file_child() helper | ||||||
|  | 
 | ||||||
|  |     Almost all drivers call bdrv_open_child() similarly. Let's create a | ||||||
|  |     helper for this. | ||||||
|  | 
 | ||||||
|  |     The only not updated drivers that call bdrv_open_child() to set | ||||||
|  |     bs->file are raw-format and snapshot-access: | ||||||
|  |         raw-format sometimes want to have filtered child but | ||||||
|  |             don't set drv->is_filter to true. | ||||||
|  |         snapshot-access wants only DATA | PRIMARY | ||||||
|  | 
 | ||||||
|  |     Possibly we should implement drv->is_filter_func() handler, to consider | ||||||
|  |     raw-format as filter when it works as filter.. But it's another story. | ||||||
|  | 
 | ||||||
|  |     Note also, that we decrease assignments to bs->file in code: it helps | ||||||
|  |     us restrict modifying this field in further commit. | ||||||
|  | 
 | ||||||
|  |     Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | ||||||
|  |     Reviewed-by: Hanna Reitz <hreitz@redhat.com> | ||||||
|  |     Message-Id: <20220726201134.924743-3-vsementsov@yandex-team.ru> | ||||||
|  |     Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  |     Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  block.c                   | 18 ++++++++++++++++++ | ||||||
|  |  block/blkdebug.c          |  9 +++------ | ||||||
|  |  block/blklogwrites.c      |  7 ++----- | ||||||
|  |  block/blkreplay.c         |  7 ++----- | ||||||
|  |  block/blkverify.c         |  9 +++------ | ||||||
|  |  block/bochs.c             |  7 +++---- | ||||||
|  |  block/cloop.c             |  7 +++---- | ||||||
|  |  block/copy-before-write.c |  9 ++++----- | ||||||
|  |  block/copy-on-read.c      |  9 ++++----- | ||||||
|  |  block/crypto.c            | 11 ++++++----- | ||||||
|  |  block/dmg.c               |  7 +++---- | ||||||
|  |  block/filter-compress.c   |  8 +++----- | ||||||
|  |  block/parallels.c         |  7 +++---- | ||||||
|  |  block/preallocate.c       |  9 ++++----- | ||||||
|  |  block/qcow.c              |  6 ++---- | ||||||
|  |  block/qcow2.c             |  8 ++++---- | ||||||
|  |  block/qed.c               |  8 ++++---- | ||||||
|  |  block/replication.c       |  8 +++----- | ||||||
|  |  block/throttle.c          |  8 +++----- | ||||||
|  |  block/vdi.c               |  7 +++---- | ||||||
|  |  block/vhdx.c              |  7 +++---- | ||||||
|  |  block/vmdk.c              |  7 +++---- | ||||||
|  |  block/vpc.c               |  7 +++---- | ||||||
|  |  include/block/block.h     |  3 +++ | ||||||
|  |  24 files changed, 92 insertions(+), 101 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/block.c b/block.c
 | ||||||
|  | index 0ac5b163d2..889f878565 100644
 | ||||||
|  | --- a/block.c
 | ||||||
|  | +++ b/block.c
 | ||||||
|  | @@ -3546,6 +3546,24 @@ BdrvChild *bdrv_open_child(const char *filename,
 | ||||||
|  |                               errp); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
 | ||||||
|  | + */
 | ||||||
|  | +int bdrv_open_file_child(const char *filename,
 | ||||||
|  | +                         QDict *options, const char *bdref_key,
 | ||||||
|  | +                         BlockDriverState *parent, Error **errp)
 | ||||||
|  | +{
 | ||||||
|  | +    BdrvChildRole role;
 | ||||||
|  | +
 | ||||||
|  | +    role = parent->drv->is_filter ?
 | ||||||
|  | +        (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
 | ||||||
|  | +
 | ||||||
|  | +    parent->file = bdrv_open_child(filename, options, bdref_key, parent,
 | ||||||
|  | +                                   &child_of_bds, role, false, errp);
 | ||||||
|  | +
 | ||||||
|  | +    return parent->file ? 0 : -EINVAL;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  /* | ||||||
|  |   * TODO Future callers may need to specify parent/child_class in order for | ||||||
|  |   * option inheritance to work. Existing callers use it for the root node. | ||||||
|  | diff --git a/block/blkdebug.c b/block/blkdebug.c
 | ||||||
|  | index bbf2948703..5fcfc8ac6f 100644
 | ||||||
|  | --- a/block/blkdebug.c
 | ||||||
|  | +++ b/block/blkdebug.c
 | ||||||
|  | @@ -503,12 +503,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      /* Open the image file */ | ||||||
|  | -    bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
 | ||||||
|  | -                               bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        ret = -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image",
 | ||||||
|  | +                               bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  |          goto out; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | diff --git a/block/blklogwrites.c b/block/blklogwrites.c
 | ||||||
|  | index f7a251e91f..f66a617eb3 100644
 | ||||||
|  | --- a/block/blklogwrites.c
 | ||||||
|  | +++ b/block/blklogwrites.c
 | ||||||
|  | @@ -155,11 +155,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      /* Open the file */ | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
 | ||||||
|  | -                               errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        ret = -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  |          goto fail; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | diff --git a/block/blkreplay.c b/block/blkreplay.c
 | ||||||
|  | index dcbe780ddb..76a0b8d12a 100644
 | ||||||
|  | --- a/block/blkreplay.c
 | ||||||
|  | +++ b/block/blkreplay.c
 | ||||||
|  | @@ -26,11 +26,8 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      int ret; | ||||||
|  |   | ||||||
|  |      /* Open the image file */ | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        ret = -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  |          goto fail; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | diff --git a/block/blkverify.c b/block/blkverify.c
 | ||||||
|  | index d1facf5ba9..920e891684 100644
 | ||||||
|  | --- a/block/blkverify.c
 | ||||||
|  | +++ b/block/blkverify.c
 | ||||||
|  | @@ -121,12 +121,9 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      /* Open the raw file */ | ||||||
|  | -    bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
 | ||||||
|  | -                               bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        ret = -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw",
 | ||||||
|  | +                               bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  |          goto fail; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | diff --git a/block/bochs.c b/block/bochs.c
 | ||||||
|  | index 4d68658087..b2dc06bbfd 100644
 | ||||||
|  | --- a/block/bochs.c
 | ||||||
|  | +++ b/block/bochs.c
 | ||||||
|  | @@ -110,10 +110,9 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |          return ret; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs)); | ||||||
|  | diff --git a/block/cloop.c b/block/cloop.c
 | ||||||
|  | index b8c6d0eccd..bee87da173 100644
 | ||||||
|  | --- a/block/cloop.c
 | ||||||
|  | +++ b/block/cloop.c
 | ||||||
|  | @@ -71,10 +71,9 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |          return ret; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      /* read header */ | ||||||
|  | diff --git a/block/copy-before-write.c b/block/copy-before-write.c
 | ||||||
|  | index c30a5ff8de..8aa2cb6a85 100644
 | ||||||
|  | --- a/block/copy-before-write.c
 | ||||||
|  | +++ b/block/copy-before-write.c
 | ||||||
|  | @@ -150,12 +150,11 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |  { | ||||||
|  |      BDRVCopyBeforeWriteState *s = bs->opaque; | ||||||
|  |      BdrvDirtyBitmap *copy_bitmap; | ||||||
|  | +    int ret;
 | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds, | ||||||
|  | diff --git a/block/copy-on-read.c b/block/copy-on-read.c
 | ||||||
|  | index 1fc7fb3333..815ac1d835 100644
 | ||||||
|  | --- a/block/copy-on-read.c
 | ||||||
|  | +++ b/block/copy-on-read.c
 | ||||||
|  | @@ -41,12 +41,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      BDRVStateCOR *state = bs->opaque; | ||||||
|  |      /* Find a bottom node name, if any */ | ||||||
|  |      const char *bottom_node = qdict_get_try_str(options, "bottom"); | ||||||
|  | +    int ret;
 | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      bs->supported_read_flags = BDRV_REQ_PREFETCH; | ||||||
|  | diff --git a/block/crypto.c b/block/crypto.c
 | ||||||
|  | index c8ba4681e2..abfce39230 100644
 | ||||||
|  | --- a/block/crypto.c
 | ||||||
|  | +++ b/block/crypto.c
 | ||||||
|  | @@ -260,15 +260,14 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
 | ||||||
|  |  { | ||||||
|  |      BlockCrypto *crypto = bs->opaque; | ||||||
|  |      QemuOpts *opts = NULL; | ||||||
|  | -    int ret = -EINVAL;
 | ||||||
|  | +    int ret;
 | ||||||
|  |      QCryptoBlockOpenOptions *open_opts = NULL; | ||||||
|  |      unsigned int cflags = 0; | ||||||
|  |      QDict *cryptoopts = NULL; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      bs->supported_write_flags = BDRV_REQ_FUA & | ||||||
|  | @@ -276,6 +275,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
 | ||||||
|  |   | ||||||
|  |      opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort); | ||||||
|  |      if (!qemu_opts_absorb_qdict(opts, options, errp)) { | ||||||
|  | +        ret = -EINVAL;
 | ||||||
|  |          goto cleanup; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | @@ -284,6 +284,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
 | ||||||
|  |   | ||||||
|  |      open_opts = block_crypto_open_opts_init(cryptoopts, errp); | ||||||
|  |      if (!open_opts) { | ||||||
|  | +        ret = -EINVAL;
 | ||||||
|  |          goto cleanup; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | diff --git a/block/dmg.c b/block/dmg.c
 | ||||||
|  | index 447901fbb8..38c363dd39 100644
 | ||||||
|  | --- a/block/dmg.c
 | ||||||
|  | +++ b/block/dmg.c
 | ||||||
|  | @@ -439,10 +439,9 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |          return ret; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      block_module_load_one("dmg-bz2"); | ||||||
|  | diff --git a/block/filter-compress.c b/block/filter-compress.c
 | ||||||
|  | index d5be538619..305716c86c 100644
 | ||||||
|  | --- a/block/filter-compress.c
 | ||||||
|  | +++ b/block/filter-compress.c
 | ||||||
|  | @@ -30,11 +30,9 @@
 | ||||||
|  |  static int compress_open(BlockDriverState *bs, QDict *options, int flags, | ||||||
|  |                           Error **errp) | ||||||
|  |  { | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    int ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) { | ||||||
|  | diff --git a/block/parallels.c b/block/parallels.c
 | ||||||
|  | index 6ebad2a2bb..ed4debd899 100644
 | ||||||
|  | --- a/block/parallels.c
 | ||||||
|  | +++ b/block/parallels.c
 | ||||||
|  | @@ -735,10 +735,9 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      Error *local_err = NULL; | ||||||
|  |      char *buf; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph)); | ||||||
|  | diff --git a/block/preallocate.c b/block/preallocate.c
 | ||||||
|  | index 1d4233f730..332408bdc9 100644
 | ||||||
|  | --- a/block/preallocate.c
 | ||||||
|  | +++ b/block/preallocate.c
 | ||||||
|  | @@ -134,6 +134,7 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |                              Error **errp) | ||||||
|  |  { | ||||||
|  |      BDRVPreallocateState *s = bs->opaque; | ||||||
|  | +    int ret;
 | ||||||
|  |   | ||||||
|  |      /* | ||||||
|  |       * s->data_end and friends should be initialized on permission update. | ||||||
|  | @@ -141,11 +142,9 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |       */ | ||||||
|  |      s->file_end = s->zero_start = s->data_end = -EINVAL; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) { | ||||||
|  | diff --git a/block/qcow.c b/block/qcow.c
 | ||||||
|  | index c39940f33e..544a17261f 100644
 | ||||||
|  | --- a/block/qcow.c
 | ||||||
|  | +++ b/block/qcow.c
 | ||||||
|  | @@ -120,10 +120,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      qdict_extract_subqdict(options, &encryptopts, "encrypt."); | ||||||
|  |      encryptfmt = qdict_get_try_str(encryptopts, "format"); | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        ret = -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  |          goto fail; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | diff --git a/block/qcow2.c b/block/qcow2.c
 | ||||||
|  | index 6ee1919612..29ea157e6b 100644
 | ||||||
|  | --- a/block/qcow2.c
 | ||||||
|  | +++ b/block/qcow2.c
 | ||||||
|  | @@ -1907,11 +1907,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |          .errp = errp, | ||||||
|  |          .ret = -EINPROGRESS | ||||||
|  |      }; | ||||||
|  | +    int ret;
 | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      /* Initialise locks */ | ||||||
|  | diff --git a/block/qed.c b/block/qed.c
 | ||||||
|  | index 558d3646c4..e3b06a3d00 100644
 | ||||||
|  | --- a/block/qed.c
 | ||||||
|  | +++ b/block/qed.c
 | ||||||
|  | @@ -558,11 +558,11 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |          .errp = errp, | ||||||
|  |          .ret = -EINPROGRESS | ||||||
|  |      }; | ||||||
|  | +    int ret;
 | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      bdrv_qed_init_state(bs); | ||||||
|  | diff --git a/block/replication.c b/block/replication.c
 | ||||||
|  | index 55c8f894aa..2f17397764 100644
 | ||||||
|  | --- a/block/replication.c
 | ||||||
|  | +++ b/block/replication.c
 | ||||||
|  | @@ -88,11 +88,9 @@ static int replication_open(BlockDriverState *bs, QDict *options,
 | ||||||
|  |      const char *mode; | ||||||
|  |      const char *top_id; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      ret = -EINVAL; | ||||||
|  | diff --git a/block/throttle.c b/block/throttle.c
 | ||||||
|  | index 6e8d52fa24..4fb5798c27 100644
 | ||||||
|  | --- a/block/throttle.c
 | ||||||
|  | +++ b/block/throttle.c
 | ||||||
|  | @@ -78,11 +78,9 @@ static int throttle_open(BlockDriverState *bs, QDict *options,
 | ||||||
|  |      char *group; | ||||||
|  |      int ret; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
 | ||||||
|  | -                               false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |      bs->supported_write_flags = bs->file->bs->supported_write_flags | | ||||||
|  |                                  BDRV_REQ_WRITE_UNCHANGED; | ||||||
|  | diff --git a/block/vdi.c b/block/vdi.c
 | ||||||
|  | index bdc58d726e..c50c0ed61f 100644
 | ||||||
|  | --- a/block/vdi.c
 | ||||||
|  | +++ b/block/vdi.c
 | ||||||
|  | @@ -376,10 +376,9 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      int ret; | ||||||
|  |      QemuUUID uuid_link, uuid_parent; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      logout("\n"); | ||||||
|  | diff --git a/block/vhdx.c b/block/vhdx.c
 | ||||||
|  | index 356ec4c455..e7d6d7509a 100644
 | ||||||
|  | --- a/block/vhdx.c
 | ||||||
|  | +++ b/block/vhdx.c
 | ||||||
|  | @@ -996,10 +996,9 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      uint64_t signature; | ||||||
|  |      Error *local_err = NULL; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      s->bat = NULL; | ||||||
|  | diff --git a/block/vmdk.c b/block/vmdk.c
 | ||||||
|  | index 0dfab6e941..7d7e56b36c 100644
 | ||||||
|  | --- a/block/vmdk.c
 | ||||||
|  | +++ b/block/vmdk.c
 | ||||||
|  | @@ -1262,10 +1262,9 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      BDRVVmdkState *s = bs->opaque; | ||||||
|  |      uint32_t magic; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      buf = vmdk_read_desc(bs->file, 0, errp); | ||||||
|  | diff --git a/block/vpc.c b/block/vpc.c
 | ||||||
|  | index 297a26262a..430cab1cbb 100644
 | ||||||
|  | --- a/block/vpc.c
 | ||||||
|  | +++ b/block/vpc.c
 | ||||||
|  | @@ -232,10 +232,9 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
 | ||||||
|  |      int ret; | ||||||
|  |      int64_t bs_size; | ||||||
|  |   | ||||||
|  | -    bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
 | ||||||
|  | -                               BDRV_CHILD_IMAGE, false, errp);
 | ||||||
|  | -    if (!bs->file) {
 | ||||||
|  | -        return -EINVAL;
 | ||||||
|  | +    ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
 | ||||||
|  | +    if (ret < 0) {
 | ||||||
|  | +        return ret;
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort); | ||||||
|  | diff --git a/include/block/block.h b/include/block/block.h
 | ||||||
|  | index e5dd22b034..f885f113ef 100644
 | ||||||
|  | --- a/include/block/block.h
 | ||||||
|  | +++ b/include/block/block.h
 | ||||||
|  | @@ -376,6 +376,9 @@ BdrvChild *bdrv_open_child(const char *filename,
 | ||||||
|  |                             const BdrvChildClass *child_class, | ||||||
|  |                             BdrvChildRole child_role, | ||||||
|  |                             bool allow_none, Error **errp); | ||||||
|  | +int bdrv_open_file_child(const char *filename,
 | ||||||
|  | +                         QDict *options, const char *bdref_key,
 | ||||||
|  | +                         BlockDriverState *parent, Error **errp);
 | ||||||
|  |  BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp); | ||||||
|  |  int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, | ||||||
|  |                          Error **errp); | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
							
								
								
									
										104
									
								
								SOURCES/kvm-block-move-bdrv_qiov_is_aligned-to-file-posix.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								SOURCES/kvm-block-move-bdrv_qiov_is_aligned-to-file-posix.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | |||||||
|  | From 636e32b4c570ddb20266b6672311174353644f0e Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Keith Busch <kbusch@kernel.org> | ||||||
|  | Date: Thu, 29 Sep 2022 13:05:22 -0700 | ||||||
|  | Subject: [PATCH 1/2] block: move bdrv_qiov_is_aligned to file-posix | ||||||
|  | 
 | ||||||
|  | RH-Author: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-MergeRequest: 411: block: Fix iov_len check in bdrv_qiov_is_aligned() | ||||||
|  | RH-Jira: RHEL-60553 | ||||||
|  | RH-Acked-by: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-Acked-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-Commit: [1/2] 682c1b81b42959d9d91e0f68cd70e9753e53a279 | ||||||
|  | 
 | ||||||
|  | There is only user of bdrv_qiov_is_aligned(), so move the alignment | ||||||
|  | function to there and make it static. | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Keith Busch <kbusch@kernel.org> | ||||||
|  | Message-Id: <20220929200523.3218710-2-kbusch@meta.com> | ||||||
|  | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | (cherry picked from commit a7c5f67a78569f8c275ea4ea9962e9c79b9d03cb) | ||||||
|  | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  block/file-posix.c    | 20 ++++++++++++++++++++ | ||||||
|  |  block/io.c            | 20 -------------------- | ||||||
|  |  include/block/block.h |  1 - | ||||||
|  |  3 files changed, 20 insertions(+), 21 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/block/file-posix.c b/block/file-posix.c
 | ||||||
|  | index b283093e5b..b404e1544f 100644
 | ||||||
|  | --- a/block/file-posix.c
 | ||||||
|  | +++ b/block/file-posix.c
 | ||||||
|  | @@ -2051,6 +2051,26 @@ static int coroutine_fn raw_thread_pool_submit(BlockDriverState *bs,
 | ||||||
|  |      return thread_pool_submit_co(pool, func, arg); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * Check if all memory in this vector is sector aligned.
 | ||||||
|  | + */
 | ||||||
|  | +static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
 | ||||||
|  | +{
 | ||||||
|  | +    int i;
 | ||||||
|  | +    size_t alignment = bdrv_min_mem_align(bs);
 | ||||||
|  | +
 | ||||||
|  | +    for (i = 0; i < qiov->niov; i++) {
 | ||||||
|  | +        if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
 | ||||||
|  | +            return false;
 | ||||||
|  | +        }
 | ||||||
|  | +        if (qiov->iov[i].iov_len % alignment) {
 | ||||||
|  | +            return false;
 | ||||||
|  | +        }
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    return true;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset, | ||||||
|  |                                     uint64_t bytes, QEMUIOVector *qiov, int type) | ||||||
|  |  { | ||||||
|  | diff --git a/block/io.c b/block/io.c
 | ||||||
|  | index 8ae57728a6..639e171eff 100644
 | ||||||
|  | --- a/block/io.c
 | ||||||
|  | +++ b/block/io.c
 | ||||||
|  | @@ -3375,26 +3375,6 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size)
 | ||||||
|  |      return mem; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -/*
 | ||||||
|  | - * Check if all memory in this vector is sector aligned.
 | ||||||
|  | - */
 | ||||||
|  | -bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
 | ||||||
|  | -{
 | ||||||
|  | -    int i;
 | ||||||
|  | -    size_t alignment = bdrv_min_mem_align(bs);
 | ||||||
|  | -
 | ||||||
|  | -    for (i = 0; i < qiov->niov; i++) {
 | ||||||
|  | -        if ((uintptr_t) qiov->iov[i].iov_base % alignment) {
 | ||||||
|  | -            return false;
 | ||||||
|  | -        }
 | ||||||
|  | -        if (qiov->iov[i].iov_len % alignment) {
 | ||||||
|  | -            return false;
 | ||||||
|  | -        }
 | ||||||
|  | -    }
 | ||||||
|  | -
 | ||||||
|  | -    return true;
 | ||||||
|  | -}
 | ||||||
|  | -
 | ||||||
|  |  void bdrv_io_plug(BlockDriverState *bs) | ||||||
|  |  { | ||||||
|  |      BdrvChild *child; | ||||||
|  | diff --git a/include/block/block.h b/include/block/block.h
 | ||||||
|  | index f885f113ef..09b374b496 100644
 | ||||||
|  | --- a/include/block/block.h
 | ||||||
|  | +++ b/include/block/block.h
 | ||||||
|  | @@ -622,7 +622,6 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size);
 | ||||||
|  |  void *qemu_blockalign0(BlockDriverState *bs, size_t size); | ||||||
|  |  void *qemu_try_blockalign(BlockDriverState *bs, size_t size); | ||||||
|  |  void *qemu_try_blockalign0(BlockDriverState *bs, size_t size); | ||||||
|  | -bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov);
 | ||||||
|  |   | ||||||
|  |  void bdrv_enable_copy_on_read(BlockDriverState *bs); | ||||||
|  |  void bdrv_disable_copy_on_read(BlockDriverState *bs); | ||||||
|  | -- 
 | ||||||
|  | 2.45.2 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | From 9009b674a01dc0cd92c319c87714b5aca6e639f8 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Keith Busch <kbusch@kernel.org> | ||||||
|  | Date: Thu, 29 Sep 2022 13:05:23 -0700 | ||||||
|  | Subject: [PATCH 2/2] block: use the request length for iov alignment | ||||||
|  | 
 | ||||||
|  | RH-Author: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-MergeRequest: 411: block: Fix iov_len check in bdrv_qiov_is_aligned() | ||||||
|  | RH-Jira: RHEL-60553 | ||||||
|  | RH-Acked-by: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-Acked-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-Commit: [2/2] 0e01d51cfb21ca43283626c2367e5c5d0d531736 | ||||||
|  | 
 | ||||||
|  | An iov length needs to be aligned to the logical block size, which may | ||||||
|  | be larger than the memory alignment. | ||||||
|  | 
 | ||||||
|  | Tested-by: Jens Axboe <axboe@kernel.dk> | ||||||
|  | Signed-off-by: Keith Busch <kbusch@kernel.org> | ||||||
|  | Message-Id: <20220929200523.3218710-3-kbusch@meta.com> | ||||||
|  | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | (cherry picked from commit 25474d90aa50bd32e0de395a33d8de42dd6f2aef) | ||||||
|  | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  block/file-posix.c | 3 ++- | ||||||
|  |  1 file changed, 2 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/block/file-posix.c b/block/file-posix.c
 | ||||||
|  | index b404e1544f..b84c5725cc 100644
 | ||||||
|  | --- a/block/file-posix.c
 | ||||||
|  | +++ b/block/file-posix.c
 | ||||||
|  | @@ -2058,12 +2058,13 @@ static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
 | ||||||
|  |  { | ||||||
|  |      int i; | ||||||
|  |      size_t alignment = bdrv_min_mem_align(bs); | ||||||
|  | +    size_t len = bs->bl.request_alignment;
 | ||||||
|  |   | ||||||
|  |      for (i = 0; i < qiov->niov; i++) { | ||||||
|  |          if ((uintptr_t) qiov->iov[i].iov_base % alignment) { | ||||||
|  |              return false; | ||||||
|  |          } | ||||||
|  | -        if (qiov->iov[i].iov_len % alignment) {
 | ||||||
|  | +        if (qiov->iov[i].iov_len % len) {
 | ||||||
|  |              return false; | ||||||
|  |          } | ||||||
|  |      } | ||||||
|  | -- 
 | ||||||
|  | 2.45.2 | ||||||
|  | 
 | ||||||
							
								
								
									
										105
									
								
								SOURCES/kvm-glib-compat-Introduce-g_memdup2-wrapper.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								SOURCES/kvm-glib-compat-Introduce-g_memdup2-wrapper.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,105 @@ | |||||||
|  | From 939c75ab92ac608893cad0e46f55527950518a57 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Tue, 5 Mar 2024 11:36:15 -0500 | ||||||
|  | Subject: [PATCH 1/3] glib-compat: Introduce g_memdup2() wrapper | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 353: ui/clipboard: mark type as not available when there is no data | ||||||
|  | RH-Jira: RHEL-19628 | ||||||
|  | RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Commit: [1/2] f401c63303ef558bfcbb36e4c8fcc8bf2b1c3eb4 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-19628 | ||||||
|  | CVE: CVE-2023-6683 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit 2c674fada72079583a3f2cc1790b16a0259c4fa0 | ||||||
|  | Author: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  | Date:   Fri Sep 3 19:44:44 2021 +0200 | ||||||
|  | 
 | ||||||
|  |     glib-compat: Introduce g_memdup2() wrapper | ||||||
|  |     When experimenting raising GLIB_VERSION_MIN_REQUIRED to 2.68 | ||||||
|  |     (Fedora 34 provides GLib 2.68.1) we get: | ||||||
|  | 
 | ||||||
|  |       hw/virtio/virtio-crypto.c:245:24: error: 'g_memdup' is deprecated: Use 'g_memdup2' instead [-Werror,-Wdeprecated-declarations] | ||||||
|  |       ... | ||||||
|  | 
 | ||||||
|  |     g_memdup() has been updated by g_memdup2() to fix eventual security | ||||||
|  |     issues (size argument is 32-bit and could be truncated / wrapping). | ||||||
|  |     GLib recommends to copy their static inline version of g_memdup2(): | ||||||
|  |     https://discourse.gnome.org/t/port-your-module-from-g-memdup-to-g-memdup2-now/5538 | ||||||
|  | 
 | ||||||
|  |     Our glib-compat.h provides a comment explaining how to deal with | ||||||
|  |     these deprecated declarations (see commit e71e8cc0355 | ||||||
|  |     "glib: enforce the minimum required version and warn about old APIs"). | ||||||
|  | 
 | ||||||
|  |     Following this comment suggestion, implement the g_memdup2_qemu() | ||||||
|  |     wrapper to g_memdup2(), and use the safer equivalent inlined when | ||||||
|  |     we are using pre-2.68 GLib. | ||||||
|  | 
 | ||||||
|  |     Reported-by: Eric Blake <eblake@redhat.com> | ||||||
|  |     Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com> | ||||||
|  |     Reviewed-by: Eric Blake <eblake@redhat.com> | ||||||
|  |     Message-Id: <20210903174510.751630-3-philmd@redhat.com> | ||||||
|  |     Signed-off-by: Laurent Vivier <laurent@vivier.eu> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  include/glib-compat.h | 37 +++++++++++++++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 37 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/include/glib-compat.h b/include/glib-compat.h
 | ||||||
|  | index 9e95c888f5..8d01a8c01f 100644
 | ||||||
|  | --- a/include/glib-compat.h
 | ||||||
|  | +++ b/include/glib-compat.h
 | ||||||
|  | @@ -68,6 +68,43 @@
 | ||||||
|  |   * without generating warnings. | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * g_memdup2_qemu:
 | ||||||
|  | + * @mem: (nullable): the memory to copy.
 | ||||||
|  | + * @byte_size: the number of bytes to copy.
 | ||||||
|  | + *
 | ||||||
|  | + * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
 | ||||||
|  | + * from @mem. If @mem is %NULL it returns %NULL.
 | ||||||
|  | + *
 | ||||||
|  | + * This replaces g_memdup(), which was prone to integer overflows when
 | ||||||
|  | + * converting the argument from a #gsize to a #guint.
 | ||||||
|  | + *
 | ||||||
|  | + * This static inline version is a backport of the new public API from
 | ||||||
|  | + * GLib 2.68, kept internal to GLib for backport to older stable releases.
 | ||||||
|  | + * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319.
 | ||||||
|  | + *
 | ||||||
|  | + * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
 | ||||||
|  | + *          or %NULL if @mem is %NULL.
 | ||||||
|  | + */
 | ||||||
|  | +static inline gpointer g_memdup2_qemu(gconstpointer mem, gsize byte_size)
 | ||||||
|  | +{
 | ||||||
|  | +#if GLIB_CHECK_VERSION(2, 68, 0)
 | ||||||
|  | +    return g_memdup2(mem, byte_size);
 | ||||||
|  | +#else
 | ||||||
|  | +    gpointer new_mem;
 | ||||||
|  | +
 | ||||||
|  | +    if (mem && byte_size != 0) {
 | ||||||
|  | +        new_mem = g_malloc(byte_size);
 | ||||||
|  | +        memcpy(new_mem, mem, byte_size);
 | ||||||
|  | +    } else {
 | ||||||
|  | +        new_mem = NULL;
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    return new_mem;
 | ||||||
|  | +#endif
 | ||||||
|  | +}
 | ||||||
|  | +#define g_memdup2(m, s) g_memdup2_qemu(m, s)
 | ||||||
|  | +
 | ||||||
|  |  #if defined(G_OS_UNIX) | ||||||
|  |  /* | ||||||
|  |   * Note: The fallback implementation is not MT-safe, and it returns a copy of | ||||||
|  | -- 
 | ||||||
|  | 2.41.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,61 @@ | |||||||
|  | From f4623ea611a74c684b0097b98a803cbe7ffb0825 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Thu, 18 Jul 2024 09:26:55 -0400 | ||||||
|  | Subject: [PATCH 5/6] hw/char/virtio-serial-bus: Protect from DMA re-entrancy | ||||||
|  |  bugs | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability | ||||||
|  | RH-Jira: RHEL-32276 | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [5/6] fc8a445ebf6e763cd1482cd1f7ee23e5b5bbb388 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-32276 | ||||||
|  | CVE: CVE-2024-3446 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit b4295bff25f7b50de1d9cc94a9c6effd40056bca | ||||||
|  | Author: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  | Date:   Thu Apr 4 20:56:35 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs | ||||||
|  | 
 | ||||||
|  |     Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() | ||||||
|  |     so the bus and device use the same guard. Otherwise the | ||||||
|  |     DMA-reentrancy protection can be bypassed. | ||||||
|  | 
 | ||||||
|  |     Fixes: CVE-2024-3446 | ||||||
|  |     Cc: qemu-stable@nongnu.org | ||||||
|  |     Suggested-by: Alexander Bulekov <alxndr@bu.edu> | ||||||
|  |     Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  |     Acked-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  |     Reviewed-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Message-Id: <20240409105537.18308-4-philmd@linaro.org> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  hw/char/virtio-serial-bus.c | 3 +-- | ||||||
|  |  1 file changed, 1 insertion(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
 | ||||||
|  | index f18124b155..791b7ac59e 100644
 | ||||||
|  | --- a/hw/char/virtio-serial-bus.c
 | ||||||
|  | +++ b/hw/char/virtio-serial-bus.c
 | ||||||
|  | @@ -985,8 +985,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
 | ||||||
|  |          return; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port,
 | ||||||
|  | -                                   &dev->mem_reentrancy_guard);
 | ||||||
|  | +    port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port);
 | ||||||
|  |      port->elem = NULL; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,160 @@ | |||||||
|  | From d37035373a266644b241aab1f041ab09c9185540 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Thu, 18 Jul 2024 09:29:54 -0400 | ||||||
|  | Subject: [PATCH 4/6] hw/display/virtio-gpu: Protect from DMA re-entrancy bugs | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability | ||||||
|  | RH-Jira: RHEL-32276 | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [4/6] e3cd21742228528a1a74ea62d55b5941d3efb261 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-32276 | ||||||
|  | CVE: CVE-2024-3446 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit ba28e0ff4d95b56dc334aac2730ab3651ffc3132 | ||||||
|  | Author: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  | Date:   Thu Apr 4 20:56:27 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     hw/display/virtio-gpu: Protect from DMA re-entrancy bugs | ||||||
|  | 
 | ||||||
|  |     Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() | ||||||
|  |     so the bus and device use the same guard. Otherwise the | ||||||
|  |     DMA-reentrancy protection can be bypassed: | ||||||
|  | 
 | ||||||
|  |       $ cat << EOF | qemu-system-i386 -display none -nodefaults \ | ||||||
|  |                                       -machine q35,accel=qtest \ | ||||||
|  |                                       -m 512M \ | ||||||
|  |                                       -device virtio-gpu \ | ||||||
|  |                                       -qtest stdio | ||||||
|  |       outl 0xcf8 0x80000820 | ||||||
|  |       outl 0xcfc 0xe0004000 | ||||||
|  |       outl 0xcf8 0x80000804 | ||||||
|  |       outw 0xcfc 0x06 | ||||||
|  |       write 0xe0004030 0x4 0x024000e0 | ||||||
|  |       write 0xe0004028 0x1 0xff | ||||||
|  |       write 0xe0004020 0x4 0x00009300 | ||||||
|  |       write 0xe000401c 0x1 0x01 | ||||||
|  |       write 0x101 0x1 0x04 | ||||||
|  |       write 0x103 0x1 0x1c | ||||||
|  |       write 0x9301c8 0x1 0x18 | ||||||
|  |       write 0x105 0x1 0x1c | ||||||
|  |       write 0x107 0x1 0x1c | ||||||
|  |       write 0x109 0x1 0x1c | ||||||
|  |       write 0x10b 0x1 0x00 | ||||||
|  |       write 0x10d 0x1 0x00 | ||||||
|  |       write 0x10f 0x1 0x00 | ||||||
|  |       write 0x111 0x1 0x00 | ||||||
|  |       write 0x113 0x1 0x00 | ||||||
|  |       write 0x115 0x1 0x00 | ||||||
|  |       write 0x117 0x1 0x00 | ||||||
|  |       write 0x119 0x1 0x00 | ||||||
|  |       write 0x11b 0x1 0x00 | ||||||
|  |       write 0x11d 0x1 0x00 | ||||||
|  |       write 0x11f 0x1 0x00 | ||||||
|  |       write 0x121 0x1 0x00 | ||||||
|  |       write 0x123 0x1 0x00 | ||||||
|  |       write 0x125 0x1 0x00 | ||||||
|  |       write 0x127 0x1 0x00 | ||||||
|  |       write 0x129 0x1 0x00 | ||||||
|  |       write 0x12b 0x1 0x00 | ||||||
|  |       write 0x12d 0x1 0x00 | ||||||
|  |       write 0x12f 0x1 0x00 | ||||||
|  |       write 0x131 0x1 0x00 | ||||||
|  |       write 0x133 0x1 0x00 | ||||||
|  |       write 0x135 0x1 0x00 | ||||||
|  |       write 0x137 0x1 0x00 | ||||||
|  |       write 0x139 0x1 0x00 | ||||||
|  |       write 0xe0007003 0x1 0x00 | ||||||
|  |       EOF | ||||||
|  |       ... | ||||||
|  |       ================================================================= | ||||||
|  |       ==276099==ERROR: AddressSanitizer: heap-use-after-free on address 0x60d000011178 | ||||||
|  |       at pc 0x562cc3b736c7 bp 0x7ffed49dee60 sp 0x7ffed49dee58 | ||||||
|  |       READ of size 8 at 0x60d000011178 thread T0 | ||||||
|  |           #0 0x562cc3b736c6 in virtio_gpu_ctrl_response hw/display/virtio-gpu.c:180:42 | ||||||
|  |           #1 0x562cc3b7c40b in virtio_gpu_ctrl_response_nodata hw/display/virtio-gpu.c:192:5 | ||||||
|  |           #2 0x562cc3b7c40b in virtio_gpu_simple_process_cmd hw/display/virtio-gpu.c:1015:13 | ||||||
|  |           #3 0x562cc3b82873 in virtio_gpu_process_cmdq hw/display/virtio-gpu.c:1050:9 | ||||||
|  |           #4 0x562cc4a85514 in aio_bh_call util/async.c:169:5 | ||||||
|  |           #5 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13 | ||||||
|  |           #6 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5 | ||||||
|  |           #7 0x562cc4a8a2da in aio_ctx_dispatch util/async.c:358:5 | ||||||
|  |           #8 0x7f36840547a8 in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x547a8) | ||||||
|  |           #9 0x562cc4a8b753 in glib_pollfds_poll util/main-loop.c:290:9 | ||||||
|  |           #10 0x562cc4a8b753 in os_host_main_loop_wait util/main-loop.c:313:5 | ||||||
|  |           #11 0x562cc4a8b753 in main_loop_wait util/main-loop.c:592:11 | ||||||
|  |           #12 0x562cc3938186 in qemu_main_loop system/runstate.c:782:9 | ||||||
|  |           #13 0x562cc43b7af5 in qemu_default_main system/main.c:37:14 | ||||||
|  |           #14 0x7f3683a6c189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 | ||||||
|  |           #15 0x7f3683a6c244 in __libc_start_main csu/../csu/libc-start.c:381:3 | ||||||
|  |           #16 0x562cc2a58ac0 in _start (qemu-system-i386+0x231bac0) | ||||||
|  | 
 | ||||||
|  |       0x60d000011178 is located 56 bytes inside of 136-byte region [0x60d000011140,0x60d0000111c8) | ||||||
|  |       freed by thread T0 here: | ||||||
|  |           #0 0x562cc2adb662 in __interceptor_free (qemu-system-i386+0x239e662) | ||||||
|  |           #1 0x562cc3b86b21 in virtio_gpu_reset hw/display/virtio-gpu.c:1524:9 | ||||||
|  |           #2 0x562cc416e20e in virtio_reset hw/virtio/virtio.c:2145:9 | ||||||
|  |           #3 0x562cc37c5644 in virtio_pci_reset hw/virtio/virtio-pci.c:2249:5 | ||||||
|  |           #4 0x562cc4233758 in memory_region_write_accessor system/memory.c:497:5 | ||||||
|  |           #5 0x562cc4232eea in access_with_adjusted_size system/memory.c:573:18 | ||||||
|  | 
 | ||||||
|  |       previously allocated by thread T0 here: | ||||||
|  |           #0 0x562cc2adb90e in malloc (qemu-system-i386+0x239e90e) | ||||||
|  |           #1 0x7f368405a678 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5a678) | ||||||
|  |           #2 0x562cc4163ffc in virtqueue_split_pop hw/virtio/virtio.c:1612:12 | ||||||
|  |           #3 0x562cc4163ffc in virtqueue_pop hw/virtio/virtio.c:1783:16 | ||||||
|  |           #4 0x562cc3b91a95 in virtio_gpu_handle_ctrl hw/display/virtio-gpu.c:1112:15 | ||||||
|  |           #5 0x562cc4a85514 in aio_bh_call util/async.c:169:5 | ||||||
|  |           #6 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13 | ||||||
|  |           #7 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5 | ||||||
|  | 
 | ||||||
|  |       SUMMARY: AddressSanitizer: heap-use-after-free hw/display/virtio-gpu.c:180:42 in virtio_gpu_ctrl_response | ||||||
|  | 
 | ||||||
|  |     With this change, the same reproducer triggers: | ||||||
|  | 
 | ||||||
|  |       qemu-system-i386: warning: Blocked re-entrant IO on MemoryRegion: virtio-pci-common-virtio-gpu at addr: 0x6 | ||||||
|  | 
 | ||||||
|  |     Fixes: CVE-2024-3446 | ||||||
|  |     Cc: qemu-stable@nongnu.org | ||||||
|  |     Reported-by: Alexander Bulekov <alxndr@bu.edu> | ||||||
|  |     Reported-by: Yongkang Jia <kangel@zju.edu.cn> | ||||||
|  |     Reported-by: Xiao Lei <nop.leixiao@gmail.com> | ||||||
|  |     Reported-by: Yiming Tao <taoym@zju.edu.cn> | ||||||
|  |     Buglink: https://bugs.launchpad.net/qemu/+bug/1888606 | ||||||
|  |     Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  |     Acked-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  |     Reviewed-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Message-Id: <20240409105537.18308-3-philmd@linaro.org> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  hw/display/virtio-gpu.c | 6 ++---- | ||||||
|  |  1 file changed, 2 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
 | ||||||
|  | index c28ce1ea72..64fdc18478 100644
 | ||||||
|  | --- a/hw/display/virtio-gpu.c
 | ||||||
|  | +++ b/hw/display/virtio-gpu.c
 | ||||||
|  | @@ -1334,10 +1334,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
 | ||||||
|  |   | ||||||
|  |      g->ctrl_vq = virtio_get_queue(vdev, 0); | ||||||
|  |      g->cursor_vq = virtio_get_queue(vdev, 1); | ||||||
|  | -    g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g,
 | ||||||
|  | -                                     &qdev->mem_reentrancy_guard);
 | ||||||
|  | -    g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g,
 | ||||||
|  | -                                       &qdev->mem_reentrancy_guard);
 | ||||||
|  | +    g->ctrl_bh = virtio_bh_new_guarded(qdev, virtio_gpu_ctrl_bh, g);
 | ||||||
|  | +    g->cursor_bh = virtio_bh_new_guarded(qdev, virtio_gpu_cursor_bh, g);
 | ||||||
|  |      g->reset_bh = qemu_bh_new(virtio_gpu_reset_bh, g); | ||||||
|  |      qemu_cond_init(&g->reset_cond); | ||||||
|  |      QTAILQ_INIT(&g->reslist); | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,86 @@ | |||||||
|  | From 1b62d61c495bf4cd3a819ab8d1ef024d153e0ece Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Thu, 18 Jul 2024 09:40:29 -0400 | ||||||
|  | Subject: [PATCH 3/6] hw/virtio: Introduce virtio_bh_new_guarded() helper | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability | ||||||
|  | RH-Jira: RHEL-32276 | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [3/6] 1cbde7ddb8393b72e2e8d457b5e2d739116567a9 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-32276 | ||||||
|  | CVE: CVE-2024-3446 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit ec0504b989ca61e03636384d3602b7bf07ffe4da | ||||||
|  | Author: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  | Date:   Thu Apr 4 20:56:11 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     hw/virtio: Introduce virtio_bh_new_guarded() helper | ||||||
|  | 
 | ||||||
|  |     Introduce virtio_bh_new_guarded(), similar to qemu_bh_new_guarded() | ||||||
|  |     but using the transport memory guard, instead of the device one | ||||||
|  |     (there can only be one virtio device per virtio bus). | ||||||
|  | 
 | ||||||
|  |     Inspired-by: Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  |     Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  |     Acked-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  |     Reviewed-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Message-Id: <20240409105537.18308-2-philmd@linaro.org> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  hw/virtio/virtio.c         | 10 ++++++++++ | ||||||
|  |  include/hw/virtio/virtio.h |  7 +++++++ | ||||||
|  |  2 files changed, 17 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
 | ||||||
|  | index ea7c079fb0..5ae9c44841 100644
 | ||||||
|  | --- a/hw/virtio/virtio.c
 | ||||||
|  | +++ b/hw/virtio/virtio.c
 | ||||||
|  | @@ -3874,3 +3874,13 @@ static void virtio_register_types(void)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  type_init(virtio_register_types) | ||||||
|  | +
 | ||||||
|  | +QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
 | ||||||
|  | +                                   QEMUBHFunc *cb, void *opaque,
 | ||||||
|  | +                                   const char *name)
 | ||||||
|  | +{
 | ||||||
|  | +    DeviceState *transport = qdev_get_parent_bus(dev)->parent;
 | ||||||
|  | +
 | ||||||
|  | +    return qemu_bh_new_full(cb, opaque, name,
 | ||||||
|  | +                            &transport->mem_reentrancy_guard);
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
 | ||||||
|  | index 8bab9cfb75..731c631a81 100644
 | ||||||
|  | --- a/include/hw/virtio/virtio.h
 | ||||||
|  | +++ b/include/hw/virtio/virtio.h
 | ||||||
|  | @@ -22,6 +22,7 @@
 | ||||||
|  |  #include "standard-headers/linux/virtio_config.h" | ||||||
|  |  #include "standard-headers/linux/virtio_ring.h" | ||||||
|  |  #include "qom/object.h" | ||||||
|  | +#include "block/aio.h"
 | ||||||
|  |   | ||||||
|  |  /* A guest should never accept this.  It implies negotiation is broken. */ | ||||||
|  |  #define VIRTIO_F_BAD_FEATURE		30 | ||||||
|  | @@ -397,4 +398,10 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev)
 | ||||||
|  |  bool virtio_legacy_allowed(VirtIODevice *vdev); | ||||||
|  |  bool virtio_legacy_check_disabled(VirtIODevice *vdev); | ||||||
|  |   | ||||||
|  | +QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
 | ||||||
|  | +                                   QEMUBHFunc *cb, void *opaque,
 | ||||||
|  | +                                   const char *name);
 | ||||||
|  | +#define virtio_bh_new_guarded(dev, cb, opaque) \
 | ||||||
|  | +    virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb)))
 | ||||||
|  | +
 | ||||||
|  |  #endif | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,62 @@ | |||||||
|  | From 2ecbd673a0e2191821ce88128587f709936ad765 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Thu, 18 Jul 2024 09:21:27 -0400 | ||||||
|  | Subject: [PATCH 6/6] hw/virtio/virtio-crypto: Protect from DMA re-entrancy | ||||||
|  |  bugs | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability | ||||||
|  | RH-Jira: RHEL-32276 | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [6/6] 975ac4640fd8e7cbf3820757787ee7b1270173be (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-32276 | ||||||
|  | CVE: CVE-2024-3446 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit f4729ec39ad97a42ceaa7b5697f84f440ea6e5dc | ||||||
|  | Author: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  | Date:   Thu Apr 4 20:56:41 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs | ||||||
|  | 
 | ||||||
|  |     Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() | ||||||
|  |     so the bus and device use the same guard. Otherwise the | ||||||
|  |     DMA-reentrancy protection can be bypassed. | ||||||
|  | 
 | ||||||
|  |     Fixes: CVE-2024-3446 | ||||||
|  |     Cc: qemu-stable@nongnu.org | ||||||
|  |     Suggested-by: Alexander Bulekov <alxndr@bu.edu> | ||||||
|  |     Reviewed-by: Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  |     Acked-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||||||
|  |     Reviewed-by: Michael S. Tsirkin <mst@redhat.com> | ||||||
|  |     Message-Id: <20240409105537.18308-5-philmd@linaro.org> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  hw/virtio/virtio-crypto.c | 4 ++-- | ||||||
|  |  1 file changed, 2 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
 | ||||||
|  | index 1be7bb543c..1741d4aba1 100644
 | ||||||
|  | --- a/hw/virtio/virtio-crypto.c
 | ||||||
|  | +++ b/hw/virtio/virtio-crypto.c
 | ||||||
|  | @@ -817,8 +817,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
 | ||||||
|  |          vcrypto->vqs[i].dataq = | ||||||
|  |                   virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh); | ||||||
|  |          vcrypto->vqs[i].dataq_bh = | ||||||
|  | -                 qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i],
 | ||||||
|  | -                                     &dev->mem_reentrancy_guard);
 | ||||||
|  | +                 virtio_bh_new_guarded(dev, virtio_crypto_dataq_bh,
 | ||||||
|  | +                                       &vcrypto->vqs[i]);
 | ||||||
|  |          vcrypto->vqs[i].vcrypto = vcrypto; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,68 @@ | |||||||
|  | From 3cb587f460ec432f329fb83df034bbb7e79e17aa Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||||||
|  | Subject: [PATCH 2/5] iotests/244: Don't store data-file with protocol in image | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||||||
|  | RH-Jira: RHEL-35616 | ||||||
|  | RH-CVE: CVE-2024-4467 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [2/5] a422cfdba938e1bd857008ccbbddc695011ae0ff | ||||||
|  | 
 | ||||||
|  | commit 92e00dab8be1570b13172353d77d2af44cb4e22b | ||||||
|  | Author: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | Date:   Thu Apr 25 14:49:40 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     iotests/244: Don't store data-file with protocol in image | ||||||
|  | 
 | ||||||
|  |     We want to disable filename parsing for data files because it's too easy | ||||||
|  |     to abuse in malicious image files. Make the test ready for the change by | ||||||
|  |     passing the data file explicitly in command line options. | ||||||
|  | 
 | ||||||
|  |     Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  |     Reviewed-by: Eric Blake <eblake@redhat.com> | ||||||
|  |     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  |     Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  |     Upstream: N/A, embargoed | ||||||
|  |     Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  tests/qemu-iotests/244 | 19 ++++++++++++++++--- | ||||||
|  |  1 file changed, 16 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
 | ||||||
|  | index 3e61fa25bb..bb9cc6512f 100755
 | ||||||
|  | --- a/tests/qemu-iotests/244
 | ||||||
|  | +++ b/tests/qemu-iotests/244
 | ||||||
|  | @@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
 | ||||||
|  |  $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" | ||||||
|  |   | ||||||
|  |  # blkdebug doesn't support copy offloading, so this tests the error path | ||||||
|  | -$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG"
 | ||||||
|  | -$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
 | ||||||
|  | -$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
 | ||||||
|  | +test_img_with_blkdebug="json:{
 | ||||||
|  | +    'driver': 'qcow2',
 | ||||||
|  | +    'file': {
 | ||||||
|  | +        'driver': 'file',
 | ||||||
|  | +        'filename': '$TEST_IMG'
 | ||||||
|  | +    },
 | ||||||
|  | +    'data-file': {
 | ||||||
|  | +        'driver': 'blkdebug',
 | ||||||
|  | +        'image': {
 | ||||||
|  | +            'driver': 'file',
 | ||||||
|  | +            'filename': '$TEST_IMG.data'
 | ||||||
|  | +        }
 | ||||||
|  | +    }
 | ||||||
|  | +}"
 | ||||||
|  | +$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug"
 | ||||||
|  | +$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug"
 | ||||||
|  |   | ||||||
|  |  echo | ||||||
|  |  echo "=== Flushing should flush the data file ===" | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,71 @@ | |||||||
|  | From 59a84673079f9763e9507733e308442397aba703 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||||||
|  | Subject: [PATCH 3/5] iotests/270: Don't store data-file with json: prefix in | ||||||
|  |  image | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||||||
|  | RH-Jira: RHEL-35616 | ||||||
|  | RH-CVE: CVE-2024-4467 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [3/5] ac08690fd3ea3af6e24b2f6a8beedcfe469917a8 | ||||||
|  | 
 | ||||||
|  | commit 705bcc2819ce8e0f8b9d660a93bc48de26413aec | ||||||
|  | Author: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | Date:   Thu Apr 25 14:49:40 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     iotests/270: Don't store data-file with json: prefix in image | ||||||
|  | 
 | ||||||
|  |     We want to disable filename parsing for data files because it's too easy | ||||||
|  |     to abuse in malicious image files. Make the test ready for the change by | ||||||
|  |     passing the data file explicitly in command line options. | ||||||
|  | 
 | ||||||
|  |     Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  |     Reviewed-by: Eric Blake <eblake@redhat.com> | ||||||
|  |     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  |     Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  |     Upstream: N/A, embargoed | ||||||
|  |     Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  tests/qemu-iotests/270 | 14 +++++++++++--- | ||||||
|  |  1 file changed, 11 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270
 | ||||||
|  | index 74352342db..c37b674aa2 100755
 | ||||||
|  | --- a/tests/qemu-iotests/270
 | ||||||
|  | +++ b/tests/qemu-iotests/270
 | ||||||
|  | @@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \
 | ||||||
|  |  # "write" 2G of data without using any space. | ||||||
|  |  # (qemu-img create does not like it, though, because null-co does not | ||||||
|  |  # support image creation.) | ||||||
|  | -$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
 | ||||||
|  | -    "$TEST_IMG"
 | ||||||
|  | +test_img_with_null_data="json:{
 | ||||||
|  | +    'driver': '$IMGFMT',
 | ||||||
|  | +    'file': {
 | ||||||
|  | +        'filename': '$TEST_IMG'
 | ||||||
|  | +    },
 | ||||||
|  | +    'data-file': {
 | ||||||
|  | +        'driver': 'null-co',
 | ||||||
|  | +        'size':'4294967296'
 | ||||||
|  | +    }
 | ||||||
|  | +}"
 | ||||||
|  |   | ||||||
|  |  # This gives us a range of: | ||||||
|  |  #   2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31 | ||||||
|  | @@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
 | ||||||
|  |  # on L2 boundaries, we need large L2 tables; hence the cluster size of | ||||||
|  |  # 2 MB.  (Anything from 256 kB should work, though, because then one L2 | ||||||
|  |  # table covers 8 GB.) | ||||||
|  | -$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io
 | ||||||
|  | +$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io
 | ||||||
|  |   | ||||||
|  |  _check_test_img | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
							
								
								
									
										277
									
								
								SOURCES/kvm-iotests-test-NBD-TLS-iothread.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								SOURCES/kvm-iotests-test-NBD-TLS-iothread.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,277 @@ | |||||||
|  | From a0b12780f3cb97abad0a2c54d185c298d3f589e7 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric Blake <eblake@redhat.com> | ||||||
|  | Date: Fri, 17 May 2024 21:50:15 -0500 | ||||||
|  | Subject: [PATCH 2/3] iotests: test NBD+TLS+iothread | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-MergeRequest: 398: nbd/server: CVE-2024-7409: Avoid use-after-free when closing server | ||||||
|  | RH-Jira: RHEL-52611 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [2/3] f522ff5156086a83a7327c379dd3ccd8b583a421 (ebblake/qemu-kvm) | ||||||
|  | 
 | ||||||
|  | Prevent regressions when using NBD with TLS in the presence of | ||||||
|  | iothreads, adding coverage the fix to qio channels made in the | ||||||
|  | previous patch. | ||||||
|  | 
 | ||||||
|  | The shell function pick_unused_port() was copied from | ||||||
|  | nbdkit.git/tests/functions.sh.in, where it had all authors from Red | ||||||
|  | Hat, agreeing to the resulting relicensing from 2-clause BSD to GPLv2. | ||||||
|  | 
 | ||||||
|  | CC: qemu-stable@nongnu.org | ||||||
|  | CC: "Richard W.M. Jones" <rjones@redhat.com> | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | Message-ID: <20240531180639.1392905-6-eblake@redhat.com> | ||||||
|  | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit a73c99378022ebb785481e84cfe1e81097546268) | ||||||
|  | Jira: https://issues.redhat.com/browse/RHEL-52611 | ||||||
|  | Conflicts: | ||||||
|  | 	tests/qemu-iotests/tests/nbd-tls-iothread{,.out} - drop unknown | ||||||
|  |           "tls-hostname" parameter | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  tests/qemu-iotests/tests/nbd-tls-iothread     | 167 ++++++++++++++++++ | ||||||
|  |  tests/qemu-iotests/tests/nbd-tls-iothread.out |  53 ++++++ | ||||||
|  |  2 files changed, 220 insertions(+) | ||||||
|  |  create mode 100755 tests/qemu-iotests/tests/nbd-tls-iothread | ||||||
|  |  create mode 100644 tests/qemu-iotests/tests/nbd-tls-iothread.out | ||||||
|  | 
 | ||||||
|  | diff --git a/tests/qemu-iotests/tests/nbd-tls-iothread b/tests/qemu-iotests/tests/nbd-tls-iothread
 | ||||||
|  | new file mode 100755 | ||||||
|  | index 0000000000..9e747e2639
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/qemu-iotests/tests/nbd-tls-iothread
 | ||||||
|  | @@ -0,0 +1,167 @@
 | ||||||
|  | +#!/usr/bin/env bash
 | ||||||
|  | +# group: rw quick
 | ||||||
|  | +#
 | ||||||
|  | +# Test of NBD+TLS+iothread
 | ||||||
|  | +#
 | ||||||
|  | +# Copyright (C) 2024 Red Hat, Inc.
 | ||||||
|  | +#
 | ||||||
|  | +# This program is free software; you can redistribute it and/or modify
 | ||||||
|  | +# it under the terms of the GNU General Public License as published by
 | ||||||
|  | +# the Free Software Foundation; either version 2 of the License, or
 | ||||||
|  | +# (at your option) any later version.
 | ||||||
|  | +#
 | ||||||
|  | +# This program is distributed in the hope that it will be useful,
 | ||||||
|  | +# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||||||
|  | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | ||||||
|  | +# GNU General Public License for more details.
 | ||||||
|  | +#
 | ||||||
|  | +# You should have received a copy of the GNU General Public License
 | ||||||
|  | +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
|  | +#
 | ||||||
|  | +
 | ||||||
|  | +# creator
 | ||||||
|  | +owner=eblake@redhat.com
 | ||||||
|  | +
 | ||||||
|  | +seq=`basename $0`
 | ||||||
|  | +echo "QA output created by $seq"
 | ||||||
|  | +
 | ||||||
|  | +status=1    # failure is the default!
 | ||||||
|  | +
 | ||||||
|  | +_cleanup()
 | ||||||
|  | +{
 | ||||||
|  | +    _cleanup_qemu
 | ||||||
|  | +    _cleanup_test_img
 | ||||||
|  | +    rm -f "$dst_image"
 | ||||||
|  | +    tls_x509_cleanup
 | ||||||
|  | +}
 | ||||||
|  | +trap "_cleanup; exit \$status" 0 1 2 3 15
 | ||||||
|  | +
 | ||||||
|  | +# get standard environment, filters and checks
 | ||||||
|  | +cd ..
 | ||||||
|  | +. ./common.rc
 | ||||||
|  | +. ./common.filter
 | ||||||
|  | +. ./common.qemu
 | ||||||
|  | +. ./common.tls
 | ||||||
|  | +. ./common.nbd
 | ||||||
|  | +
 | ||||||
|  | +_supported_fmt qcow2  # Hardcoded to qcow2 command line and QMP below
 | ||||||
|  | +_supported_proto file
 | ||||||
|  | +
 | ||||||
|  | +# pick_unused_port
 | ||||||
|  | +#
 | ||||||
|  | +# Picks and returns an "unused" port, setting the global variable
 | ||||||
|  | +# $port.
 | ||||||
|  | +#
 | ||||||
|  | +# This is inherently racy, but we need it because qemu does not currently
 | ||||||
|  | +# permit NBD+TLS over a Unix domain socket
 | ||||||
|  | +pick_unused_port ()
 | ||||||
|  | +{
 | ||||||
|  | +    if ! (ss --version) >/dev/null 2>&1; then
 | ||||||
|  | +        _notrun "ss utility required, skipped this test"
 | ||||||
|  | +    fi
 | ||||||
|  | +
 | ||||||
|  | +    # Start at a random port to make it less likely that two parallel
 | ||||||
|  | +    # tests will conflict.
 | ||||||
|  | +    port=$(( 50000 + (RANDOM%15000) ))
 | ||||||
|  | +    while ss -ltn | grep -sqE ":$port\b"; do
 | ||||||
|  | +        ((port++))
 | ||||||
|  | +        if [ $port -eq 65000 ]; then port=50000; fi
 | ||||||
|  | +    done
 | ||||||
|  | +    echo picked unused port
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +tls_x509_init
 | ||||||
|  | +
 | ||||||
|  | +size=1G
 | ||||||
|  | +DST_IMG="$TEST_DIR/dst.qcow2"
 | ||||||
|  | +
 | ||||||
|  | +echo
 | ||||||
|  | +echo "== preparing TLS creds and spare port =="
 | ||||||
|  | +
 | ||||||
|  | +pick_unused_port
 | ||||||
|  | +tls_x509_create_root_ca "ca1"
 | ||||||
|  | +tls_x509_create_server "ca1" "server1"
 | ||||||
|  | +tls_x509_create_client "ca1" "client1"
 | ||||||
|  | +tls_obj_base=tls-creds-x509,id=tls0,verify-peer=true,dir="${tls_dir}"
 | ||||||
|  | +
 | ||||||
|  | +echo
 | ||||||
|  | +echo "== preparing image =="
 | ||||||
|  | +
 | ||||||
|  | +_make_test_img $size
 | ||||||
|  | +$QEMU_IMG create -f qcow2 "$DST_IMG" $size | _filter_img_create
 | ||||||
|  | +
 | ||||||
|  | +echo
 | ||||||
|  | +echo === Starting Src QEMU ===
 | ||||||
|  | +echo
 | ||||||
|  | +
 | ||||||
|  | +_launch_qemu -machine q35 \
 | ||||||
|  | +    -object iothread,id=iothread0 \
 | ||||||
|  | +    -object "${tls_obj_base}"/client1,endpoint=client \
 | ||||||
|  | +    -device '{"driver":"pcie-root-port", "id":"root0", "multifunction":true,
 | ||||||
|  | +              "bus":"pcie.0"}' \
 | ||||||
|  | +    -device '{"driver":"virtio-scsi-pci", "id":"virtio_scsi_pci0",
 | ||||||
|  | +              "bus":"root0", "iothread":"iothread0"}' \
 | ||||||
|  | +    -device '{"driver":"scsi-hd", "id":"image1", "drive":"drive_image1",
 | ||||||
|  | +              "bus":"virtio_scsi_pci0.0"}' \
 | ||||||
|  | +    -blockdev '{"driver":"file", "cache":{"direct":true, "no-flush":false},
 | ||||||
|  | +                "filename":"'"$TEST_IMG"'", "node-name":"drive_sys1"}' \
 | ||||||
|  | +    -blockdev '{"driver":"qcow2", "node-name":"drive_image1",
 | ||||||
|  | +                "file":"drive_sys1"}'
 | ||||||
|  | +h1=$QEMU_HANDLE
 | ||||||
|  | +_send_qemu_cmd $h1 '{"execute": "qmp_capabilities"}' 'return'
 | ||||||
|  | +
 | ||||||
|  | +echo
 | ||||||
|  | +echo === Starting Dst VM2 ===
 | ||||||
|  | +echo
 | ||||||
|  | +
 | ||||||
|  | +_launch_qemu -machine q35 \
 | ||||||
|  | +    -object iothread,id=iothread0 \
 | ||||||
|  | +    -object "${tls_obj_base}"/server1,endpoint=server \
 | ||||||
|  | +    -device '{"driver":"pcie-root-port", "id":"root0", "multifunction":true,
 | ||||||
|  | +              "bus":"pcie.0"}' \
 | ||||||
|  | +    -device '{"driver":"virtio-scsi-pci", "id":"virtio_scsi_pci0",
 | ||||||
|  | +              "bus":"root0", "iothread":"iothread0"}' \
 | ||||||
|  | +    -device '{"driver":"scsi-hd", "id":"image1", "drive":"drive_image1",
 | ||||||
|  | +              "bus":"virtio_scsi_pci0.0"}' \
 | ||||||
|  | +    -blockdev '{"driver":"file", "cache":{"direct":true, "no-flush":false},
 | ||||||
|  | +                "filename":"'"$DST_IMG"'", "node-name":"drive_sys1"}' \
 | ||||||
|  | +    -blockdev '{"driver":"qcow2", "node-name":"drive_image1",
 | ||||||
|  | +                "file":"drive_sys1"}' \
 | ||||||
|  | +    -incoming defer
 | ||||||
|  | +h2=$QEMU_HANDLE
 | ||||||
|  | +_send_qemu_cmd $h2 '{"execute": "qmp_capabilities"}' 'return'
 | ||||||
|  | +
 | ||||||
|  | +echo
 | ||||||
|  | +echo === Dst VM: Enable NBD server for incoming storage migration ===
 | ||||||
|  | +echo
 | ||||||
|  | +
 | ||||||
|  | +_send_qemu_cmd $h2 '{"execute": "nbd-server-start", "arguments":
 | ||||||
|  | +    {"addr": {"type": "inet", "data": {"host": "127.0.0.1", "port": "'$port'"}},
 | ||||||
|  | +              "tls-creds": "tls0"}}' '{"return": {}}' | sed "s/\"$port\"/PORT/g"
 | ||||||
|  | +_send_qemu_cmd $h2 '{"execute": "block-export-add", "arguments":
 | ||||||
|  | +    {"node-name": "drive_image1", "type": "nbd", "writable": true,
 | ||||||
|  | +      "id": "drive_image1"}}' '{"return": {}}'
 | ||||||
|  | +
 | ||||||
|  | +echo
 | ||||||
|  | +echo === Src VM: Mirror to dst NBD for outgoing storage migration ===
 | ||||||
|  | +echo
 | ||||||
|  | +
 | ||||||
|  | +_send_qemu_cmd $h1 '{"execute": "blockdev-add", "arguments":
 | ||||||
|  | +    {"node-name": "mirror", "driver": "nbd",
 | ||||||
|  | +     "server": {"type": "inet", "host": "127.0.0.1", "port": "'$port'"},
 | ||||||
|  | +     "export": "drive_image1", "tls-creds": "tls0"}}' '{"return": {}}' | sed "s/\"$port\"/PORT/g"
 | ||||||
|  | +_send_qemu_cmd $h1 '{"execute": "blockdev-mirror", "arguments":
 | ||||||
|  | +    {"sync": "full", "device": "drive_image1", "target": "mirror",
 | ||||||
|  | +     "job-id": "drive_image1_53"}}' '{"return": {}}'
 | ||||||
|  | +_timed_wait_for $h1 '"ready"'
 | ||||||
|  | +
 | ||||||
|  | +echo
 | ||||||
|  | +echo === Cleaning up ===
 | ||||||
|  | +echo
 | ||||||
|  | +
 | ||||||
|  | +_send_qemu_cmd $h1 '{"execute":"quit"}' ''
 | ||||||
|  | +_send_qemu_cmd $h2 '{"execute":"quit"}' ''
 | ||||||
|  | +
 | ||||||
|  | +echo "*** done"
 | ||||||
|  | +rm -f $seq.full
 | ||||||
|  | +status=0
 | ||||||
|  | diff --git a/tests/qemu-iotests/tests/nbd-tls-iothread.out b/tests/qemu-iotests/tests/nbd-tls-iothread.out
 | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000000..a3899fd2d7
 | ||||||
|  | --- /dev/null
 | ||||||
|  | +++ b/tests/qemu-iotests/tests/nbd-tls-iothread.out
 | ||||||
|  | @@ -0,0 +1,53 @@
 | ||||||
|  | +QA output created by nbd-tls-iothread
 | ||||||
|  | +
 | ||||||
|  | +== preparing TLS creds and spare port ==
 | ||||||
|  | +picked unused port
 | ||||||
|  | +Generating a self signed certificate...
 | ||||||
|  | +Generating a signed certificate...
 | ||||||
|  | +Generating a signed certificate...
 | ||||||
|  | +
 | ||||||
|  | +== preparing image ==
 | ||||||
|  | +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
 | ||||||
|  | +Formatting 'TEST_DIR/dst.IMGFMT', fmt=IMGFMT size=1073741824
 | ||||||
|  | +
 | ||||||
|  | +=== Starting Src QEMU ===
 | ||||||
|  | +
 | ||||||
|  | +{"execute": "qmp_capabilities"}
 | ||||||
|  | +{"return": {}}
 | ||||||
|  | +
 | ||||||
|  | +=== Starting Dst VM2 ===
 | ||||||
|  | +
 | ||||||
|  | +{"execute": "qmp_capabilities"}
 | ||||||
|  | +{"return": {}}
 | ||||||
|  | +
 | ||||||
|  | +=== Dst VM: Enable NBD server for incoming storage migration ===
 | ||||||
|  | +
 | ||||||
|  | +{"execute": "nbd-server-start", "arguments":
 | ||||||
|  | +    {"addr": {"type": "inet", "data": {"host": "127.0.0.1", "port": PORT}},
 | ||||||
|  | +              "tls-creds": "tls0"}}
 | ||||||
|  | +{"return": {}}
 | ||||||
|  | +{"execute": "block-export-add", "arguments":
 | ||||||
|  | +    {"node-name": "drive_image1", "type": "nbd", "writable": true,
 | ||||||
|  | +      "id": "drive_image1"}}
 | ||||||
|  | +{"return": {}}
 | ||||||
|  | +
 | ||||||
|  | +=== Src VM: Mirror to dst NBD for outgoing storage migration ===
 | ||||||
|  | +
 | ||||||
|  | +{"execute": "blockdev-add", "arguments":
 | ||||||
|  | +    {"node-name": "mirror", "driver": "nbd",
 | ||||||
|  | +     "server": {"type": "inet", "host": "127.0.0.1", "port": PORT},
 | ||||||
|  | +     "export": "drive_image1", "tls-creds": "tls0"}}
 | ||||||
|  | +{"return": {}}
 | ||||||
|  | +{"execute": "blockdev-mirror", "arguments":
 | ||||||
|  | +    {"sync": "full", "device": "drive_image1", "target": "mirror",
 | ||||||
|  | +     "job-id": "drive_image1_53"}}
 | ||||||
|  | +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "drive_image1_53"}}
 | ||||||
|  | +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "drive_image1_53"}}
 | ||||||
|  | +{"return": {}}
 | ||||||
|  | +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "drive_image1_53"}}
 | ||||||
|  | +
 | ||||||
|  | +=== Cleaning up ===
 | ||||||
|  | +
 | ||||||
|  | +{"execute":"quit"}
 | ||||||
|  | +{"execute":"quit"}
 | ||||||
|  | +*** done
 | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,101 @@ | |||||||
|  | From 676438ff8c42323c3e5d9e7eeeb1b3367999136c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric Blake <eblake@redhat.com> | ||||||
|  | Date: Thu, 22 Aug 2024 09:35:29 -0500 | ||||||
|  | Subject: [PATCH 3/3] nbd/server: CVE-2024-7409: Avoid use-after-free when | ||||||
|  |  closing server | ||||||
|  | 
 | ||||||
|  | RH-Author: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-MergeRequest: 398: nbd/server: CVE-2024-7409: Avoid use-after-free when closing server | ||||||
|  | RH-Jira: RHEL-52611 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [3/3] 1ee35a40ded067a085bf6fcafa690b40976d7f2d (ebblake/qemu-kvm) | ||||||
|  | 
 | ||||||
|  | Commit 3e7ef738 plugged the use-after-free of the global nbd_server | ||||||
|  | object, but overlooked a use-after-free of nbd_server->listener. | ||||||
|  | Although this race is harder to hit, notice that our shutdown path | ||||||
|  | first drops the reference count of nbd_server->listener, then triggers | ||||||
|  | actions that can result in a pending client reaching the | ||||||
|  | nbd_blockdev_client_closed() callback, which in turn calls | ||||||
|  | qio_net_listener_set_client_func on a potentially stale object. | ||||||
|  | 
 | ||||||
|  | If we know we don't want any more clients to connect, and have already | ||||||
|  | told the listener socket to shut down, then we should not be trying to | ||||||
|  | update the listener socket's associated function. | ||||||
|  | 
 | ||||||
|  | Reproducer: | ||||||
|  | 
 | ||||||
|  | > #!/usr/bin/python3
 | ||||||
|  | > | ||||||
|  | > import os
 | ||||||
|  | > from threading import Thread
 | ||||||
|  | > | ||||||
|  | > def start_stop():
 | ||||||
|  | >     while 1:
 | ||||||
|  | >         os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-start",
 | ||||||
|  | +"arguments":{"addr":{"type":"unix","data":{"path":"/tmp/nbd-sock"}}}}\'')
 | ||||||
|  | >         os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-stop"}\'')
 | ||||||
|  | > | ||||||
|  | > def nbd_list():
 | ||||||
|  | >     while 1:
 | ||||||
|  | >         os.system('/path/to/build/qemu-nbd -L -k /tmp/nbd-sock')
 | ||||||
|  | > | ||||||
|  | > def test():
 | ||||||
|  | >     sst = Thread(target=start_stop)
 | ||||||
|  | >     sst.start()
 | ||||||
|  | >     nlt = Thread(target=nbd_list)
 | ||||||
|  | >     nlt.start()
 | ||||||
|  | > | ||||||
|  | >     sst.join()
 | ||||||
|  | >     nlt.join()
 | ||||||
|  | > | ||||||
|  | > test()
 | ||||||
|  | 
 | ||||||
|  | Fixes: CVE-2024-7409 | ||||||
|  | Fixes: 3e7ef738c8 ("nbd/server: CVE-2024-7409: Close stray clients at server-stop") | ||||||
|  | CC: qemu-stable@nongnu.org | ||||||
|  | Reported-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com> | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | Message-ID: <20240822143617.800419-2-eblake@redhat.com> | ||||||
|  | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 3874f5f73c441c52f1c699c848d463b0eda01e4c) | ||||||
|  | Jira: https://issues.redhat.com/browse/RHEL-52611 | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  blockdev-nbd.c | 12 ++++++++---- | ||||||
|  |  1 file changed, 8 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/blockdev-nbd.c b/blockdev-nbd.c
 | ||||||
|  | index 87839c180b..b5d55e2518 100644
 | ||||||
|  | --- a/blockdev-nbd.c
 | ||||||
|  | +++ b/blockdev-nbd.c
 | ||||||
|  | @@ -87,10 +87,13 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
 | ||||||
|  |   | ||||||
|  |  static void nbd_update_server_watch(NBDServerData *s) | ||||||
|  |  { | ||||||
|  | -    if (!s->max_connections || s->connections < s->max_connections) {
 | ||||||
|  | -        qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, NULL);
 | ||||||
|  | -    } else {
 | ||||||
|  | -        qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
 | ||||||
|  | +    if (s->listener) {
 | ||||||
|  | +        if (!s->max_connections || s->connections < s->max_connections) {
 | ||||||
|  | +            qio_net_listener_set_client_func(s->listener, nbd_accept, NULL,
 | ||||||
|  | +                                             NULL);
 | ||||||
|  | +        } else {
 | ||||||
|  | +            qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
 | ||||||
|  | +        }
 | ||||||
|  |      } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -108,6 +111,7 @@ static void nbd_server_free(NBDServerData *server)
 | ||||||
|  |       */ | ||||||
|  |      qio_net_listener_disconnect(server->listener); | ||||||
|  |      object_unref(OBJECT(server->listener)); | ||||||
|  | +    server->listener = NULL;
 | ||||||
|  |      QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) { | ||||||
|  |          qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH, | ||||||
|  |                               NULL); | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,187 @@ | |||||||
|  | From adfddc25c82576458442f61efb913e44d83bcbd0 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric Blake <eblake@redhat.com> | ||||||
|  | Date: Tue, 6 Aug 2024 13:53:00 -0500 | ||||||
|  | Subject: [PATCH 2/5] nbd/server: CVE-2024-7409: Cap default max-connections to | ||||||
|  |  100 | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z] | ||||||
|  | RH-Jira: RHEL-52611 | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Acked-by: Richard W.M. Jones <rjones@redhat.com> | ||||||
|  | RH-Commit: [2/4] 1f5d88d5644c46cbb957778254a993930b9d86dc (ebblake/qemu-kvm) | ||||||
|  | 
 | ||||||
|  | Allowing an unlimited number of clients to any web service is a recipe | ||||||
|  | for a rudimentary denial of service attack: the client merely needs to | ||||||
|  | open lots of sockets without closing them, until qemu no longer has | ||||||
|  | any more fds available to allocate. | ||||||
|  | 
 | ||||||
|  | For qemu-nbd, we default to allowing only 1 connection unless more are | ||||||
|  | explicitly asked for (-e or --shared); this was historically picked as | ||||||
|  | a nice default (without an explicit -t, a non-persistent qemu-nbd goes | ||||||
|  | away after a client disconnects, without needing any additional | ||||||
|  | follow-up commands), and we are not going to change that interface now | ||||||
|  | (besides, someday we want to point people towards qemu-storage-daemon | ||||||
|  | instead of qemu-nbd). | ||||||
|  | 
 | ||||||
|  | But for qemu proper, and the newer qemu-storage-daemon, the QMP | ||||||
|  | nbd-server-start command has historically had a default of unlimited | ||||||
|  | number of connections, in part because unlike qemu-nbd it is | ||||||
|  | inherently persistent until nbd-server-stop.  Allowing multiple client | ||||||
|  | sockets is particularly useful for clients that can take advantage of | ||||||
|  | MULTI_CONN (creating parallel sockets to increase throughput), | ||||||
|  | although known clients that do so (such as libnbd's nbdcopy) typically | ||||||
|  | use only 8 or 16 connections (the benefits of scaling diminish once | ||||||
|  | more sockets are competing for kernel attention).  Picking a number | ||||||
|  | large enough for typical use cases, but not unlimited, makes it | ||||||
|  | slightly harder for a malicious client to perform a denial of service | ||||||
|  | merely by opening lots of connections withot progressing through the | ||||||
|  | handshake. | ||||||
|  | 
 | ||||||
|  | This change does not eliminate CVE-2024-7409 on its own, but reduces | ||||||
|  | the chance for fd exhaustion or unlimited memory usage as an attack | ||||||
|  | surface.  On the other hand, by itself, it makes it more obvious that | ||||||
|  | with a finite limit, we have the problem of an unauthenticated client | ||||||
|  | holding 100 fds opened as a way to block out a legitimate client from | ||||||
|  | being able to connect; thus, later patches will further add timeouts | ||||||
|  | to reject clients that are not making progress. | ||||||
|  | 
 | ||||||
|  | This is an INTENTIONAL change in behavior, and will break any client | ||||||
|  | of nbd-server-start that was not passing an explicit max-connections | ||||||
|  | parameter, yet expects more than 100 simultaneous connections.  We are | ||||||
|  | not aware of any such client (as stated above, most clients aware of | ||||||
|  | MULTI_CONN get by just fine on 8 or 16 connections, and probably cope | ||||||
|  | with later connections failing by relying on the earlier connections; | ||||||
|  | libvirt has not yet been passing max-connections, but generally | ||||||
|  | creates NBD servers with the intent for a single client for the sake | ||||||
|  | of live storage migration; meanwhile, the KubeSAN project anticipates | ||||||
|  | a large cluster sharing multiple clients [up to 8 per node, and up to | ||||||
|  | 100 nodes in a cluster], but it currently uses qemu-nbd with an | ||||||
|  | explicit --shared=0 rather than qemu-storage-daemon with | ||||||
|  | nbd-server-start). | ||||||
|  | 
 | ||||||
|  | We considered using a deprecation period (declare that omitting | ||||||
|  | max-parameters is deprecated, and make it mandatory in 3 releases - | ||||||
|  | then we don't need to pick an arbitrary default); that has zero risk | ||||||
|  | of breaking any apps that accidentally depended on more than 100 | ||||||
|  | connections, and where such breakage might not be noticed under unit | ||||||
|  | testing but only under the larger loads of production usage.  But it | ||||||
|  | does not close the denial-of-service hole until far into the future, | ||||||
|  | and requires all apps to change to add the parameter even if 100 was | ||||||
|  | good enough.  It also has a drawback that any app (like libvirt) that | ||||||
|  | is accidentally relying on an unlimited default should seriously | ||||||
|  | consider their own CVE now, at which point they are going to change to | ||||||
|  | pass explicit max-connections sooner than waiting for 3 qemu releases. | ||||||
|  | Finally, if our changed default breaks an app, that app can always | ||||||
|  | pass in an explicit max-parameters with a larger value. | ||||||
|  | 
 | ||||||
|  | It is also intentional that the HMP interface to nbd-server-start is | ||||||
|  | not changed to expose max-connections (any client needing to fine-tune | ||||||
|  | things should be using QMP). | ||||||
|  | 
 | ||||||
|  | Suggested-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | Message-ID: <20240807174943.771624-12-eblake@redhat.com> | ||||||
|  | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | [ericb: Expand commit message to summarize Dan's argument for why we | ||||||
|  | break corner-case back-compat behavior without a deprecation period] | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit c8a76dbd90c2f48df89b75bef74917f90a59b623) | ||||||
|  | Conflicts: | ||||||
|  | 	qapi/block-export.json - context (no multi-conn, older format) | ||||||
|  | Jira: https://issues.redhat.com/browse/RHEL-52611 | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  block/monitor/block-hmp-cmds.c | 3 ++- | ||||||
|  |  blockdev-nbd.c                 | 8 ++++++++ | ||||||
|  |  include/block/nbd.h            | 7 +++++++ | ||||||
|  |  qapi/block-export.json         | 4 ++-- | ||||||
|  |  4 files changed, 19 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
 | ||||||
|  | index 2ac4aedfff..32a666b5dc 100644
 | ||||||
|  | --- a/block/monitor/block-hmp-cmds.c
 | ||||||
|  | +++ b/block/monitor/block-hmp-cmds.c
 | ||||||
|  | @@ -411,7 +411,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
 | ||||||
|  |          goto exit; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    nbd_server_start(addr, NULL, NULL, 0, &local_err);
 | ||||||
|  | +    nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS,
 | ||||||
|  | +                     &local_err);
 | ||||||
|  |      qapi_free_SocketAddress(addr); | ||||||
|  |      if (local_err != NULL) { | ||||||
|  |          goto exit; | ||||||
|  | diff --git a/blockdev-nbd.c b/blockdev-nbd.c
 | ||||||
|  | index b9e8dc78f3..4bd90bac16 100644
 | ||||||
|  | --- a/blockdev-nbd.c
 | ||||||
|  | +++ b/blockdev-nbd.c
 | ||||||
|  | @@ -171,6 +171,10 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
 | ||||||
|  |   | ||||||
|  |  void nbd_server_start_options(NbdServerOptions *arg, Error **errp) | ||||||
|  |  { | ||||||
|  | +    if (!arg->has_max_connections) {
 | ||||||
|  | +        arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  |      nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, | ||||||
|  |                       arg->max_connections, errp); | ||||||
|  |  } | ||||||
|  | @@ -183,6 +187,10 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
 | ||||||
|  |  { | ||||||
|  |      SocketAddress *addr_flat = socket_address_flatten(addr); | ||||||
|  |   | ||||||
|  | +    if (!has_max_connections) {
 | ||||||
|  | +        max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  |      nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp); | ||||||
|  |      qapi_free_SocketAddress(addr_flat); | ||||||
|  |  } | ||||||
|  | diff --git a/include/block/nbd.h b/include/block/nbd.h
 | ||||||
|  | index b71a297249..a31c34a8a6 100644
 | ||||||
|  | --- a/include/block/nbd.h
 | ||||||
|  | +++ b/include/block/nbd.h
 | ||||||
|  | @@ -33,6 +33,13 @@ extern const BlockExportDriver blk_exp_nbd;
 | ||||||
|  |   */ | ||||||
|  |  #define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10 | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at
 | ||||||
|  | + * once; must be large enough to allow a MULTI_CONN-aware client like
 | ||||||
|  | + * nbdcopy to create its typical number of 8-16 sockets.
 | ||||||
|  | + */
 | ||||||
|  | +#define NBD_DEFAULT_MAX_CONNECTIONS 100
 | ||||||
|  | +
 | ||||||
|  |  /* Handshake phase structs - this struct is passed on the wire */ | ||||||
|  |   | ||||||
|  |  struct NBDOption { | ||||||
|  | diff --git a/qapi/block-export.json b/qapi/block-export.json
 | ||||||
|  | index c1b92ce1c1..181d7238fe 100644
 | ||||||
|  | --- a/qapi/block-export.json
 | ||||||
|  | +++ b/qapi/block-export.json
 | ||||||
|  | @@ -21,7 +21,7 @@
 | ||||||
|  |  #             recreated on the fly while the NBD server is active. | ||||||
|  |  #             If missing, it will default to denying access (since 4.0). | ||||||
|  |  # @max-connections: The maximum number of connections to allow at the same | ||||||
|  | -#                   time, 0 for unlimited. (since 5.2; default: 0)
 | ||||||
|  | +#                   time, 0 for unlimited. (since 5.2; default: 100)
 | ||||||
|  |  # | ||||||
|  |  # Since: 4.2 | ||||||
|  |  ## | ||||||
|  | @@ -50,7 +50,7 @@
 | ||||||
|  |  #             recreated on the fly while the NBD server is active. | ||||||
|  |  #             If missing, it will default to denying access (since 4.0). | ||||||
|  |  # @max-connections: The maximum number of connections to allow at the same | ||||||
|  | -#                   time, 0 for unlimited. (since 5.2; default: 0)
 | ||||||
|  | +#                   time, 0 for unlimited. (since 5.2; default: 100)
 | ||||||
|  |  # | ||||||
|  |  # Returns: error if the server is already running. | ||||||
|  |  # | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,180 @@ | |||||||
|  | From 4ab086cdf9a5842c49f3fe59baff1747d863b97a Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric Blake <eblake@redhat.com> | ||||||
|  | Date: Wed, 7 Aug 2024 12:23:13 -0500 | ||||||
|  | Subject: [PATCH 4/5] nbd/server: CVE-2024-7409: Close stray clients at | ||||||
|  |  server-stop | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z] | ||||||
|  | RH-Jira: RHEL-52611 | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Acked-by: Richard W.M. Jones <rjones@redhat.com> | ||||||
|  | RH-Commit: [4/4] 92a20764dbee3cf94181cab412d90cbf92b4a417 (ebblake/qemu-kvm) | ||||||
|  | 
 | ||||||
|  | A malicious client can attempt to connect to an NBD server, and then | ||||||
|  | intentionally delay progress in the handshake, including if it does | ||||||
|  | not know the TLS secrets.  Although the previous two patches reduce | ||||||
|  | this behavior by capping the default max-connections parameter and | ||||||
|  | killing slow clients, they did not eliminate the possibility of a | ||||||
|  | client waiting to close the socket until after the QMP nbd-server-stop | ||||||
|  | command is executed, at which point qemu would SEGV when trying to | ||||||
|  | dereference the NULL nbd_server global which is no longer present. | ||||||
|  | This amounts to a denial of service attack.  Worse, if another NBD | ||||||
|  | server is started before the malicious client disconnects, I cannot | ||||||
|  | rule out additional adverse effects when the old client interferes | ||||||
|  | with the connection count of the new server (although the most likely | ||||||
|  | is a crash due to an assertion failure when checking | ||||||
|  | nbd_server->connections > 0). | ||||||
|  | 
 | ||||||
|  | For environments without this patch, the CVE can be mitigated by | ||||||
|  | ensuring (such as via a firewall) that only trusted clients can | ||||||
|  | connect to an NBD server.  Note that using frameworks like libvirt | ||||||
|  | that ensure that TLS is used and that nbd-server-stop is not executed | ||||||
|  | while any trusted clients are still connected will only help if there | ||||||
|  | is also no possibility for an untrusted client to open a connection | ||||||
|  | but then stall on the NBD handshake. | ||||||
|  | 
 | ||||||
|  | Given the previous patches, it would be possible to guarantee that no | ||||||
|  | clients remain connected by having nbd-server-stop sleep for longer | ||||||
|  | than the default handshake deadline before finally freeing the global | ||||||
|  | nbd_server object, but that could make QMP non-responsive for a long | ||||||
|  | time.  So intead, this patch fixes the problem by tracking all client | ||||||
|  | sockets opened while the server is running, and forcefully closing any | ||||||
|  | such sockets remaining without a completed handshake at the time of | ||||||
|  | nbd-server-stop, then waiting until the coroutines servicing those | ||||||
|  | sockets notice the state change.  nbd-server-stop now has a second | ||||||
|  | AIO_WAIT_WHILE_UNLOCKED (the first is indirectly through the | ||||||
|  | blk_exp_close_all_type() that disconnects all clients that completed | ||||||
|  | handshakes), but forced socket shutdown is enough to progress the | ||||||
|  | coroutines and quickly tear down all clients before the server is | ||||||
|  | freed, thus finally fixing the CVE. | ||||||
|  | 
 | ||||||
|  | This patch relies heavily on the fact that nbd/server.c guarantees | ||||||
|  | that it only calls nbd_blockdev_client_closed() from the main loop | ||||||
|  | (see the assertion in nbd_client_put() and the hoops used in | ||||||
|  | nbd_client_put_nonzero() to achieve that); if we did not have that | ||||||
|  | guarantee, we would also need a mutex protecting our accesses of the | ||||||
|  | list of connections to survive re-entrancy from independent iothreads. | ||||||
|  | 
 | ||||||
|  | Although I did not actually try to test old builds, it looks like this | ||||||
|  | problem has existed since at least commit 862172f45c (v2.12.0, 2017) - | ||||||
|  | even back when that patch started using a QIONetListener to handle | ||||||
|  | listening on multiple sockets, nbd_server_free() was already unaware | ||||||
|  | that the nbd_blockdev_client_closed callback can be reached later by a | ||||||
|  | client thread that has not completed handshakes (and therefore the | ||||||
|  | client's socket never got added to the list closed in | ||||||
|  | nbd_export_close_all), despite that patch intentionally tearing down | ||||||
|  | the QIONetListener to prevent new clients. | ||||||
|  | 
 | ||||||
|  | Reported-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com> | ||||||
|  | Fixes: CVE-2024-7409 | ||||||
|  | CC: qemu-stable@nongnu.org | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | Message-ID: <20240807174943.771624-14-eblake@redhat.com> | ||||||
|  | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 3e7ef738c8462c45043a1d39f702a0990406a3b3) | ||||||
|  | Conflicts: | ||||||
|  |  - blockdev-nbd.c: | ||||||
|  |    - qemu_in_main_thread() not backported, but only used in assertions so | ||||||
|  |      safe to drop | ||||||
|  |    - AIO_WAIT_WHILE_UNLOCKED() not backported, use AIO_WAIT_WHILE() like | ||||||
|  |      blk_exp_close_all_type() | ||||||
|  | Jira: https://issues.redhat.com/browse/RHEL-52611 | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  blockdev-nbd.c | 35 ++++++++++++++++++++++++++++++++++- | ||||||
|  |  1 file changed, 34 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/blockdev-nbd.c b/blockdev-nbd.c
 | ||||||
|  | index 4bd90bac16..87839c180b 100644
 | ||||||
|  | --- a/blockdev-nbd.c
 | ||||||
|  | +++ b/blockdev-nbd.c
 | ||||||
|  | @@ -21,12 +21,18 @@
 | ||||||
|  |  #include "io/channel-socket.h" | ||||||
|  |  #include "io/net-listener.h" | ||||||
|  |   | ||||||
|  | +typedef struct NBDConn {
 | ||||||
|  | +    QIOChannelSocket *cioc;
 | ||||||
|  | +    QLIST_ENTRY(NBDConn) next;
 | ||||||
|  | +} NBDConn;
 | ||||||
|  | +
 | ||||||
|  |  typedef struct NBDServerData { | ||||||
|  |      QIONetListener *listener; | ||||||
|  |      QCryptoTLSCreds *tlscreds; | ||||||
|  |      char *tlsauthz; | ||||||
|  |      uint32_t max_connections; | ||||||
|  |      uint32_t connections; | ||||||
|  | +    QLIST_HEAD(, NBDConn) conns;
 | ||||||
|  |  } NBDServerData; | ||||||
|  |   | ||||||
|  |  static NBDServerData *nbd_server; | ||||||
|  | @@ -46,6 +52,14 @@ bool nbd_server_is_running(void)
 | ||||||
|  |   | ||||||
|  |  static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) | ||||||
|  |  { | ||||||
|  | +    NBDConn *conn = nbd_client_owner(client);
 | ||||||
|  | +
 | ||||||
|  | +    assert(nbd_server);
 | ||||||
|  | +
 | ||||||
|  | +    object_unref(OBJECT(conn->cioc));
 | ||||||
|  | +    QLIST_REMOVE(conn, next);
 | ||||||
|  | +    g_free(conn);
 | ||||||
|  | +
 | ||||||
|  |      nbd_client_put(client); | ||||||
|  |      assert(nbd_server->connections > 0); | ||||||
|  |      nbd_server->connections--; | ||||||
|  | @@ -55,14 +69,20 @@ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
 | ||||||
|  |  static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, | ||||||
|  |                         gpointer opaque) | ||||||
|  |  { | ||||||
|  | +    NBDConn *conn = g_new0(NBDConn, 1);
 | ||||||
|  | +
 | ||||||
|  | +    assert(nbd_server);
 | ||||||
|  |      nbd_server->connections++; | ||||||
|  | +    object_ref(OBJECT(cioc));
 | ||||||
|  | +    conn->cioc = cioc;
 | ||||||
|  | +    QLIST_INSERT_HEAD(&nbd_server->conns, conn, next);
 | ||||||
|  |      nbd_update_server_watch(nbd_server); | ||||||
|  |   | ||||||
|  |      qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); | ||||||
|  |      /* TODO - expose handshake timeout as QMP option */ | ||||||
|  |      nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, | ||||||
|  |                     nbd_server->tlscreds, nbd_server->tlsauthz, | ||||||
|  | -                   nbd_blockdev_client_closed, NULL);
 | ||||||
|  | +                   nbd_blockdev_client_closed, conn);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void nbd_update_server_watch(NBDServerData *s) | ||||||
|  | @@ -76,12 +96,25 @@ static void nbd_update_server_watch(NBDServerData *s)
 | ||||||
|  |   | ||||||
|  |  static void nbd_server_free(NBDServerData *server) | ||||||
|  |  { | ||||||
|  | +    NBDConn *conn, *tmp;
 | ||||||
|  | +
 | ||||||
|  |      if (!server) { | ||||||
|  |          return; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | +    /*
 | ||||||
|  | +     * Forcefully close the listener socket, and any clients that have
 | ||||||
|  | +     * not yet disconnected on their own.
 | ||||||
|  | +     */
 | ||||||
|  |      qio_net_listener_disconnect(server->listener); | ||||||
|  |      object_unref(OBJECT(server->listener)); | ||||||
|  | +    QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) {
 | ||||||
|  | +        qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH,
 | ||||||
|  | +                             NULL);
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    AIO_WAIT_WHILE(NULL, server->connections > 0);
 | ||||||
|  | +
 | ||||||
|  |      if (server->tlscreds) { | ||||||
|  |          object_unref(OBJECT(server->tlscreds)); | ||||||
|  |      } | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,135 @@ | |||||||
|  | From faac5261d5a9af155950c4e7779c5a4721562824 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric Blake <eblake@redhat.com> | ||||||
|  | Date: Thu, 8 Aug 2024 16:05:08 -0500 | ||||||
|  | Subject: [PATCH 3/5] nbd/server: CVE-2024-7409: Drop non-negotiating clients | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z] | ||||||
|  | RH-Jira: RHEL-52611 | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Acked-by: Richard W.M. Jones <rjones@redhat.com> | ||||||
|  | RH-Commit: [3/4] 8c39829f8efbded9af018a4b915af266a55a793a (ebblake/qemu-kvm) | ||||||
|  | 
 | ||||||
|  | A client that opens a socket but does not negotiate is merely hogging | ||||||
|  | qemu's resources (an open fd and a small amount of memory); and a | ||||||
|  | malicious client that can access the port where NBD is listening can | ||||||
|  | attempt a denial of service attack by intentionally opening and | ||||||
|  | abandoning lots of unfinished connections.  The previous patch put a | ||||||
|  | default bound on the number of such ongoing connections, but once that | ||||||
|  | limit is hit, no more clients can connect (including legitimate ones). | ||||||
|  | The solution is to insist that clients complete handshake within a | ||||||
|  | reasonable time limit, defaulting to 10 seconds.  A client that has | ||||||
|  | not successfully completed NBD_OPT_GO by then (including the case of | ||||||
|  | where the client didn't know TLS credentials to even reach the point | ||||||
|  | of NBD_OPT_GO) is wasting our time and does not deserve to stay | ||||||
|  | connected.  Later patches will allow fine-tuning the limit away from | ||||||
|  | the default value (including disabling it for doing integration | ||||||
|  | testing of the handshake process itself). | ||||||
|  | 
 | ||||||
|  | Note that this patch in isolation actually makes it more likely to see | ||||||
|  | qemu SEGV after nbd-server-stop, as any client socket still connected | ||||||
|  | when the server shuts down will now be closed after 10 seconds rather | ||||||
|  | than at the client's whims.  That will be addressed in the next patch. | ||||||
|  | 
 | ||||||
|  | For a demo of this patch in action: | ||||||
|  | $ qemu-nbd -f raw -r -t -e 10 file & | ||||||
|  | $ nbdsh --opt-mode -c ' | ||||||
|  | H = list() | ||||||
|  | for i in range(20): | ||||||
|  |   print(i) | ||||||
|  |   H.insert(i, nbd.NBD()) | ||||||
|  |   H[i].set_opt_mode(True) | ||||||
|  |   H[i].connect_uri("nbd://localhost") | ||||||
|  | ' | ||||||
|  | $ kill $! | ||||||
|  | 
 | ||||||
|  | where later connections get to start progressing once earlier ones are | ||||||
|  | forcefully dropped for taking too long, rather than hanging. | ||||||
|  | 
 | ||||||
|  | Suggested-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | Message-ID: <20240807174943.771624-13-eblake@redhat.com> | ||||||
|  | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | [eblake: rebase to changes earlier in series, reduce scope of timer] | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit b9b72cb3ce15b693148bd09cef7e50110566d8a0) | ||||||
|  | Conflicts: | ||||||
|  | 	nbd/server.c - context with different aiocontext locking | ||||||
|  |         nbd/trace-events - context with no client-connection.c | ||||||
|  | Jira: https://issues.redhat.com/browse/RHEL-52611 | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  nbd/server.c     | 28 +++++++++++++++++++++++++++- | ||||||
|  |  nbd/trace-events |  1 + | ||||||
|  |  2 files changed, 28 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/nbd/server.c b/nbd/server.c
 | ||||||
|  | index cc1b6838bf..1265068f70 100644
 | ||||||
|  | --- a/nbd/server.c
 | ||||||
|  | +++ b/nbd/server.c
 | ||||||
|  | @@ -2701,22 +2701,48 @@ static void nbd_client_receive_next_request(NBDClient *client)
 | ||||||
|  |      } | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void nbd_handshake_timer_cb(void *opaque)
 | ||||||
|  | +{
 | ||||||
|  | +    QIOChannel *ioc = opaque;
 | ||||||
|  | +
 | ||||||
|  | +    trace_nbd_handshake_timer_cb();
 | ||||||
|  | +    qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  static coroutine_fn void nbd_co_client_start(void *opaque) | ||||||
|  |  { | ||||||
|  |      NBDClient *client = opaque; | ||||||
|  |      Error *local_err = NULL; | ||||||
|  | +    QEMUTimer *handshake_timer = NULL;
 | ||||||
|  |   | ||||||
|  |      qemu_co_mutex_init(&client->send_lock); | ||||||
|  |   | ||||||
|  | -    /* TODO - utilize client->handshake_max_secs */
 | ||||||
|  | +    /*
 | ||||||
|  | +     * Create a timer to bound the time spent in negotiation. If the
 | ||||||
|  | +     * timer expires, it is likely nbd_negotiate will fail because the
 | ||||||
|  | +     * socket was shutdown.
 | ||||||
|  | +     */
 | ||||||
|  | +    if (client->handshake_max_secs > 0) {
 | ||||||
|  | +        handshake_timer = aio_timer_new(qemu_get_aio_context(),
 | ||||||
|  | +                                        QEMU_CLOCK_REALTIME,
 | ||||||
|  | +                                        SCALE_NS,
 | ||||||
|  | +                                        nbd_handshake_timer_cb,
 | ||||||
|  | +                                        client->sioc);
 | ||||||
|  | +        timer_mod(handshake_timer,
 | ||||||
|  | +                  qemu_clock_get_ns(QEMU_CLOCK_REALTIME) +
 | ||||||
|  | +                  client->handshake_max_secs * NANOSECONDS_PER_SECOND);
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  |      if (nbd_negotiate(client, &local_err)) { | ||||||
|  |          if (local_err) { | ||||||
|  |              error_report_err(local_err); | ||||||
|  |          } | ||||||
|  | +        timer_free(handshake_timer);
 | ||||||
|  |          client_close(client, false); | ||||||
|  |          return; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | +    timer_free(handshake_timer);
 | ||||||
|  |      nbd_client_receive_next_request(client); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/nbd/trace-events b/nbd/trace-events
 | ||||||
|  | index c4919a2dd5..553546f1f2 100644
 | ||||||
|  | --- a/nbd/trace-events
 | ||||||
|  | +++ b/nbd/trace-events
 | ||||||
|  | @@ -73,3 +73,4 @@ nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *n
 | ||||||
|  |  nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32 | ||||||
|  |  nbd_co_receive_align_compliance(const char *op, uint64_t from, uint32_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx32 ", align=0x%" PRIx32 | ||||||
|  |  nbd_trip(void) "Reading request" | ||||||
|  | +nbd_handshake_timer_cb(void) "client took too long to negotiate"
 | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,161 @@ | |||||||
|  | From 00af174d1388ed2d2df7961ee78be6af3757a01c Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric Blake <eblake@redhat.com> | ||||||
|  | Date: Wed, 30 Aug 2023 18:48:02 -0400 | ||||||
|  | Subject: [PATCH 1/3] nbd/server: Favor qemu_aio_context over iohandler context | ||||||
|  | 
 | ||||||
|  | RH-Author: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-MergeRequest: 398: nbd/server: CVE-2024-7409: Avoid use-after-free when closing server | ||||||
|  | RH-Jira: RHEL-52611 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [1/3] 6ec0ef287fbc976175da83a0c14d9878e83affa2 (ebblake/qemu-kvm) | ||||||
|  | 
 | ||||||
|  | DOWNSTREAM ONLY - but based on an idea originally included as a | ||||||
|  | side-effect in the larger upstream patch 06e0f098 "io: follow | ||||||
|  | coroutine AioContext in qio_channel_yield()", as well as handling the | ||||||
|  | state of the qio TLS channel before it is associated with a block | ||||||
|  | device as an alternative to 199e84de "qio: Inherit | ||||||
|  | follow_coroutine_ctx across TLS". | ||||||
|  | 
 | ||||||
|  | The NBD server code wants to use qio_channel_shutdown() followed by | ||||||
|  | AIO_WAIT_WHILE() during nbd_server_free(), but cannot attach the ioc | ||||||
|  | to an AioContext until the client has completed the handshake to the | ||||||
|  | point that the server knows what block device to associate with the | ||||||
|  | connection.  The qio code is set up to handle connections with no | ||||||
|  | AioContext in the iohandler context, but this context is specifically | ||||||
|  | designed to NOT make progress during AIO_WAIT_WHILE().  In order to | ||||||
|  | prevent things from deadlocking, the qio channels handling NBD | ||||||
|  | handshake MUST be in the qemu_aio_context, so that an early shutdown | ||||||
|  | triggered by nbd-server-stop can make progress. | ||||||
|  | 
 | ||||||
|  | Note that upstream handled the main qio channel by the use of | ||||||
|  | qio_channel_set_follow_coroutine_ctx() in only one place in | ||||||
|  | nbd/server.c; upstream handled the TLS channel by a more generic | ||||||
|  | second patch that taught qio TLS channel to inherit the | ||||||
|  | follow_coroutine_ctx status from its parent.  But since this patch is | ||||||
|  | already downstream only, the minimal diff is achieved by manually | ||||||
|  | setting the status of the TLS channel in NBD code, rather than | ||||||
|  | backporting the qio inheritance code.  For testing that the second | ||||||
|  | call to qio_channel_set_favor_qemu_aio_ctx() matters, I used this test | ||||||
|  | setup (borrowing a pre-built PSK file for username alice from the | ||||||
|  | libnbd project, and using IPv4 since this qemu is too old to support | ||||||
|  | TLS over Unix sockets): | ||||||
|  | 
 | ||||||
|  | $ # in terminal 1: | ||||||
|  | $ qemu-system-x86_64 --nographic --nodefaults --qmp stdio \ | ||||||
|  |   --object tls-creds-psk,id=tls0,dir=/PATHTO/libnbd/tests,endpoint=server | ||||||
|  | {"execute": "qmp_capabilities"} | ||||||
|  | {"execute":"nbd-server-start","arguments":{"addr":{"type":"inet", | ||||||
|  |   "data":{"host":"127.0.0.1","port":"10809"}},"tls-creds":"tls0"}} | ||||||
|  | 
 | ||||||
|  | $ # in terminal 2: | ||||||
|  | $ nbdsh -c 'h.set_uri_allow_local_file(True)' --opt-mode -u \ | ||||||
|  |   'nbds://alice@127.0.0.1/?tls-psk-file=/PATHTO/libnbd/tests/keys.psk' \ | ||||||
|  |   -c 'import time; time.sleep(15)' | ||||||
|  | 
 | ||||||
|  | $ # in terminal 1, before 10 seconds elapse | ||||||
|  | {"execute":"nbd-server-stop"} | ||||||
|  | {"execute":"quit"} | ||||||
|  | 
 | ||||||
|  | and observed that, when omitting the one-line TLS setting, qemu would | ||||||
|  | hit the same deadlock with a TLS client as what I was observing for a | ||||||
|  | non-TLS client without this entire patch. | ||||||
|  | 
 | ||||||
|  | Jira: https://issues.redhat.com/browse/RHEL-52611 | ||||||
|  | Suggested-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  include/io/channel.h | 16 ++++++++++++++++ | ||||||
|  |  io/channel.c         | 14 +++++++++++++- | ||||||
|  |  nbd/server.c         |  2 ++ | ||||||
|  |  3 files changed, 31 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/include/io/channel.h b/include/io/channel.h
 | ||||||
|  | index 716235d496..f1ce19ea81 100644
 | ||||||
|  | --- a/include/io/channel.h
 | ||||||
|  | +++ b/include/io/channel.h
 | ||||||
|  | @@ -84,6 +84,7 @@ struct QIOChannel {
 | ||||||
|  |      AioContext *ctx; | ||||||
|  |      Coroutine *read_coroutine; | ||||||
|  |      Coroutine *write_coroutine; | ||||||
|  | +    bool favor_qemu_aio_ctx;
 | ||||||
|  |  #ifdef _WIN32 | ||||||
|  |      HANDLE event; /* For use with GSource on Win32 */ | ||||||
|  |  #endif | ||||||
|  | @@ -498,6 +499,21 @@ int qio_channel_set_blocking(QIOChannel *ioc,
 | ||||||
|  |                               bool enabled, | ||||||
|  |                               Error **errp); | ||||||
|  |   | ||||||
|  | +/**
 | ||||||
|  | + * qio_channel_set_favor_qemu_aio_ctx:
 | ||||||
|  | + * @ioc: the channel object
 | ||||||
|  | + * @enabled: whether to fall back to qemu_aio_context
 | ||||||
|  | + *
 | ||||||
|  | + * If @enabled is true, calls to qio_channel_yield() with no AioContext
 | ||||||
|  | + * set use the qemu_aio_context instead of the global iohandler context.
 | ||||||
|  | + *
 | ||||||
|  | + * If @enabled is false, calls to qio_channel_yield() use the global iohandler
 | ||||||
|  | + * AioContext. This is may be used by coroutines that run in the main loop and
 | ||||||
|  | + * do not wish to respond to I/O during nested event loops. This is the
 | ||||||
|  | + * default for compatibility with code that is not aware of AioContexts.
 | ||||||
|  | + */
 | ||||||
|  | +void qio_channel_set_favor_qemu_aio_ctx(QIOChannel *ioc, bool enabled);
 | ||||||
|  | +
 | ||||||
|  |  /** | ||||||
|  |   * qio_channel_close: | ||||||
|  |   * @ioc: the channel object | ||||||
|  | diff --git a/io/channel.c b/io/channel.c
 | ||||||
|  | index a8c7f11649..74704d0464 100644
 | ||||||
|  | --- a/io/channel.c
 | ||||||
|  | +++ b/io/channel.c
 | ||||||
|  | @@ -364,6 +364,12 @@ int qio_channel_set_blocking(QIOChannel *ioc,
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |   | ||||||
|  | +void qio_channel_set_favor_qemu_aio_ctx(QIOChannel *ioc, bool enabled)
 | ||||||
|  | +{
 | ||||||
|  | +    ioc->favor_qemu_aio_ctx = enabled;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +
 | ||||||
|  |  int qio_channel_close(QIOChannel *ioc, | ||||||
|  |                        Error **errp) | ||||||
|  |  { | ||||||
|  | @@ -545,7 +551,13 @@ static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
 | ||||||
|  |          wr_handler = qio_channel_restart_write; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
 | ||||||
|  | +    if (ioc->ctx) {
 | ||||||
|  | +        ctx = ioc->ctx;
 | ||||||
|  | +    } else if (ioc->favor_qemu_aio_ctx) {
 | ||||||
|  | +        ctx = qemu_get_aio_context();
 | ||||||
|  | +    } else {
 | ||||||
|  | +        ctx = iohandler_get_aio_context();
 | ||||||
|  | +    }
 | ||||||
|  |      qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | diff --git a/nbd/server.c b/nbd/server.c
 | ||||||
|  | index 1265068f70..41a2003300 100644
 | ||||||
|  | --- a/nbd/server.c
 | ||||||
|  | +++ b/nbd/server.c
 | ||||||
|  | @@ -758,6 +758,7 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
 | ||||||
|  |          return NULL; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | +    qio_channel_set_favor_qemu_aio_ctx(QIO_CHANNEL(tioc), true);
 | ||||||
|  |      qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls"); | ||||||
|  |      trace_nbd_negotiate_handle_starttls_handshake(); | ||||||
|  |      data.loop = g_main_loop_new(g_main_context_default(), FALSE); | ||||||
|  | @@ -1333,6 +1334,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
 | ||||||
|  |       */ | ||||||
|  |   | ||||||
|  |      qio_channel_set_blocking(client->ioc, false, NULL); | ||||||
|  | +    qio_channel_set_favor_qemu_aio_ctx(client->ioc, true);
 | ||||||
|  |   | ||||||
|  |      trace_nbd_negotiate_begin(); | ||||||
|  |      memcpy(buf, "NBDMAGIC", 8); | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
							
								
								
									
										174
									
								
								SOURCES/kvm-nbd-server-Plumb-in-new-args-to-nbd_client_add.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								SOURCES/kvm-nbd-server-Plumb-in-new-args-to-nbd_client_add.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,174 @@ | |||||||
|  | From 0d204cb81aec2b13254a0bd53938f53bfea81cb5 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Eric Blake <eblake@redhat.com> | ||||||
|  | Date: Wed, 7 Aug 2024 08:50:01 -0500 | ||||||
|  | Subject: [PATCH 1/5] nbd/server: Plumb in new args to nbd_client_add() | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Eric Blake <eblake@redhat.com> | ||||||
|  | RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z] | ||||||
|  | RH-Jira: RHEL-52611 | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Acked-by: Richard W.M. Jones <rjones@redhat.com> | ||||||
|  | RH-Commit: [1/4] 292be8dd2df2a840b2200e31a27e9d17fdab91ad (ebblake/qemu-kvm) | ||||||
|  | 
 | ||||||
|  | Upcoming patches to fix a CVE need to track an opaque pointer passed | ||||||
|  | in by the owner of a client object, as well as request for a time | ||||||
|  | limit on how fast negotiation must complete.  Prepare for that by | ||||||
|  | changing the signature of nbd_client_new() and adding an accessor to | ||||||
|  | get at the opaque pointer, although for now the two servers | ||||||
|  | (qemu-nbd.c and blockdev-nbd.c) do not change behavior even though | ||||||
|  | they pass in a new default timeout value. | ||||||
|  | 
 | ||||||
|  | Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | Message-ID: <20240807174943.771624-11-eblake@redhat.com> | ||||||
|  | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | [eblake: s/LIMIT/MAX_SECS/ as suggested by Dan] | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit fb1c2aaa981e0a2fa6362c9985f1296b74f055ac) | ||||||
|  | Jira: https://issues.redhat.com/browse/RHEL-52611 | ||||||
|  | Signed-off-by: Eric Blake <eblake@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  blockdev-nbd.c      |  6 ++++-- | ||||||
|  |  include/block/nbd.h | 11 ++++++++++- | ||||||
|  |  nbd/server.c        | 20 +++++++++++++++++--- | ||||||
|  |  qemu-nbd.c          |  4 +++- | ||||||
|  |  4 files changed, 34 insertions(+), 7 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/blockdev-nbd.c b/blockdev-nbd.c
 | ||||||
|  | index bdfa7ed3a5..b9e8dc78f3 100644
 | ||||||
|  | --- a/blockdev-nbd.c
 | ||||||
|  | +++ b/blockdev-nbd.c
 | ||||||
|  | @@ -59,8 +59,10 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
 | ||||||
|  |      nbd_update_server_watch(nbd_server); | ||||||
|  |   | ||||||
|  |      qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); | ||||||
|  | -    nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz,
 | ||||||
|  | -                   nbd_blockdev_client_closed);
 | ||||||
|  | +    /* TODO - expose handshake timeout as QMP option */
 | ||||||
|  | +    nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
 | ||||||
|  | +                   nbd_server->tlscreds, nbd_server->tlsauthz,
 | ||||||
|  | +                   nbd_blockdev_client_closed, NULL);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void nbd_update_server_watch(NBDServerData *s) | ||||||
|  | diff --git a/include/block/nbd.h b/include/block/nbd.h
 | ||||||
|  | index 78d101b774..b71a297249 100644
 | ||||||
|  | --- a/include/block/nbd.h
 | ||||||
|  | +++ b/include/block/nbd.h
 | ||||||
|  | @@ -27,6 +27,12 @@
 | ||||||
|  |   | ||||||
|  |  extern const BlockExportDriver blk_exp_nbd; | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must
 | ||||||
|  | + * succeed at NBD_OPT_GO before being forcefully dropped as too slow.
 | ||||||
|  | + */
 | ||||||
|  | +#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10
 | ||||||
|  | +
 | ||||||
|  |  /* Handshake phase structs - this struct is passed on the wire */ | ||||||
|  |   | ||||||
|  |  struct NBDOption { | ||||||
|  | @@ -338,9 +344,12 @@ AioContext *nbd_export_aio_context(NBDExport *exp);
 | ||||||
|  |  NBDExport *nbd_export_find(const char *name); | ||||||
|  |   | ||||||
|  |  void nbd_client_new(QIOChannelSocket *sioc, | ||||||
|  | +                    uint32_t handshake_max_secs,
 | ||||||
|  |                      QCryptoTLSCreds *tlscreds, | ||||||
|  |                      const char *tlsauthz, | ||||||
|  | -                    void (*close_fn)(NBDClient *, bool));
 | ||||||
|  | +                    void (*close_fn)(NBDClient *, bool),
 | ||||||
|  | +                    void *owner);
 | ||||||
|  | +void *nbd_client_owner(NBDClient *client);
 | ||||||
|  |  void nbd_client_get(NBDClient *client); | ||||||
|  |  void nbd_client_put(NBDClient *client); | ||||||
|  |   | ||||||
|  | diff --git a/nbd/server.c b/nbd/server.c
 | ||||||
|  | index 6db124cf53..cc1b6838bf 100644
 | ||||||
|  | --- a/nbd/server.c
 | ||||||
|  | +++ b/nbd/server.c
 | ||||||
|  | @@ -120,10 +120,12 @@ typedef struct NBDExportMetaContexts {
 | ||||||
|  |  struct NBDClient { | ||||||
|  |      int refcount; | ||||||
|  |      void (*close_fn)(NBDClient *client, bool negotiated); | ||||||
|  | +    void *owner;
 | ||||||
|  |   | ||||||
|  |      NBDExport *exp; | ||||||
|  |      QCryptoTLSCreds *tlscreds; | ||||||
|  |      char *tlsauthz; | ||||||
|  | +    uint32_t handshake_max_secs;
 | ||||||
|  |      QIOChannelSocket *sioc; /* The underlying data channel */ | ||||||
|  |      QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ | ||||||
|  |   | ||||||
|  | @@ -2706,6 +2708,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
 | ||||||
|  |   | ||||||
|  |      qemu_co_mutex_init(&client->send_lock); | ||||||
|  |   | ||||||
|  | +    /* TODO - utilize client->handshake_max_secs */
 | ||||||
|  |      if (nbd_negotiate(client, &local_err)) { | ||||||
|  |          if (local_err) { | ||||||
|  |              error_report_err(local_err); | ||||||
|  | @@ -2718,14 +2721,17 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  /* | ||||||
|  | - * Create a new client listener using the given channel @sioc.
 | ||||||
|  | + * Create a new client listener using the given channel @sioc and @owner.
 | ||||||
|  |   * Begin servicing it in a coroutine.  When the connection closes, call | ||||||
|  | - * @close_fn with an indication of whether the client completed negotiation.
 | ||||||
|  | + * @close_fn with an indication of whether the client completed negotiation
 | ||||||
|  | + * within @handshake_max_secs seconds (0 for unbounded).
 | ||||||
|  |   */ | ||||||
|  |  void nbd_client_new(QIOChannelSocket *sioc, | ||||||
|  | +                    uint32_t handshake_max_secs,
 | ||||||
|  |                      QCryptoTLSCreds *tlscreds, | ||||||
|  |                      const char *tlsauthz, | ||||||
|  | -                    void (*close_fn)(NBDClient *, bool))
 | ||||||
|  | +                    void (*close_fn)(NBDClient *, bool),
 | ||||||
|  | +                    void *owner)
 | ||||||
|  |  { | ||||||
|  |      NBDClient *client; | ||||||
|  |      Coroutine *co; | ||||||
|  | @@ -2737,13 +2743,21 @@ void nbd_client_new(QIOChannelSocket *sioc,
 | ||||||
|  |          object_ref(OBJECT(client->tlscreds)); | ||||||
|  |      } | ||||||
|  |      client->tlsauthz = g_strdup(tlsauthz); | ||||||
|  | +    client->handshake_max_secs = handshake_max_secs;
 | ||||||
|  |      client->sioc = sioc; | ||||||
|  |      qio_channel_set_delay(QIO_CHANNEL(sioc), false); | ||||||
|  |      object_ref(OBJECT(client->sioc)); | ||||||
|  |      client->ioc = QIO_CHANNEL(sioc); | ||||||
|  |      object_ref(OBJECT(client->ioc)); | ||||||
|  |      client->close_fn = close_fn; | ||||||
|  | +    client->owner = owner;
 | ||||||
|  |   | ||||||
|  |      co = qemu_coroutine_create(nbd_co_client_start, client); | ||||||
|  |      qemu_coroutine_enter(co); | ||||||
|  |  } | ||||||
|  | +
 | ||||||
|  | +void *
 | ||||||
|  | +nbd_client_owner(NBDClient *client)
 | ||||||
|  | +{
 | ||||||
|  | +    return client->owner;
 | ||||||
|  | +}
 | ||||||
|  | diff --git a/qemu-nbd.c b/qemu-nbd.c
 | ||||||
|  | index c6c20df68a..f48abf379e 100644
 | ||||||
|  | --- a/qemu-nbd.c
 | ||||||
|  | +++ b/qemu-nbd.c
 | ||||||
|  | @@ -363,7 +363,9 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
 | ||||||
|  |   | ||||||
|  |      nb_fds++; | ||||||
|  |      nbd_update_server_watch(); | ||||||
|  | -    nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed);
 | ||||||
|  | +    /* TODO - expose handshake timeout as command line option */
 | ||||||
|  | +    nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
 | ||||||
|  | +                   tlscreds, tlsauthz, nbd_client_closed, NULL);
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static void nbd_update_server_watch(void) | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
							
								
								
									
										209
									
								
								SOURCES/kvm-qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								SOURCES/kvm-qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,209 @@ | |||||||
|  | From 5cdbc87ab24a8cc4cf926158ec429d43d8a45f15 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Wed, 5 Jun 2024 19:56:51 -0400 | ||||||
|  | Subject: [PATCH 1/5] qcow2: Don't open data_file with BDRV_O_NO_IO | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC) | ||||||
|  | RH-Jira: RHEL-35616 | ||||||
|  | RH-CVE: CVE-2024-4467 | ||||||
|  | RH-Acked-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [1/5] 2e72d21c14d86645cf68eec78f49d5cc5d77581f | ||||||
|  | 
 | ||||||
|  | Conflicts: qcow2_do_open(): missing boolean ´open_data_file'. | ||||||
|  |            We assume it to be true. | ||||||
|  | 
 | ||||||
|  | commit f9843ce5c519901654a7d8ba43ee95ce25ca13c2 | ||||||
|  | Author: Kevin Wolf <kwolf@redhat.com> | ||||||
|  | Date:   Thu Apr 11 15:06:01 2024 +0200 | ||||||
|  | 
 | ||||||
|  |     qcow2: Don't open data_file with BDRV_O_NO_IO | ||||||
|  | 
 | ||||||
|  |     One use case for 'qemu-img info' is verifying that untrusted images | ||||||
|  |     don't reference an unwanted external file, be it as a backing file or an | ||||||
|  |     external data file. To make sure that calling 'qemu-img info' can't | ||||||
|  |     already have undesired side effects with a malicious image, just don't | ||||||
|  |     open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do | ||||||
|  |     I/O, we don't need to have it open. | ||||||
|  | 
 | ||||||
|  |     This changes the output of iotests case 061, which used 'qemu-img info' | ||||||
|  |     to show that opening an image with an invalid data file fails. After | ||||||
|  |     this patch, it succeeds. Replace this part of the test with a qemu-io | ||||||
|  |     call, but keep the final 'qemu-img info' to show that the invalid data | ||||||
|  |     file is correctly displayed in the output. | ||||||
|  | 
 | ||||||
|  |     Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||||||
|  |     Reviewed-by: Eric Blake <eblake@redhat.com> | ||||||
|  |     Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  |     Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  |     Upstream: N/A, embargoed | ||||||
|  |     Signed-off-by: Hanna Czenczek <hreitz@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  block/qcow2.c              | 87 +++++++++++++++++++++++--------------- | ||||||
|  |  tests/qemu-iotests/061     |  6 ++- | ||||||
|  |  tests/qemu-iotests/061.out |  8 +++- | ||||||
|  |  3 files changed, 62 insertions(+), 39 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/block/qcow2.c b/block/qcow2.c
 | ||||||
|  | index d509016756..6ee1919612 100644
 | ||||||
|  | --- a/block/qcow2.c
 | ||||||
|  | +++ b/block/qcow2.c
 | ||||||
|  | @@ -1613,50 +1613,67 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
 | ||||||
|  |          goto fail; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    /* Open external data file */
 | ||||||
|  | -    s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
 | ||||||
|  | -                                   &child_of_bds, BDRV_CHILD_DATA,
 | ||||||
|  | -                                   true, errp);
 | ||||||
|  | -    if (*errp) {
 | ||||||
|  | -        ret = -EINVAL;
 | ||||||
|  | -        goto fail;
 | ||||||
|  | -    }
 | ||||||
|  | +    if (flags & BDRV_O_NO_IO) {
 | ||||||
|  | +        /*
 | ||||||
|  | +         * Don't open the data file for 'qemu-img info' so that it can be used
 | ||||||
|  | +         * to verify that an untrusted qcow2 image doesn't refer to external
 | ||||||
|  | +         * files.
 | ||||||
|  | +         *
 | ||||||
|  | +         * Note: This still makes has_data_file() return true.
 | ||||||
|  | +         */
 | ||||||
|  | +        if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
 | ||||||
|  | +            s->data_file = NULL;
 | ||||||
|  | +        } else {
 | ||||||
|  | +            s->data_file = bs->file;
 | ||||||
|  | +        }
 | ||||||
|  | +        qdict_extract_subqdict(options, NULL, "data-file.");
 | ||||||
|  | +        qdict_del(options, "data-file");
 | ||||||
|  | +    } else {
 | ||||||
|  | +        /* Open external data file */
 | ||||||
|  | +        s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
 | ||||||
|  | +                                       &child_of_bds, BDRV_CHILD_DATA,
 | ||||||
|  | +                                       true, errp);
 | ||||||
|  | +        if (*errp) {
 | ||||||
|  | +            ret = -EINVAL;
 | ||||||
|  | +            goto fail;
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  | -    if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
 | ||||||
|  | -        if (!s->data_file && s->image_data_file) {
 | ||||||
|  | -            s->data_file = bdrv_open_child(s->image_data_file, options,
 | ||||||
|  | -                                           "data-file", bs, &child_of_bds,
 | ||||||
|  | -                                           BDRV_CHILD_DATA, false, errp);
 | ||||||
|  | +        if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
 | ||||||
|  | +            if (!s->data_file && s->image_data_file) {
 | ||||||
|  | +                s->data_file = bdrv_open_child(s->image_data_file, options,
 | ||||||
|  | +                                               "data-file", bs, &child_of_bds,
 | ||||||
|  | +                                               BDRV_CHILD_DATA, false, errp);
 | ||||||
|  | +                if (!s->data_file) {
 | ||||||
|  | +                    ret = -EINVAL;
 | ||||||
|  | +                    goto fail;
 | ||||||
|  | +                }
 | ||||||
|  | +            }
 | ||||||
|  |              if (!s->data_file) { | ||||||
|  | +                error_setg(errp, "'data-file' is required for this image");
 | ||||||
|  |                  ret = -EINVAL; | ||||||
|  |                  goto fail; | ||||||
|  |              } | ||||||
|  | -        }
 | ||||||
|  | -        if (!s->data_file) {
 | ||||||
|  | -            error_setg(errp, "'data-file' is required for this image");
 | ||||||
|  | -            ret = -EINVAL;
 | ||||||
|  | -            goto fail;
 | ||||||
|  | -        }
 | ||||||
|  |   | ||||||
|  | -        /* No data here */
 | ||||||
|  | -        bs->file->role &= ~BDRV_CHILD_DATA;
 | ||||||
|  | +            /* No data here */
 | ||||||
|  | +            bs->file->role &= ~BDRV_CHILD_DATA;
 | ||||||
|  |   | ||||||
|  | -        /* Must succeed because we have given up permissions if anything */
 | ||||||
|  | -        bdrv_child_refresh_perms(bs, bs->file, &error_abort);
 | ||||||
|  | -    } else {
 | ||||||
|  | -        if (s->data_file) {
 | ||||||
|  | -            error_setg(errp, "'data-file' can only be set for images with an "
 | ||||||
|  | -                             "external data file");
 | ||||||
|  | -            ret = -EINVAL;
 | ||||||
|  | -            goto fail;
 | ||||||
|  | -        }
 | ||||||
|  | +            /* Must succeed because we have given up permissions if anything */
 | ||||||
|  | +            bdrv_child_refresh_perms(bs, bs->file, &error_abort);
 | ||||||
|  | +        } else {
 | ||||||
|  | +            if (s->data_file) {
 | ||||||
|  | +                error_setg(errp, "'data-file' can only be set for images with an "
 | ||||||
|  | +                           "external data file");
 | ||||||
|  | +                ret = -EINVAL;
 | ||||||
|  | +                goto fail;
 | ||||||
|  | +            }
 | ||||||
|  |   | ||||||
|  | -        s->data_file = bs->file;
 | ||||||
|  | +            s->data_file = bs->file;
 | ||||||
|  |   | ||||||
|  | -        if (data_file_is_raw(bs)) {
 | ||||||
|  | -            error_setg(errp, "data-file-raw requires a data file");
 | ||||||
|  | -            ret = -EINVAL;
 | ||||||
|  | -            goto fail;
 | ||||||
|  | +            if (data_file_is_raw(bs)) {
 | ||||||
|  | +                error_setg(errp, "data-file-raw requires a data file");
 | ||||||
|  | +                ret = -EINVAL;
 | ||||||
|  | +                goto fail;
 | ||||||
|  | +            }
 | ||||||
|  |          } | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
 | ||||||
|  | index 9507c223bd..6a5bd47efc 100755
 | ||||||
|  | --- a/tests/qemu-iotests/061
 | ||||||
|  | +++ b/tests/qemu-iotests/061
 | ||||||
|  | @@ -322,12 +322,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
 | ||||||
|  |  echo | ||||||
|  |  _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M | ||||||
|  |  $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" | ||||||
|  | -_img_info --format-specific
 | ||||||
|  | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
 | ||||||
|  | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
 | ||||||
|  |  TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||||||
|  |   | ||||||
|  |  echo | ||||||
|  |  $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" | ||||||
|  | -_img_info --format-specific
 | ||||||
|  | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
 | ||||||
|  | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
 | ||||||
|  |  TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||||||
|  |   | ||||||
|  |  echo | ||||||
|  | diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
 | ||||||
|  | index 7ecbd4dea8..99b2307a23 100644
 | ||||||
|  | --- a/tests/qemu-iotests/061.out
 | ||||||
|  | +++ b/tests/qemu-iotests/061.out
 | ||||||
|  | @@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
 | ||||||
|  |  qemu-img: data-file can only be set for images that use an external data file | ||||||
|  |   | ||||||
|  |  Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data | ||||||
|  | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory
 | ||||||
|  | +qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory
 | ||||||
|  | +read 4096/4096 bytes at offset 0
 | ||||||
|  | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | ||||||
|  |  image: TEST_DIR/t.IMGFMT | ||||||
|  |  file format: IMGFMT | ||||||
|  |  virtual size: 64 MiB (67108864 bytes) | ||||||
|  | @@ -560,7 +562,9 @@ Format specific information:
 | ||||||
|  |      corrupt: false | ||||||
|  |      extended l2: false | ||||||
|  |   | ||||||
|  | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
 | ||||||
|  | +qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image
 | ||||||
|  | +read 4096/4096 bytes at offset 0
 | ||||||
|  | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 | ||||||
|  |  image: TEST_DIR/t.IMGFMT | ||||||
|  |  file format: IMGFMT | ||||||
|  |  virtual size: 64 MiB (67108864 bytes) | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
							
								
								
									
										94
									
								
								SOURCES/kvm-qga-skip-bind-mounts-in-fs-list.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								SOURCES/kvm-qga-skip-bind-mounts-in-fs-list.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | |||||||
|  | From 661c0fee958d993b5c8d4600998ba0fdbf43da11 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Konstantin Kostiuk <kkostiuk@redhat.com> | ||||||
|  | Date: Wed, 18 Dec 2024 18:49:04 +0200 | ||||||
|  | Subject: [PATCH] qga: skip bind mounts in fs list | ||||||
|  | 
 | ||||||
|  | RH-Author: Konstantin Kostiuk <None> | ||||||
|  | RH-MergeRequest: 423: qga: skip bind mounts in fs list | ||||||
|  | RH-Jira: RHEL-59214 | ||||||
|  | RH-Acked-by: yvugenfi <None> | ||||||
|  | RH-Acked-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-Commit: [1/1] 2ebf2a4dba0e2da9d077c116accd12dc7f3dbcd1 | ||||||
|  | 
 | ||||||
|  | The filesystem list in build_fs_mount_list should skip bind mounts. | ||||||
|  | This because we end up in locking situations when doing fsFreeze. Like | ||||||
|  | mentioned in [1] and [2]. | ||||||
|  | 
 | ||||||
|  | Next to that, the build_fs_mount_list call did a fallback via | ||||||
|  | build_fs_mount_list_from_mtab if mountinfo did not exist. | ||||||
|  | There it skipped bind mounts, but this is broken for newer OS. | ||||||
|  | This as mounts does not return the path of the bind mount but the | ||||||
|  | underlying dev/partition, so S_ISDIR will never return true in | ||||||
|  | dev_major_minor call. | ||||||
|  | 
 | ||||||
|  | This patch simply checks the existing devmajor:devminor tuple in the | ||||||
|  | mounts, and if it already exists, this means we have the same devices | ||||||
|  | mounted again, a bind mount. So skip this. | ||||||
|  | 
 | ||||||
|  | Same approach is used in open-vm-tools [3]. | ||||||
|  | 
 | ||||||
|  | [1]: https://gitlab.com/qemu-project/qemu/-/issues/592 | ||||||
|  | [2]: https://gitlab.com/qemu-project/qemu/-/issues/520 | ||||||
|  | [3]: https://github.com/vmware/open-vm-tools/commit/d58847b497e212737007958c945af1df22a8ab58 | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jean-Louis Dupond <jean-louis@dupond.be> | ||||||
|  | Reviewed-by: Konstantin Kostiuk <kkostiuk@redhat.com> | ||||||
|  | Link: https://lore.kernel.org/r/20241002100634.162499-2-jean-louis@dupond.be | ||||||
|  | Signed-off-by: Konstantin Kostiuk <kkostiuk@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  qga/commands-posix.c | 25 +++++++++++++++++++++++++ | ||||||
|  |  1 file changed, 25 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/qga/commands-posix.c b/qga/commands-posix.c
 | ||||||
|  | index 75dbaab68e..dce0d1551f 100644
 | ||||||
|  | --- a/qga/commands-posix.c
 | ||||||
|  | +++ b/qga/commands-posix.c
 | ||||||
|  | @@ -668,6 +668,22 @@ static int dev_major_minor(const char *devpath,
 | ||||||
|  |      return -1; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +/*
 | ||||||
|  | + * Check if we already have the devmajor:devminor in the mounts
 | ||||||
|  | + * If thats the case return true.
 | ||||||
|  | + */
 | ||||||
|  | +static bool dev_exists(FsMountList *mounts, unsigned int devmajor, unsigned int devminor)
 | ||||||
|  | +{
 | ||||||
|  | +    FsMount *mount;
 | ||||||
|  | +
 | ||||||
|  | +    QTAILQ_FOREACH(mount, mounts, next) {
 | ||||||
|  | +        if (mount->devmajor == devmajor && mount->devminor == devminor) {
 | ||||||
|  | +            return true;
 | ||||||
|  | +        }
 | ||||||
|  | +    }
 | ||||||
|  | +    return false;
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  /* | ||||||
|  |   * Walk the mount table and build a list of local file systems | ||||||
|  |   */ | ||||||
|  | @@ -701,6 +717,10 @@ static void build_fs_mount_list_from_mtab(FsMountList *mounts, Error **errp)
 | ||||||
|  |              /* Skip bind mounts */ | ||||||
|  |              continue; | ||||||
|  |          } | ||||||
|  | +        if (dev_exists(mounts, devmajor, devminor)) {
 | ||||||
|  | +            /* Skip already existing devices (bind mounts) */
 | ||||||
|  | +            continue;
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  |          mount = g_new0(FsMount, 1); | ||||||
|  |          mount->dirname = g_strdup(ment->mnt_dir); | ||||||
|  | @@ -780,6 +800,11 @@ static void build_fs_mount_list(FsMountList *mounts, Error **errp)
 | ||||||
|  |                  continue; | ||||||
|  |              } | ||||||
|  |          } | ||||||
|  | +        
 | ||||||
|  | +        if (dev_exists(mounts, devmajor, devminor)) {
 | ||||||
|  | +            /* Skip already existing devices (bind mounts) */
 | ||||||
|  | +            continue;
 | ||||||
|  | +        }
 | ||||||
|  |   | ||||||
|  |          mount = g_new0(FsMount, 1); | ||||||
|  |          mount->dirname = g_strdup(line + dir_s); | ||||||
|  | -- 
 | ||||||
|  | 2.47.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,52 @@ | |||||||
|  | From 1c0887f9a108a237fc87834c87e9d0358dd98dd9 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Thomas Huth <thuth@redhat.com> | ||||||
|  | Date: Wed, 23 Apr 2025 12:54:42 +0200 | ||||||
|  | Subject: [PATCH 5/5] redhat: Adjust indentation in qapi/machine-target.json | ||||||
|  |  for QEMU v6.2 | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Thomas Huth <thuth@redhat.com> | ||||||
|  | RH-MergeRequest: 449: Fix for live-migrating guests from IBM z16 to z17 host machines | ||||||
|  | RH-Jira: RHEL-88701 | ||||||
|  | RH-Acked-by: Cédric Le Goater <clg@redhat.com> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [5/5] 1a50aac42e2b8e2990f5a00f69117a58911c8107 | ||||||
|  | 
 | ||||||
|  | Upstream Status: RHEL-only | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-88701 | ||||||
|  | 
 | ||||||
|  | The QAPI parser of QEMU v6.2 is stricter with the indentation rules, | ||||||
|  | so we have to adjust the indentation with the colon of the previous | ||||||
|  | line here. | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  qapi/machine-target.json | 10 +++++----- | ||||||
|  |  1 file changed, 5 insertions(+), 5 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/qapi/machine-target.json b/qapi/machine-target.json
 | ||||||
|  | index 320688cd21..415e0fc3c6 100644
 | ||||||
|  | --- a/qapi/machine-target.json
 | ||||||
|  | +++ b/qapi/machine-target.json
 | ||||||
|  | @@ -210,11 +210,11 @@
 | ||||||
|  |  # @model: the expanded CpuModelInfo. | ||||||
|  |  # | ||||||
|  |  # @deprecated-props: a list of properties that are flagged as deprecated | ||||||
|  | -#     by the CPU vendor.  The list depends on the CpuModelExpansionType:
 | ||||||
|  | -#     "static" properties are a subset of the enabled-properties for
 | ||||||
|  | -#     the expanded model; "full" properties are a set of properties
 | ||||||
|  | -#     that are deprecated across all models for the architecture.
 | ||||||
|  | -#     (since: 9.1).
 | ||||||
|  | +#                    by the CPU vendor.  The list depends on the CpuModelExpansionType:
 | ||||||
|  | +#                    "static" properties are a subset of the enabled-properties for
 | ||||||
|  | +#                    the expanded model; "full" properties are a set of properties
 | ||||||
|  | +#                    that are deprecated across all models for the architecture.
 | ||||||
|  | +#                    (since: 9.1).
 | ||||||
|  |  # | ||||||
|  |  # Since: 2.8 | ||||||
|  |  ## | ||||||
|  | -- 
 | ||||||
|  | 2.48.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,110 @@ | |||||||
|  | From 31c0a5fb90575b85dc9510417d6b8317319d0b57 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Collin Walling <walling@linux.ibm.com> | ||||||
|  | Date: Fri, 19 Jul 2024 14:17:41 -0400 | ||||||
|  | Subject: [PATCH 3/5] target/s390x: filter deprecated properties based on model | ||||||
|  |  expansion type | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Thomas Huth <thuth@redhat.com> | ||||||
|  | RH-MergeRequest: 449: Fix for live-migrating guests from IBM z16 to z17 host machines | ||||||
|  | RH-Jira: RHEL-88701 | ||||||
|  | RH-Acked-by: Cédric Le Goater <clg@redhat.com> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [3/5] dd1889f1de28aa4c40df34fcad7898dc600374fd | ||||||
|  | 
 | ||||||
|  | Currently, there is no way to execute the query-cpu-model-expansion | ||||||
|  | command to retrieve a comprehenisve list of deprecated properties, as | ||||||
|  | the result is dependent per-model. To enable this, the expansion output | ||||||
|  | is modified as such: | ||||||
|  | 
 | ||||||
|  | When reporting a "full" CPU model, show the *entire* list of deprecated | ||||||
|  | properties regardless if they are supported on the model. A full | ||||||
|  | expansion outputs all known CPU model properties anyway, so it makes | ||||||
|  | sense to report all deprecated properties here too. | ||||||
|  | 
 | ||||||
|  | This allows management apps to query a single model (e.g. host) to | ||||||
|  | acquire the full list of deprecated properties. | ||||||
|  | 
 | ||||||
|  | Additionally, when reporting a "static" CPU model, the command will | ||||||
|  | only show deprecated properties that are a subset of the model's | ||||||
|  | *enabled* properties. This is more accurate than how the query was | ||||||
|  | handled before, which blindly reported deprecated properties that | ||||||
|  | were never otherwise introduced for certain models. | ||||||
|  | 
 | ||||||
|  | Acked-by: David Hildenbrand <david@redhat.com> | ||||||
|  | Suggested-by: Jiri Denemark <jdenemar@redhat.com> | ||||||
|  | Signed-off-by: Collin Walling <walling@linux.ibm.com> | ||||||
|  | Message-ID: <20240719181741.35146-1-walling@linux.ibm.com> | ||||||
|  | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||||||
|  | (cherry picked from commit eed0e8ffa38f0695c0519508f6e4f5a3297cbd67) | ||||||
|  | ---
 | ||||||
|  |  qapi/machine-target.json         |  5 +++-- | ||||||
|  |  target/s390x/cpu_models_sysemu.c | 16 +++++++++------- | ||||||
|  |  2 files changed, 12 insertions(+), 9 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/qapi/machine-target.json b/qapi/machine-target.json
 | ||||||
|  | index c93c811dbc..d32dc6958f 100644
 | ||||||
|  | --- a/qapi/machine-target.json
 | ||||||
|  | +++ b/qapi/machine-target.json
 | ||||||
|  | @@ -18,8 +18,9 @@
 | ||||||
|  |  # @props: a dictionary of QOM properties to be applied | ||||||
|  |  # | ||||||
|  |  # @deprecated-props: a list of properties that are flagged as deprecated | ||||||
|  | -#     by the CPU vendor.  These props are a subset of the full model's
 | ||||||
|  | -#     definition list of properties. (since 9.1)
 | ||||||
|  | +#     by the CPU vendor.  These properties are either a subset of the
 | ||||||
|  | +#     properties enabled on the CPU model, or a set of properties
 | ||||||
|  | +#     deprecated across all models for the architecture.
 | ||||||
|  |  # | ||||||
|  |  # Since: 2.8 | ||||||
|  |  ## | ||||||
|  | diff --git a/target/s390x/cpu_models_sysemu.c b/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | index 7ed94b4117..edb81769cd 100644
 | ||||||
|  | --- a/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | +++ b/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | @@ -183,11 +183,15 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 | ||||||
|  |                                  bool delta_changes) | ||||||
|  |  { | ||||||
|  |      QDict *qdict = qdict_new(); | ||||||
|  | -    S390FeatBitmap bitmap;
 | ||||||
|  | +    S390FeatBitmap bitmap, deprecated;
 | ||||||
|  |   | ||||||
|  |      /* always fallback to the static base model */ | ||||||
|  |      info->name = g_strdup_printf("%s-base", model->def->name); | ||||||
|  |   | ||||||
|  | +    /* features flagged as deprecated */
 | ||||||
|  | +    bitmap_zero(deprecated, S390_FEAT_MAX);
 | ||||||
|  | +    s390_get_deprecated_features(deprecated);
 | ||||||
|  | +
 | ||||||
|  |      if (delta_changes) { | ||||||
|  |          /* features deleted from the base feature set */ | ||||||
|  |          bitmap_andnot(bitmap, model->def->base_feat, model->features, | ||||||
|  | @@ -202,6 +206,9 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 | ||||||
|  |          if (!bitmap_empty(bitmap, S390_FEAT_MAX)) { | ||||||
|  |              s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_enabled_feat); | ||||||
|  |          } | ||||||
|  | +
 | ||||||
|  | +        /* deprecated features that are a subset of the model's enabled features */
 | ||||||
|  | +        bitmap_and(deprecated, deprecated, model->features, S390_FEAT_MAX);
 | ||||||
|  |      } else { | ||||||
|  |          /* expand all features */ | ||||||
|  |          s390_feat_bitmap_to_ascii(model->features, qdict, | ||||||
|  | @@ -217,12 +224,7 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 | ||||||
|  |          info->has_props = true; | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | -    /* features flagged as deprecated */
 | ||||||
|  | -    bitmap_zero(bitmap, S390_FEAT_MAX);
 | ||||||
|  | -    s390_get_deprecated_features(bitmap);
 | ||||||
|  | -
 | ||||||
|  | -    bitmap_and(bitmap, bitmap, model->def->full_feat, S390_FEAT_MAX);
 | ||||||
|  | -    s390_feat_bitmap_to_ascii(bitmap, &info->deprecated_props, list_add_feat);
 | ||||||
|  | +    s390_feat_bitmap_to_ascii(deprecated, &info->deprecated_props, list_add_feat);
 | ||||||
|  |      info->has_deprecated_props = !!info->deprecated_props; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.48.1 | ||||||
|  | 
 | ||||||
							
								
								
									
										44
									
								
								SOURCES/kvm-target-s390x-flag-te-and-cte-as-deprecated.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								SOURCES/kvm-target-s390x-flag-te-and-cte-as-deprecated.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | |||||||
|  | From a851c0768ce192035014cce72d231a8df62dc011 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Collin Walling <walling@linux.ibm.com> | ||||||
|  | Date: Mon, 29 Apr 2024 15:10:59 -0400 | ||||||
|  | Subject: [PATCH 2/5] target/s390x: flag te and cte as deprecated | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Thomas Huth <thuth@redhat.com> | ||||||
|  | RH-MergeRequest: 449: Fix for live-migrating guests from IBM z16 to z17 host machines | ||||||
|  | RH-Jira: RHEL-88701 | ||||||
|  | RH-Acked-by: Cédric Le Goater <clg@redhat.com> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [2/5] d00d9654126596e31603ddec04ede4227b982739 | ||||||
|  | 
 | ||||||
|  | Add the CONSTRAINT_TRANSACTIONAL_EXE (cte) and TRANSACTIONAL_EXE (te) | ||||||
|  | to the list of deprecated features. | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Collin Walling <walling@linux.ibm.com> | ||||||
|  | Reviewed-by: David Hildenbrand <david@redhat.com> | ||||||
|  | Message-ID: <20240429191059.11806-3-walling@linux.ibm.com> | ||||||
|  | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||||||
|  | (cherry picked from commit 6e55b32d45976a8e78cbd3bbdf6ed1148cb2662a) | ||||||
|  | ---
 | ||||||
|  |  target/s390x/cpu_features.c | 3 +++ | ||||||
|  |  1 file changed, 3 insertions(+) | ||||||
|  | 
 | ||||||
|  | diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c
 | ||||||
|  | index 40be75c90a..59f1d6d81e 100644
 | ||||||
|  | --- a/target/s390x/cpu_features.c
 | ||||||
|  | +++ b/target/s390x/cpu_features.c
 | ||||||
|  | @@ -218,6 +218,9 @@ void s390_get_deprecated_features(S390FeatBitmap features)
 | ||||||
|  |           /* CSSKE is deprecated on newer generations */ | ||||||
|  |           S390_FEAT_CONDITIONAL_SSKE, | ||||||
|  |           S390_FEAT_BPB, | ||||||
|  | +         /* Deprecated on z16 */
 | ||||||
|  | +         S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE,
 | ||||||
|  | +         S390_FEAT_TRANSACTIONAL_EXE
 | ||||||
|  |      }; | ||||||
|  |      int i; | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.48.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,163 @@ | |||||||
|  | From 1142610383e66712cfa4d11cc02d7661f68d7193 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Collin Walling <walling@linux.ibm.com> | ||||||
|  | Date: Fri, 26 Jul 2024 16:36:46 -0400 | ||||||
|  | Subject: [PATCH 4/5] target/s390x: move @deprecated-props to CpuModelExpansion | ||||||
|  |  Info | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Thomas Huth <thuth@redhat.com> | ||||||
|  | RH-MergeRequest: 449: Fix for live-migrating guests from IBM z16 to z17 host machines | ||||||
|  | RH-Jira: RHEL-88701 | ||||||
|  | RH-Acked-by: Cédric Le Goater <clg@redhat.com> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [4/5] 2c66f3000c44742b02d1cd4b64e3d091b4be05cb | ||||||
|  | 
 | ||||||
|  | CpuModelInfo is used both as command argument and in command | ||||||
|  | returns. | ||||||
|  | 
 | ||||||
|  | Its @deprecated-props array does not make any sense in arguments, | ||||||
|  | and is silently ignored.  We actually want it only as return value | ||||||
|  | of query-cpu-model-expansion. | ||||||
|  | 
 | ||||||
|  | Move it from CpuModelInfo to CpuModelExpansionType, and document | ||||||
|  | its dependence on expansion type property. | ||||||
|  | 
 | ||||||
|  | This was identified late during review [1] and we have to fix it up | ||||||
|  | while it's not part of an official QEMU release yet. | ||||||
|  | 
 | ||||||
|  | [1] https://lore.kernel.org/qemu-devel/20240719181741.35146-1-walling@linux.ibm.com/ | ||||||
|  | 
 | ||||||
|  | Message-ID: <20240726203646.20279-1-walling@linux.ibm.com> | ||||||
|  | Fixes: eed0e8ffa38f ("target/s390x: filter deprecated properties based on model expansion type") | ||||||
|  | Signed-off-by: Collin Walling <walling@linux.ibm.com> | ||||||
|  | [ david: - add "Fixes", adjust description, reference v3 instead | ||||||
|  |          - make property s390x-only and non-optional | ||||||
|  |          - fixup "populate" vs. "populated" ] | ||||||
|  | Signed-off-by: David Hildenbrand <david@redhat.com> | ||||||
|  | (cherry picked from commit 442110bc6f3f308aedf884103fdba87ba906dfe7) | ||||||
|  | ---
 | ||||||
|  |  qapi/machine-target.json         | 19 +++++++++++-------- | ||||||
|  |  target/s390x/cpu_models_sysemu.c | 29 ++++++++++++++++++----------- | ||||||
|  |  2 files changed, 29 insertions(+), 19 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/qapi/machine-target.json b/qapi/machine-target.json
 | ||||||
|  | index d32dc6958f..320688cd21 100644
 | ||||||
|  | --- a/qapi/machine-target.json
 | ||||||
|  | +++ b/qapi/machine-target.json
 | ||||||
|  | @@ -17,17 +17,11 @@
 | ||||||
|  |  # @name: the name of the CPU definition the model is based on | ||||||
|  |  # @props: a dictionary of QOM properties to be applied | ||||||
|  |  # | ||||||
|  | -# @deprecated-props: a list of properties that are flagged as deprecated
 | ||||||
|  | -#     by the CPU vendor.  These properties are either a subset of the
 | ||||||
|  | -#     properties enabled on the CPU model, or a set of properties
 | ||||||
|  | -#     deprecated across all models for the architecture.
 | ||||||
|  | -#
 | ||||||
|  |  # Since: 2.8 | ||||||
|  |  ## | ||||||
|  |  { 'struct': 'CpuModelInfo', | ||||||
|  |    'data': { 'name': 'str', | ||||||
|  | -            '*props': 'any',
 | ||||||
|  | -            '*deprecated-props': ['str'] } }
 | ||||||
|  | +            '*props': 'any' } }
 | ||||||
|  |   | ||||||
|  |  ## | ||||||
|  |  # @CpuModelExpansionType: | ||||||
|  | @@ -215,10 +209,19 @@
 | ||||||
|  |  # | ||||||
|  |  # @model: the expanded CpuModelInfo. | ||||||
|  |  # | ||||||
|  | +# @deprecated-props: a list of properties that are flagged as deprecated
 | ||||||
|  | +#     by the CPU vendor.  The list depends on the CpuModelExpansionType:
 | ||||||
|  | +#     "static" properties are a subset of the enabled-properties for
 | ||||||
|  | +#     the expanded model; "full" properties are a set of properties
 | ||||||
|  | +#     that are deprecated across all models for the architecture.
 | ||||||
|  | +#     (since: 9.1).
 | ||||||
|  | +#
 | ||||||
|  |  # Since: 2.8 | ||||||
|  |  ## | ||||||
|  |  { 'struct': 'CpuModelExpansionInfo', | ||||||
|  | -  'data': { 'model': 'CpuModelInfo' },
 | ||||||
|  | +  'data': { 'model': 'CpuModelInfo',
 | ||||||
|  | +            'deprecated-props' : { 'type': ['str'],
 | ||||||
|  | +                                   'if': 'TARGET_S390X' } },
 | ||||||
|  |    'if': { 'any': [ 'TARGET_S390X', | ||||||
|  |                     'TARGET_I386', | ||||||
|  |                     'TARGET_ARM' ] } } | ||||||
|  | diff --git a/target/s390x/cpu_models_sysemu.c b/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | index edb81769cd..6680724bfe 100644
 | ||||||
|  | --- a/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | +++ b/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | @@ -183,15 +183,11 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 | ||||||
|  |                                  bool delta_changes) | ||||||
|  |  { | ||||||
|  |      QDict *qdict = qdict_new(); | ||||||
|  | -    S390FeatBitmap bitmap, deprecated;
 | ||||||
|  | +    S390FeatBitmap bitmap;
 | ||||||
|  |   | ||||||
|  |      /* always fallback to the static base model */ | ||||||
|  |      info->name = g_strdup_printf("%s-base", model->def->name); | ||||||
|  |   | ||||||
|  | -    /* features flagged as deprecated */
 | ||||||
|  | -    bitmap_zero(deprecated, S390_FEAT_MAX);
 | ||||||
|  | -    s390_get_deprecated_features(deprecated);
 | ||||||
|  | -
 | ||||||
|  |      if (delta_changes) { | ||||||
|  |          /* features deleted from the base feature set */ | ||||||
|  |          bitmap_andnot(bitmap, model->def->base_feat, model->features, | ||||||
|  | @@ -206,9 +202,6 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 | ||||||
|  |          if (!bitmap_empty(bitmap, S390_FEAT_MAX)) { | ||||||
|  |              s390_feat_bitmap_to_ascii(bitmap, qdict, qdict_add_enabled_feat); | ||||||
|  |          } | ||||||
|  | -
 | ||||||
|  | -        /* deprecated features that are a subset of the model's enabled features */
 | ||||||
|  | -        bitmap_and(deprecated, deprecated, model->features, S390_FEAT_MAX);
 | ||||||
|  |      } else { | ||||||
|  |          /* expand all features */ | ||||||
|  |          s390_feat_bitmap_to_ascii(model->features, qdict, | ||||||
|  | @@ -223,9 +216,6 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 | ||||||
|  |          info->props = QOBJECT(qdict); | ||||||
|  |          info->has_props = true; | ||||||
|  |      } | ||||||
|  | -
 | ||||||
|  | -    s390_feat_bitmap_to_ascii(deprecated, &info->deprecated_props, list_add_feat);
 | ||||||
|  | -    info->has_deprecated_props = !!info->deprecated_props;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, | ||||||
|  | @@ -236,6 +226,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 | ||||||
|  |      CpuModelExpansionInfo *expansion_info = NULL; | ||||||
|  |      S390CPUModel s390_model; | ||||||
|  |      bool delta_changes = false; | ||||||
|  | +    S390FeatBitmap deprecated_feats;
 | ||||||
|  |   | ||||||
|  |      /* convert it to our internal representation */ | ||||||
|  |      cpu_model_from_info(&s390_model, model, &err); | ||||||
|  | @@ -255,6 +246,22 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
 | ||||||
|  |      expansion_info = g_new0(CpuModelExpansionInfo, 1); | ||||||
|  |      expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); | ||||||
|  |      cpu_info_from_model(expansion_info->model, &s390_model, delta_changes); | ||||||
|  | +
 | ||||||
|  | +    /* populate list of deprecated features */
 | ||||||
|  | +    bitmap_zero(deprecated_feats, S390_FEAT_MAX);
 | ||||||
|  | +    s390_get_deprecated_features(deprecated_feats);
 | ||||||
|  | +
 | ||||||
|  | +    if (delta_changes) {
 | ||||||
|  | +        /*
 | ||||||
|  | +         * Only populate deprecated features that are a
 | ||||||
|  | +         * subset of the features enabled on the CPU model.
 | ||||||
|  | +         */
 | ||||||
|  | +        bitmap_and(deprecated_feats, deprecated_feats,
 | ||||||
|  | +                   s390_model.features, S390_FEAT_MAX);
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    s390_feat_bitmap_to_ascii(deprecated_feats,
 | ||||||
|  | +                              &expansion_info->deprecated_props, list_add_feat);
 | ||||||
|  |      return expansion_info; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -- 
 | ||||||
|  | 2.48.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,136 @@ | |||||||
|  | From 1955d06f0ffcdcacdf1eec5c9fee99a2a9e81350 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Collin Walling <walling@linux.ibm.com> | ||||||
|  | Date: Mon, 29 Apr 2024 15:10:58 -0400 | ||||||
|  | Subject: [PATCH 1/5] target/s390x: report deprecated-props in | ||||||
|  |  cpu-model-expansion reply | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Thomas Huth <thuth@redhat.com> | ||||||
|  | RH-MergeRequest: 449: Fix for live-migrating guests from IBM z16 to z17 host machines | ||||||
|  | RH-Jira: RHEL-88701 | ||||||
|  | RH-Acked-by: Cédric Le Goater <clg@redhat.com> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [1/5] 9cecba35e831615bc1c899730b4f32de0fd7ba83 | ||||||
|  | 
 | ||||||
|  | Retain a list of deprecated features disjoint from any particular | ||||||
|  | CPU model. A query-cpu-model-expansion reply will now provide a list of | ||||||
|  | properties (i.e. features) that are flagged as deprecated. Example: | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |       "return": { | ||||||
|  |         "model": { | ||||||
|  |           "name": "z14.2-base", | ||||||
|  |           "deprecated-props": [ | ||||||
|  |             "bpb", | ||||||
|  |             "csske" | ||||||
|  |           ], | ||||||
|  |           "props": { | ||||||
|  |             "pfmfi": false, | ||||||
|  |             "exrl": true, | ||||||
|  |             ...a lot more props... | ||||||
|  |             "skey": false, | ||||||
|  |             "vxpdeh2": false | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | It is recommended that s390 guests operate with these features | ||||||
|  | explicitly disabled to ensure compatibility with future hardware. | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Collin Walling <walling@linux.ibm.com> | ||||||
|  | Acked-by: Markus Armbruster <armbru@redhat.com> | ||||||
|  | Reviewed-by: David Hildenbrand <david@redhat.com> | ||||||
|  | Message-ID: <20240429191059.11806-2-walling@linux.ibm.com> | ||||||
|  | Signed-off-by: Thomas Huth <thuth@redhat.com> | ||||||
|  | (cherry picked from commit 8aa2211e855df79ddd363e5f0d8c4d7d4c376e16) | ||||||
|  | ---
 | ||||||
|  |  qapi/machine-target.json         |  7 ++++++- | ||||||
|  |  target/s390x/cpu_features.c      | 14 ++++++++++++++ | ||||||
|  |  target/s390x/cpu_features.h      |  1 + | ||||||
|  |  target/s390x/cpu_models_sysemu.c |  8 ++++++++ | ||||||
|  |  4 files changed, 29 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/qapi/machine-target.json b/qapi/machine-target.json
 | ||||||
|  | index f5ec4bc172..c93c811dbc 100644
 | ||||||
|  | --- a/qapi/machine-target.json
 | ||||||
|  | +++ b/qapi/machine-target.json
 | ||||||
|  | @@ -17,11 +17,16 @@
 | ||||||
|  |  # @name: the name of the CPU definition the model is based on | ||||||
|  |  # @props: a dictionary of QOM properties to be applied | ||||||
|  |  # | ||||||
|  | +# @deprecated-props: a list of properties that are flagged as deprecated
 | ||||||
|  | +#     by the CPU vendor.  These props are a subset of the full model's
 | ||||||
|  | +#     definition list of properties. (since 9.1)
 | ||||||
|  | +#
 | ||||||
|  |  # Since: 2.8 | ||||||
|  |  ## | ||||||
|  |  { 'struct': 'CpuModelInfo', | ||||||
|  |    'data': { 'name': 'str', | ||||||
|  | -            '*props': 'any' } }
 | ||||||
|  | +            '*props': 'any',
 | ||||||
|  | +            '*deprecated-props': ['str'] } }
 | ||||||
|  |   | ||||||
|  |  ## | ||||||
|  |  # @CpuModelExpansionType: | ||||||
|  | diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c
 | ||||||
|  | index ebb155ce1c..40be75c90a 100644
 | ||||||
|  | --- a/target/s390x/cpu_features.c
 | ||||||
|  | +++ b/target/s390x/cpu_features.c
 | ||||||
|  | @@ -212,6 +212,20 @@ void s390_feat_bitmap_to_ascii(const S390FeatBitmap features, void *opaque,
 | ||||||
|  |      }; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +void s390_get_deprecated_features(S390FeatBitmap features)
 | ||||||
|  | +{
 | ||||||
|  | +    static const int feats[] = {
 | ||||||
|  | +         /* CSSKE is deprecated on newer generations */
 | ||||||
|  | +         S390_FEAT_CONDITIONAL_SSKE,
 | ||||||
|  | +         S390_FEAT_BPB,
 | ||||||
|  | +    };
 | ||||||
|  | +    int i;
 | ||||||
|  | +
 | ||||||
|  | +    for (i = 0; i < ARRAY_SIZE(feats); i++) {
 | ||||||
|  | +        set_bit(feats[i], features);
 | ||||||
|  | +    }
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  #define FEAT_GROUP_INIT(_name, _group, _desc)        \ | ||||||
|  |      {                                                \ | ||||||
|  |          .name = _name,                               \ | ||||||
|  | diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h
 | ||||||
|  | index a9bd68a2e1..661a8cd6db 100644
 | ||||||
|  | --- a/target/s390x/cpu_features.h
 | ||||||
|  | +++ b/target/s390x/cpu_features.h
 | ||||||
|  | @@ -69,6 +69,7 @@ void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type,
 | ||||||
|  |                            uint8_t *data); | ||||||
|  |  void s390_feat_bitmap_to_ascii(const S390FeatBitmap features, void *opaque, | ||||||
|  |                                 void (*fn)(const char *name, void *opaque)); | ||||||
|  | +void s390_get_deprecated_features(S390FeatBitmap features);
 | ||||||
|  |   | ||||||
|  |  /* Definition of a CPU feature group */ | ||||||
|  |  typedef struct { | ||||||
|  | diff --git a/target/s390x/cpu_models_sysemu.c b/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | index 6a04ccab1b..7ed94b4117 100644
 | ||||||
|  | --- a/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | +++ b/target/s390x/cpu_models_sysemu.c
 | ||||||
|  | @@ -216,6 +216,14 @@ static void cpu_info_from_model(CpuModelInfo *info, const S390CPUModel *model,
 | ||||||
|  |          info->props = QOBJECT(qdict); | ||||||
|  |          info->has_props = true; | ||||||
|  |      } | ||||||
|  | +
 | ||||||
|  | +    /* features flagged as deprecated */
 | ||||||
|  | +    bitmap_zero(bitmap, S390_FEAT_MAX);
 | ||||||
|  | +    s390_get_deprecated_features(bitmap);
 | ||||||
|  | +
 | ||||||
|  | +    bitmap_and(bitmap, bitmap, model->def->full_feat, S390_FEAT_MAX);
 | ||||||
|  | +    s390_feat_bitmap_to_ascii(bitmap, &info->deprecated_props, list_add_feat);
 | ||||||
|  | +    info->has_deprecated_props = !!info->deprecated_props;
 | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, | ||||||
|  | -- 
 | ||||||
|  | 2.48.1 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,118 @@ | |||||||
|  | From 4069f8f55d070b5a1eb2bf894a517ea9fb648bbd Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Tue, 5 Mar 2024 11:36:15 -0500 | ||||||
|  | Subject: [PATCH 2/3] ui/clipboard: mark type as not available when there is no | ||||||
|  |  data | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 353: ui/clipboard: mark type as not available when there is no data | ||||||
|  | RH-Jira: RHEL-19628 | ||||||
|  | RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Commit: [2/2] fa0edf7a362a16978e2377cf61f36ff227d186b2 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-19628 | ||||||
|  | CVE: CVE-2023-6683 | ||||||
|  | Upstream: Merged | ||||||
|  | Conflicts: | ||||||
|  |          - The function g_memdup2() is used by this commit, but is not present in | ||||||
|  |            this code version. It looks safe to introduce it in a preceding commit, | ||||||
|  |            instead of reverting to the less safe g_memdup(), so that is what we do. | ||||||
|  |          - There is a second upstream commit covering this CVE: | ||||||
|  |            commit 9c416582611b ("ui/clipboard: add asserts for update and request") | ||||||
|  |            which is based on several other previous commits not present in this version. | ||||||
|  |            Re-applying these, or trying to adapt the code, is too intrusive and risky | ||||||
|  |            given that it only introduces two diagnostic asserts which are not essential | ||||||
|  |            for solving the CVE. | ||||||
|  |            We therefore omit that commit. | ||||||
|  | 
 | ||||||
|  | commit 405484b29f6548c7b86549b0f961b906337aa68a | ||||||
|  | Author: Fiona Ebner <f.ebner@proxmox.com> | ||||||
|  | Date:   Wed Jan 24 11:57:48 2024 +0100 | ||||||
|  | 
 | ||||||
|  |     ui/clipboard: mark type as not available when there is no data | ||||||
|  | 
 | ||||||
|  |     With VNC, a client can send a non-extended VNC_MSG_CLIENT_CUT_TEXT | ||||||
|  |     message with len=0. In qemu_clipboard_set_data(), the clipboard info | ||||||
|  |     will be updated setting data to NULL (because g_memdup(data, size) | ||||||
|  |     returns NULL when size is 0). If the client does not set the | ||||||
|  |     VNC_ENCODING_CLIPBOARD_EXT feature when setting up the encodings, then | ||||||
|  |     the 'request' callback for the clipboard peer is not initialized. | ||||||
|  |     Later, because data is NULL, qemu_clipboard_request() can be reached | ||||||
|  |     via vdagent_chr_write() and vdagent_clipboard_recv_request() and | ||||||
|  |     there, the clipboard owner's 'request' callback will be attempted to | ||||||
|  |     be called, but that is a NULL pointer. | ||||||
|  | 
 | ||||||
|  |     In particular, this can happen when using the KRDC (22.12.3) VNC | ||||||
|  |     client. | ||||||
|  | 
 | ||||||
|  |     Another scenario leading to the same issue is with two clients (say | ||||||
|  |     noVNC and KRDC): | ||||||
|  | 
 | ||||||
|  |     The noVNC client sets the extension VNC_FEATURE_CLIPBOARD_EXT and | ||||||
|  |     initializes its cbpeer. | ||||||
|  | 
 | ||||||
|  |     The KRDC client does not, but triggers a vnc_client_cut_text() (note | ||||||
|  |     it's not the _ext variant)). There, a new clipboard info with it as | ||||||
|  |     the 'owner' is created and via qemu_clipboard_set_data() is called, | ||||||
|  |     which in turn calls qemu_clipboard_update() with that info. | ||||||
|  | 
 | ||||||
|  |     In qemu_clipboard_update(), the notifier for the noVNC client will be | ||||||
|  |     called, i.e. vnc_clipboard_notify() and also set vs->cbinfo for the | ||||||
|  |     noVNC client. The 'owner' in that clipboard info is the clipboard peer | ||||||
|  |     for the KRDC client, which did not initialize the 'request' function. | ||||||
|  |     That sounds correct to me, it is the owner of that clipboard info. | ||||||
|  | 
 | ||||||
|  |     Then when noVNC sends a VNC_MSG_CLIENT_CUT_TEXT message (it did set | ||||||
|  |     the VNC_FEATURE_CLIPBOARD_EXT feature correctly, so a check for it | ||||||
|  |     passes), that clipboard info is passed to qemu_clipboard_request() and | ||||||
|  |     the original segfault still happens. | ||||||
|  | 
 | ||||||
|  |     Fix the issue by handling updates with size 0 differently. In | ||||||
|  |     particular, mark in the clipboard info that the type is not available. | ||||||
|  | 
 | ||||||
|  |     While at it, switch to g_memdup2(), because g_memdup() is deprecated. | ||||||
|  | 
 | ||||||
|  |     Cc: qemu-stable@nongnu.org | ||||||
|  |     Fixes: CVE-2023-6683 | ||||||
|  |     Reported-by: Markus Frank <m.frank@proxmox.com> | ||||||
|  |     Suggested-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  |     Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> | ||||||
|  |     Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  |     Tested-by: Markus Frank <m.frank@proxmox.com> | ||||||
|  |     Message-ID: <20240124105749.204610-1-f.ebner@proxmox.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  ui/clipboard.c | 12 +++++++++--- | ||||||
|  |  1 file changed, 9 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ui/clipboard.c b/ui/clipboard.c
 | ||||||
|  | index d7b008d62a..b8c795f2e2 100644
 | ||||||
|  | --- a/ui/clipboard.c
 | ||||||
|  | +++ b/ui/clipboard.c
 | ||||||
|  | @@ -123,9 +123,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer,
 | ||||||
|  |      } | ||||||
|  |   | ||||||
|  |      g_free(info->types[type].data); | ||||||
|  | -    info->types[type].data = g_memdup(data, size);
 | ||||||
|  | -    info->types[type].size = size;
 | ||||||
|  | -    info->types[type].available = true;
 | ||||||
|  | +    if (size) {
 | ||||||
|  | +        info->types[type].data = g_memdup2(data, size);
 | ||||||
|  | +        info->types[type].size = size;
 | ||||||
|  | +        info->types[type].available = true;
 | ||||||
|  | +    } else {
 | ||||||
|  | +        info->types[type].data = NULL;
 | ||||||
|  | +        info->types[type].size = 0;
 | ||||||
|  | +        info->types[type].available = false;
 | ||||||
|  | +    }
 | ||||||
|  |   | ||||||
|  |      if (update) { | ||||||
|  |          qemu_clipboard_update(info); | ||||||
|  | -- 
 | ||||||
|  | 2.41.0 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,92 @@ | |||||||
|  | From 7ad4fc282b1f96d619ce2f9f7ed9049c3b894dd4 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Thu, 18 Jul 2024 09:42:42 -0400 | ||||||
|  | Subject: [PATCH 1/6] virtio-gpu: free BHs, by implementing unrealize | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability | ||||||
|  | RH-Jira: RHEL-32276 | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [1/6] d05c10426afac428d775669748f0aa689c23e787 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-32276 | ||||||
|  | CVE: CVE-2024-3446 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit 957d77863e4564454eb97f8f371096843daf4678 | ||||||
|  | Author: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  | Date:   Wed Jul 26 21:39:28 2023 +0400 | ||||||
|  | 
 | ||||||
|  |     virtio-gpu: free BHs, by implementing unrealize | ||||||
|  | 
 | ||||||
|  |     Acked-by: Dongwon Kim <dongwon.kim@intel.com> | ||||||
|  |     Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  |     Message-Id: <20230726173929.690601-2-marcandre.lureau@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  hw/display/virtio-gpu-base.c   |  2 +- | ||||||
|  |  hw/display/virtio-gpu.c        | 10 ++++++++++ | ||||||
|  |  include/hw/virtio/virtio-gpu.h |  1 + | ||||||
|  |  3 files changed, 12 insertions(+), 1 deletion(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
 | ||||||
|  | index c8da4806e0..e3ff9dcf38 100644
 | ||||||
|  | --- a/hw/display/virtio-gpu-base.c
 | ||||||
|  | +++ b/hw/display/virtio-gpu-base.c
 | ||||||
|  | @@ -223,7 +223,7 @@ virtio_gpu_base_set_features(VirtIODevice *vdev, uint64_t features)
 | ||||||
|  |      trace_virtio_gpu_features(((features & virgl) == virgl)); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void
 | ||||||
|  | +void
 | ||||||
|  |  virtio_gpu_base_device_unrealize(DeviceState *qdev) | ||||||
|  |  { | ||||||
|  |      VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev); | ||||||
|  | diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
 | ||||||
|  | index ecf9079145..e230e5091f 100644
 | ||||||
|  | --- a/hw/display/virtio-gpu.c
 | ||||||
|  | +++ b/hw/display/virtio-gpu.c
 | ||||||
|  | @@ -1341,6 +1341,15 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
 | ||||||
|  |      QTAILQ_INIT(&g->fenceq); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void virtio_gpu_device_unrealize(DeviceState *qdev)
 | ||||||
|  | +{
 | ||||||
|  | +    VirtIOGPU *g = VIRTIO_GPU(qdev);
 | ||||||
|  | +
 | ||||||
|  | +    g_clear_pointer(&g->ctrl_bh, qemu_bh_delete);
 | ||||||
|  | +    g_clear_pointer(&g->cursor_bh, qemu_bh_delete);
 | ||||||
|  | +    virtio_gpu_base_device_unrealize(qdev);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  |  void virtio_gpu_reset(VirtIODevice *vdev) | ||||||
|  |  { | ||||||
|  |      VirtIOGPU *g = VIRTIO_GPU(vdev); | ||||||
|  | @@ -1436,6 +1445,7 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
 | ||||||
|  |      vgbc->gl_flushed = virtio_gpu_handle_gl_flushed; | ||||||
|  |   | ||||||
|  |      vdc->realize = virtio_gpu_device_realize; | ||||||
|  | +    vdc->unrealize = virtio_gpu_device_unrealize;
 | ||||||
|  |      vdc->reset = virtio_gpu_reset; | ||||||
|  |      vdc->get_config = virtio_gpu_get_config; | ||||||
|  |      vdc->set_config = virtio_gpu_set_config; | ||||||
|  | diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
 | ||||||
|  | index acfba7c76c..4367d005f1 100644
 | ||||||
|  | --- a/include/hw/virtio/virtio-gpu.h
 | ||||||
|  | +++ b/include/hw/virtio/virtio-gpu.h
 | ||||||
|  | @@ -235,6 +235,7 @@ bool virtio_gpu_base_device_realize(DeviceState *qdev,
 | ||||||
|  |                                      VirtIOHandleOutput ctrl_cb, | ||||||
|  |                                      VirtIOHandleOutput cursor_cb, | ||||||
|  |                                      Error **errp); | ||||||
|  | +void virtio_gpu_base_device_unrealize(DeviceState *qdev);
 | ||||||
|  |  void virtio_gpu_base_reset(VirtIOGPUBase *g); | ||||||
|  |  void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g, | ||||||
|  |                          struct virtio_gpu_resp_display_info *dpy_info); | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
							
								
								
									
										143
									
								
								SOURCES/kvm-virtio-gpu-reset-gfx-resources-in-main-thread.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								SOURCES/kvm-virtio-gpu-reset-gfx-resources-in-main-thread.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,143 @@ | |||||||
|  | From 29328e9693aeae1c980a859d4966deda9f54242d Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Thu, 18 Jul 2024 09:36:06 -0400 | ||||||
|  | Subject: [PATCH 2/6] virtio-gpu: reset gfx resources in main thread | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability | ||||||
|  | RH-Jira: RHEL-32276 | ||||||
|  | RH-Acked-by: Gerd Hoffmann <None> | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [2/6] a97eef1e6e85b44c08d17adcdc468e857e48a17e (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-32276 | ||||||
|  | CVE: CVE-2024-3446 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit a41e2d97f92b48552988b3cc62dce79d62f60dcc | ||||||
|  | Author: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  | Date:   Wed Jul 26 21:39:29 2023 +0400 | ||||||
|  | 
 | ||||||
|  |     virtio-gpu: reset gfx resources in main thread | ||||||
|  | 
 | ||||||
|  |     Calling OpenGL from different threads can have bad consequences if not | ||||||
|  |     carefully reviewed. It's not generally supported. In my case, I was | ||||||
|  |     debugging a crash in glDeleteTextures from OPENGL32.DLL, where I asked | ||||||
|  |     qemu for gl=es, and thus ANGLE implementation was expected. libepoxy did | ||||||
|  |     resolution of the global pointer for glGenTexture to the GLES version | ||||||
|  |     from the main thread. But it resolved glDeleteTextures to the GL | ||||||
|  |     version, because it was done from a different thread without correct | ||||||
|  |     context. Oops. | ||||||
|  | 
 | ||||||
|  |     Let's stick to the main thread for GL calls by using a BH. | ||||||
|  | 
 | ||||||
|  |     Note: I didn't use atomics for reset_finished check, assuming the BQL | ||||||
|  |     will provide enough of sync, but I might be wrong. | ||||||
|  | 
 | ||||||
|  |     Acked-by: Dongwon Kim <dongwon.kim@intel.com> | ||||||
|  |     Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  |     Message-Id: <20230726173929.690601-3-marcandre.lureau@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  hw/display/virtio-gpu.c        | 35 +++++++++++++++++++++++++++++++--- | ||||||
|  |  include/hw/virtio/virtio-gpu.h |  3 +++ | ||||||
|  |  2 files changed, 35 insertions(+), 3 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
 | ||||||
|  | index e230e5091f..c28ce1ea72 100644
 | ||||||
|  | --- a/hw/display/virtio-gpu.c
 | ||||||
|  | +++ b/hw/display/virtio-gpu.c
 | ||||||
|  | @@ -14,6 +14,7 @@
 | ||||||
|  |  #include "qemu/osdep.h" | ||||||
|  |  #include "qemu/units.h" | ||||||
|  |  #include "qemu/iov.h" | ||||||
|  | +#include "sysemu/cpus.h"
 | ||||||
|  |  #include "ui/console.h" | ||||||
|  |  #include "trace.h" | ||||||
|  |  #include "sysemu/dma.h" | ||||||
|  | @@ -42,6 +43,7 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
 | ||||||
|  |   | ||||||
|  |  static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, | ||||||
|  |                                         struct virtio_gpu_simple_resource *res); | ||||||
|  | +static void virtio_gpu_reset_bh(void *opaque);
 | ||||||
|  |   | ||||||
|  |  void virtio_gpu_update_cursor_data(VirtIOGPU *g, | ||||||
|  |                                     struct virtio_gpu_scanout *s, | ||||||
|  | @@ -1336,6 +1338,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
 | ||||||
|  |                                       &qdev->mem_reentrancy_guard); | ||||||
|  |      g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g, | ||||||
|  |                                         &qdev->mem_reentrancy_guard); | ||||||
|  | +    g->reset_bh = qemu_bh_new(virtio_gpu_reset_bh, g);
 | ||||||
|  | +    qemu_cond_init(&g->reset_cond);
 | ||||||
|  |      QTAILQ_INIT(&g->reslist); | ||||||
|  |      QTAILQ_INIT(&g->cmdq); | ||||||
|  |      QTAILQ_INIT(&g->fenceq); | ||||||
|  | @@ -1347,19 +1351,44 @@ static void virtio_gpu_device_unrealize(DeviceState *qdev)
 | ||||||
|  |   | ||||||
|  |      g_clear_pointer(&g->ctrl_bh, qemu_bh_delete); | ||||||
|  |      g_clear_pointer(&g->cursor_bh, qemu_bh_delete); | ||||||
|  | +    g_clear_pointer(&g->reset_bh, qemu_bh_delete);
 | ||||||
|  | +    qemu_cond_destroy(&g->reset_cond);
 | ||||||
|  |      virtio_gpu_base_device_unrealize(qdev); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -void virtio_gpu_reset(VirtIODevice *vdev)
 | ||||||
|  | +static void virtio_gpu_reset_bh(void *opaque)
 | ||||||
|  |  { | ||||||
|  | -    VirtIOGPU *g = VIRTIO_GPU(vdev);
 | ||||||
|  | +    VirtIOGPU *g = VIRTIO_GPU(opaque);
 | ||||||
|  |      struct virtio_gpu_simple_resource *res, *tmp; | ||||||
|  | -    struct virtio_gpu_ctrl_command *cmd;
 | ||||||
|  | +    int i = 0;
 | ||||||
|  |   | ||||||
|  |      QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) { | ||||||
|  |          virtio_gpu_resource_destroy(g, res); | ||||||
|  |      } | ||||||
|  |   | ||||||
|  | +    for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
 | ||||||
|  | +        dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  | +    g->reset_finished = true;
 | ||||||
|  | +    qemu_cond_signal(&g->reset_cond);
 | ||||||
|  | +}
 | ||||||
|  | +
 | ||||||
|  | +void virtio_gpu_reset(VirtIODevice *vdev)
 | ||||||
|  | +{
 | ||||||
|  | +    VirtIOGPU *g = VIRTIO_GPU(vdev);
 | ||||||
|  | +    struct virtio_gpu_ctrl_command *cmd;
 | ||||||
|  | +
 | ||||||
|  | +    if (qemu_in_vcpu_thread()) {
 | ||||||
|  | +        g->reset_finished = false;
 | ||||||
|  | +        qemu_bh_schedule(g->reset_bh);
 | ||||||
|  | +        while (!g->reset_finished) {
 | ||||||
|  | +            qemu_cond_wait_iothread(&g->reset_cond);
 | ||||||
|  | +        }
 | ||||||
|  | +    } else {
 | ||||||
|  | +        virtio_gpu_reset_bh(g);
 | ||||||
|  | +    }
 | ||||||
|  | +
 | ||||||
|  |      while (!QTAILQ_EMPTY(&g->cmdq)) { | ||||||
|  |          cmd = QTAILQ_FIRST(&g->cmdq); | ||||||
|  |          QTAILQ_REMOVE(&g->cmdq, cmd, next); | ||||||
|  | diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
 | ||||||
|  | index 4367d005f1..f3578c1325 100644
 | ||||||
|  | --- a/include/hw/virtio/virtio-gpu.h
 | ||||||
|  | +++ b/include/hw/virtio/virtio-gpu.h
 | ||||||
|  | @@ -166,6 +166,9 @@ struct VirtIOGPU {
 | ||||||
|  |   | ||||||
|  |      QEMUBH *ctrl_bh; | ||||||
|  |      QEMUBH *cursor_bh; | ||||||
|  | +    QEMUBH *reset_bh;
 | ||||||
|  | +    QemuCond reset_cond;
 | ||||||
|  | +    bool reset_finished;
 | ||||||
|  |   | ||||||
|  |      QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; | ||||||
|  |      QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq; | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -0,0 +1,90 @@ | |||||||
|  | From c3146dd39fb274ffbd70d20f8ba9e13562fb21ad Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | Date: Tue, 5 Mar 2024 16:38:49 -0500 | ||||||
|  | Subject: [PATCH 3/3] virtio-net: correctly copy vnet header when flushing TX | ||||||
|  | 
 | ||||||
|  | RH-Author: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | RH-MergeRequest: 354: virtio-net: correctly copy vnet header when flushing TX | ||||||
|  | RH-Jira: RHEL-19496 | ||||||
|  | RH-Acked-by: Jason Wang <jasowang@redhat.com> | ||||||
|  | RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com> | ||||||
|  | RH-Commit: [1/1] 445b601da86a64298b776879fa0f30a4bf6c16f5 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2) | ||||||
|  | 
 | ||||||
|  | JIRA: https://issues.redhat.com/browse/RHEL-19496 | ||||||
|  | CVE: CVE-2023-6693 | ||||||
|  | Upstream: Merged | ||||||
|  | 
 | ||||||
|  | commit 2220e8189fb94068dbad333228659fbac819abb0 | ||||||
|  | Author: Jason Wang <jasowang@redhat.com> | ||||||
|  | Date:   Tue Jan 2 11:29:01 2024 +0800 | ||||||
|  | 
 | ||||||
|  |     virtio-net: correctly copy vnet header when flushing TX | ||||||
|  | 
 | ||||||
|  |     When HASH_REPORT is negotiated, the guest_hdr_len might be larger than | ||||||
|  |     the size of the mergeable rx buffer header. Using | ||||||
|  |     virtio_net_hdr_mrg_rxbuf during the header swap might lead a stack | ||||||
|  |     overflow in this case. Fixing this by using virtio_net_hdr_v1_hash | ||||||
|  |     instead. | ||||||
|  | 
 | ||||||
|  |     Reported-by: Xiao Lei <leixiao.nop@zju.edu.cn> | ||||||
|  |     Cc: Yuri Benditovich <yuri.benditovich@daynix.com> | ||||||
|  |     Cc: qemu-stable@nongnu.org | ||||||
|  |     Cc: Mauro Matteo Cascella <mcascell@redhat.com> | ||||||
|  |     Fixes: CVE-2023-6693 | ||||||
|  |     Fixes: e22f0603fb2f ("virtio-net: reference implementation of hash report") | ||||||
|  |     Reviewed-by: Michael Tokarev <mjt@tls.msk.ru> | ||||||
|  |     Signed-off-by: Jason Wang <jasowang@redhat.com> | ||||||
|  | 
 | ||||||
|  | Signed-off-by: Jon Maloy <jmaloy@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  hw/net/virtio-net.c | 13 +++++++++---- | ||||||
|  |  1 file changed, 9 insertions(+), 4 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
 | ||||||
|  | index f5f07f8e63..7d459726d4 100644
 | ||||||
|  | --- a/hw/net/virtio-net.c
 | ||||||
|  | +++ b/hw/net/virtio-net.c
 | ||||||
|  | @@ -602,6 +602,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
 | ||||||
|  |   | ||||||
|  |      n->mergeable_rx_bufs = mergeable_rx_bufs; | ||||||
|  |   | ||||||
|  | +    /*
 | ||||||
|  | +     * Note: when extending the vnet header, please make sure to
 | ||||||
|  | +     * change the vnet header copying logic in virtio_net_flush_tx()
 | ||||||
|  | +     * as well.
 | ||||||
|  | +     */
 | ||||||
|  |      if (version_1) { | ||||||
|  |          n->guest_hdr_len = hash_report ? | ||||||
|  |              sizeof(struct virtio_net_hdr_v1_hash) : | ||||||
|  | @@ -2535,7 +2540,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
 | ||||||
|  |          ssize_t ret; | ||||||
|  |          unsigned int out_num; | ||||||
|  |          struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg; | ||||||
|  | -        struct virtio_net_hdr_mrg_rxbuf mhdr;
 | ||||||
|  | +        struct virtio_net_hdr_v1_hash vhdr;
 | ||||||
|  |   | ||||||
|  |          elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement)); | ||||||
|  |          if (!elem) { | ||||||
|  | @@ -2552,7 +2557,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
 | ||||||
|  |          } | ||||||
|  |   | ||||||
|  |          if (n->has_vnet_hdr) { | ||||||
|  | -            if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
 | ||||||
|  | +            if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
 | ||||||
|  |                  n->guest_hdr_len) { | ||||||
|  |                  virtio_error(vdev, "virtio-net header incorrect"); | ||||||
|  |                  virtqueue_detach_element(q->tx_vq, elem, 0); | ||||||
|  | @@ -2560,8 +2565,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
 | ||||||
|  |                  return -EINVAL; | ||||||
|  |              } | ||||||
|  |              if (n->needs_vnet_hdr_swap) { | ||||||
|  | -                virtio_net_hdr_swap(vdev, (void *) &mhdr);
 | ||||||
|  | -                sg2[0].iov_base = &mhdr;
 | ||||||
|  | +                virtio_net_hdr_swap(vdev, (void *) &vhdr);
 | ||||||
|  | +                sg2[0].iov_base = &vhdr;
 | ||||||
|  |                  sg2[0].iov_len = n->guest_hdr_len; | ||||||
|  |                  out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, | ||||||
|  |                                     out_sg, out_num, | ||||||
|  | -- 
 | ||||||
|  | 2.41.0 | ||||||
|  | 
 | ||||||
							
								
								
									
										49
									
								
								SOURCES/kvm-vnc-increase-max-display-size.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								SOURCES/kvm-vnc-increase-max-display-size.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | |||||||
|  | From a38e51982522910475ec051f81116639254a2955 Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  | Date: Thu, 30 May 2024 13:10:29 +0200 | ||||||
|  | Subject: [PATCH 5/5] vnc: increase max display size | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  | 
 | ||||||
|  | RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  | RH-MergeRequest: 391: vnc: increase max display size | ||||||
|  | RH-Jira: RHEL-50854 | ||||||
|  | RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com> | ||||||
|  | RH-Commit: [1/1] 8d79bbc6949ca7264f6701121b47e946eb8ac824 | ||||||
|  | 
 | ||||||
|  | Resolves: | ||||||
|  | https://issues.redhat.com/browse/RHEL-50854 | ||||||
|  | 
 | ||||||
|  | It's 2024.  4k display resolutions are a thing these days. | ||||||
|  | Raise width and height limits of the qemu vnc server. | ||||||
|  | 
 | ||||||
|  | Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1596 | ||||||
|  | Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> | ||||||
|  | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||||||
|  | Message-ID: <20240530111029.1726329-1-kraxel@redhat.com> | ||||||
|  | 
 | ||||||
|  | (cherry picked from commit 1f1736a8f16d27a99abd371caaeedc10e6411d15) | ||||||
|  | Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> | ||||||
|  | ---
 | ||||||
|  |  ui/vnc.h | 4 ++-- | ||||||
|  |  1 file changed, 2 insertions(+), 2 deletions(-) | ||||||
|  | 
 | ||||||
|  | diff --git a/ui/vnc.h b/ui/vnc.h
 | ||||||
|  | index a7149831f9..4d44957cc2 100644
 | ||||||
|  | --- a/ui/vnc.h
 | ||||||
|  | +++ b/ui/vnc.h
 | ||||||
|  | @@ -81,8 +81,8 @@ typedef void VncSendHextileTile(VncState *vs,
 | ||||||
|  |   | ||||||
|  |  /* VNC_MAX_WIDTH must be a multiple of VNC_DIRTY_PIXELS_PER_BIT. */ | ||||||
|  |   | ||||||
|  | -#define VNC_MAX_WIDTH ROUND_UP(2560, VNC_DIRTY_PIXELS_PER_BIT)
 | ||||||
|  | -#define VNC_MAX_HEIGHT 2048
 | ||||||
|  | +#define VNC_MAX_WIDTH ROUND_UP(5120, VNC_DIRTY_PIXELS_PER_BIT)
 | ||||||
|  | +#define VNC_MAX_HEIGHT 2160
 | ||||||
|  |   | ||||||
|  |  /* VNC_DIRTY_BITS is the number of bits in the dirty bitmap. */ | ||||||
|  |  #define VNC_DIRTY_BITS (VNC_MAX_WIDTH / VNC_DIRTY_PIXELS_PER_BIT) | ||||||
|  | -- 
 | ||||||
|  | 2.39.3 | ||||||
|  | 
 | ||||||
| @ -83,7 +83,7 @@ Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} | |||||||
| Summary: QEMU is a machine emulator and virtualizer | Summary: QEMU is a machine emulator and virtualizer | ||||||
| Name: qemu-kvm | Name: qemu-kvm | ||||||
| Version: 6.2.0 | Version: 6.2.0 | ||||||
| Release: 48%{?rcrel}%{?dist} | Release: 53%{?rcrel}%{?dist}.4 | ||||||
| # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped | # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped | ||||||
| Epoch: 15 | Epoch: 15 | ||||||
| License: GPLv2 and GPLv2+ and CC-BY | License: GPLv2 and GPLv2+ and CC-BY | ||||||
| @ -841,6 +841,68 @@ Patch339: kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch | |||||||
| Patch340: kvm-monitor-only-run-coroutine-commands-in-qemu_aio_cont.patch | Patch340: kvm-monitor-only-run-coroutine-commands-in-qemu_aio_cont.patch | ||||||
| # For RHEL-7353 - [qemu-kvm] no response with QMP command device_add when repeatedly hotplug/unplug virtio disks [RHEL-8] | # For RHEL-7353 - [qemu-kvm] no response with QMP command device_add when repeatedly hotplug/unplug virtio disks [RHEL-8] | ||||||
| Patch341: kvm-iotests-Make-144-deterministic-again.patch | Patch341: kvm-iotests-Make-144-deterministic-again.patch | ||||||
|  | # For RHEL-19628 - CVE-2023-6683 virt:rhel/qemu-kvm: QEMU: VNC: NULL pointer dereference in qemu_clipboard_request() [rhel-8] | ||||||
|  | Patch342: kvm-glib-compat-Introduce-g_memdup2-wrapper.patch | ||||||
|  | # For RHEL-19628 - CVE-2023-6683 virt:rhel/qemu-kvm: QEMU: VNC: NULL pointer dereference in qemu_clipboard_request() [rhel-8] | ||||||
|  | Patch343: kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch | ||||||
|  | # For RHEL-19496 - CVE-2023-6693 virt:rhel/qemu-kvm: QEMU: virtio-net: stack buffer overflow in virtio_net_flush_tx() [rhel-8] | ||||||
|  | Patch344: kvm-virtio-net-correctly-copy-vnet-header-when-flushing-.patch | ||||||
|  | # For RHEL-35616 - CVE-2024-4467 virt:rhel/qemu-kvm: QEMU: 'qemu-img info' leads to host file read/write [rhel-8.10.z] | ||||||
|  | Patch345: kvm-qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO.patch | ||||||
|  | # For RHEL-35616 - CVE-2024-4467 virt:rhel/qemu-kvm: QEMU: 'qemu-img info' leads to host file read/write [rhel-8.10.z] | ||||||
|  | Patch346: kvm-iotests-244-Don-t-store-data-file-with-protocol-in-i.patch | ||||||
|  | # For RHEL-35616 - CVE-2024-4467 virt:rhel/qemu-kvm: QEMU: 'qemu-img info' leads to host file read/write [rhel-8.10.z] | ||||||
|  | Patch347: kvm-iotests-270-Don-t-store-data-file-with-json-prefix-i.patch | ||||||
|  | # For RHEL-35616 - CVE-2024-4467 virt:rhel/qemu-kvm: QEMU: 'qemu-img info' leads to host file read/write [rhel-8.10.z] | ||||||
|  | Patch348: kvm-block-introduce-bdrv_open_file_child-helper.patch | ||||||
|  | # For RHEL-35616 - CVE-2024-4467 virt:rhel/qemu-kvm: QEMU: 'qemu-img info' leads to host file read/write [rhel-8.10.z] | ||||||
|  | Patch349: kvm-block-Parse-filenames-only-when-explicitly-requested.patch | ||||||
|  | # For RHEL-32276 - CVE-2024-3446 virt:rhel/qemu-kvm: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability [rhel-8] | ||||||
|  | Patch350: kvm-virtio-gpu-free-BHs-by-implementing-unrealize.patch | ||||||
|  | # For RHEL-32276 - CVE-2024-3446 virt:rhel/qemu-kvm: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability [rhel-8] | ||||||
|  | Patch351: kvm-virtio-gpu-reset-gfx-resources-in-main-thread.patch | ||||||
|  | # For RHEL-32276 - CVE-2024-3446 virt:rhel/qemu-kvm: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability [rhel-8] | ||||||
|  | Patch352: kvm-hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch | ||||||
|  | # For RHEL-32276 - CVE-2024-3446 virt:rhel/qemu-kvm: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability [rhel-8] | ||||||
|  | Patch353: kvm-hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch | ||||||
|  | # For RHEL-32276 - CVE-2024-3446 virt:rhel/qemu-kvm: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability [rhel-8] | ||||||
|  | Patch354: kvm-hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch | ||||||
|  | # For RHEL-32276 - CVE-2024-3446 virt:rhel/qemu-kvm: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability [rhel-8] | ||||||
|  | Patch355: kvm-hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch | ||||||
|  | # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] | ||||||
|  | Patch356: kvm-nbd-server-Plumb-in-new-args-to-nbd_client_add.patch | ||||||
|  | # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] | ||||||
|  | Patch357: kvm-nbd-server-CVE-2024-7409-Cap-default-max-connections.patch | ||||||
|  | # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] | ||||||
|  | Patch358: kvm-nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch | ||||||
|  | # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] | ||||||
|  | Patch359: kvm-nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch | ||||||
|  | # For RHEL-50854 - vnc: increase max display size to 4K | ||||||
|  | Patch360: kvm-vnc-increase-max-display-size.patch | ||||||
|  | # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] | ||||||
|  | Patch361: kvm-nbd-server-Favor-qemu_aio_context-over-iohandler-con.patch | ||||||
|  | # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] | ||||||
|  | Patch362: kvm-iotests-test-NBD-TLS-iothread.patch | ||||||
|  | # For RHEL-52611 - CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z] | ||||||
|  | Patch363: kvm-nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch | ||||||
|  | # For RHEL-60553 - Frequent VM pauses on OpenShift Virtualization with Portworx storage | ||||||
|  | Patch364: kvm-block-move-bdrv_qiov_is_aligned-to-file-posix.patch | ||||||
|  | # For RHEL-60553 - Frequent VM pauses on OpenShift Virtualization with Portworx storage | ||||||
|  | Patch365: kvm-block-use-the-request-length-for-iov-alignment.patch | ||||||
|  | # For RHEL-26197 - virtiofsd --help and manpage does not agree on --thread-pool-size default value | ||||||
|  | Patch366: kvm-Fix-thread-pool-size-default-value-in-the-man-page.patch | ||||||
|  | # For RHEL-59214 - qemu-ga cannot freeze filesystems with sentinelone | ||||||
|  | Patch367: kvm-qga-skip-bind-mounts-in-fs-list.patch | ||||||
|  | # For RHEL-88701 - [RHEL 8.10 qemu] KVM - Live migration of guest fails from z16-z17 [rhel-8.10.z] | ||||||
|  | Patch368: kvm-target-s390x-report-deprecated-props-in-cpu-model-ex.patch | ||||||
|  | # For RHEL-88701 - [RHEL 8.10 qemu] KVM - Live migration of guest fails from z16-z17 [rhel-8.10.z] | ||||||
|  | Patch369: kvm-target-s390x-flag-te-and-cte-as-deprecated.patch | ||||||
|  | # For RHEL-88701 - [RHEL 8.10 qemu] KVM - Live migration of guest fails from z16-z17 [rhel-8.10.z] | ||||||
|  | Patch370: kvm-target-s390x-filter-deprecated-properties-based-on-m.patch | ||||||
|  | # For RHEL-88701 - [RHEL 8.10 qemu] KVM - Live migration of guest fails from z16-z17 [rhel-8.10.z] | ||||||
|  | Patch371: kvm-target-s390x-move-deprecated-props-to-CpuModelExpans.patch | ||||||
|  | # For RHEL-88701 - [RHEL 8.10 qemu] KVM - Live migration of guest fails from z16-z17 [rhel-8.10.z] | ||||||
|  | Patch372: kvm-redhat-Adjust-indentation-in-qapi-machine-target.jso.patch | ||||||
| 
 | 
 | ||||||
| BuildRequires: wget | BuildRequires: wget | ||||||
| BuildRequires: rpm-build | BuildRequires: rpm-build | ||||||
| @ -2010,6 +2072,77 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Mon May 05 2025 Jon Maloy <jmaloy@redhat.com> - 6.2.0-53.el8.4 | ||||||
|  | - kvm-target-s390x-report-deprecated-props-in-cpu-model-ex.patch [RHEL-88701] | ||||||
|  | - kvm-target-s390x-flag-te-and-cte-as-deprecated.patch [RHEL-88701] | ||||||
|  | - kvm-target-s390x-filter-deprecated-properties-based-on-m.patch [RHEL-88701] | ||||||
|  | - kvm-target-s390x-move-deprecated-props-to-CpuModelExpans.patch [RHEL-88701] | ||||||
|  | - kvm-redhat-Adjust-indentation-in-qapi-machine-target.jso.patch [RHEL-88701] | ||||||
|  | - Resolves: RHEL-88701 | ||||||
|  |   ([RHEL 8.10 qemu] KVM - Live migration of guest fails from z16-z17 [rhel-8.10.z]) | ||||||
|  | 
 | ||||||
|  | * Sun Jan 05 2025 Jon Maloy <jmaloy@redhat.com> - 6.2.0-53.el8.3 | ||||||
|  | - kvm-qga-skip-bind-mounts-in-fs-list.patch [RHEL-59214] | ||||||
|  | - Resolves: RHEL-59214 | ||||||
|  |   (qemu-ga cannot freeze filesystems with sentinelone) | ||||||
|  | 
 | ||||||
|  | * Tue Oct 15 2024 Jon Maloy <jmaloy@redhat.com> - 6.2.0-53.el8.2 | ||||||
|  | - kvm-Fix-thread-pool-size-default-value-in-the-man-page.patch [RHEL-26197] | ||||||
|  | - Resolves: RHEL-26197 | ||||||
|  |   (virtiofsd --help and manpage does not agree on --thread-pool-size default value) | ||||||
|  | 
 | ||||||
|  | * Tue Oct 08 2024 Jon Maloy <jmaloy@redhat.com> - 6.2.0-53.el8.1 | ||||||
|  | - kvm-block-move-bdrv_qiov_is_aligned-to-file-posix.patch [RHEL-60553] | ||||||
|  | - kvm-block-use-the-request-length-for-iov-alignment.patch [RHEL-60553] | ||||||
|  | - Resolves: RHEL-60553 | ||||||
|  |   (Frequent VM pauses on OpenShift Virtualization with Portworx storage) | ||||||
|  | 
 | ||||||
|  | * Thu Sep 05 2024 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-53.el8 | ||||||
|  | - kvm-nbd-server-Favor-qemu_aio_context-over-iohandler-con.patch [RHEL-52611] | ||||||
|  | - kvm-iotests-test-NBD-TLS-iothread.patch [RHEL-52611] | ||||||
|  | - kvm-nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch [RHEL-52611] | ||||||
|  | - Resolves: RHEL-52611 | ||||||
|  |   (CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z]) | ||||||
|  | 
 | ||||||
|  | * Wed Aug 21 2024 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-52.el8 | ||||||
|  | - kvm-nbd-server-Plumb-in-new-args-to-nbd_client_add.patch [RHEL-52611] | ||||||
|  | - kvm-nbd-server-CVE-2024-7409-Cap-default-max-connections.patch [RHEL-52611] | ||||||
|  | - kvm-nbd-server-CVE-2024-7409-Drop-non-negotiating-client.patch [RHEL-52611] | ||||||
|  | - kvm-nbd-server-CVE-2024-7409-Close-stray-clients-at-serv.patch [RHEL-52611] | ||||||
|  | - kvm-vnc-increase-max-display-size.patch [RHEL-50854] | ||||||
|  | - Resolves: RHEL-52611 | ||||||
|  |   (CVE-2024-7409 virt:rhel/qemu-kvm: Denial of Service via Improper Synchronization in QEMU NBD Server During Socket Closure [rhel-8.10.z]) | ||||||
|  | - Resolves: RHEL-50854 | ||||||
|  |   (vnc: increase max display size to 4K) | ||||||
|  | 
 | ||||||
|  | * Mon Jul 29 2024 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-51.el8 | ||||||
|  | - kvm-virtio-gpu-free-BHs-by-implementing-unrealize.patch [RHEL-32276] | ||||||
|  | - kvm-virtio-gpu-reset-gfx-resources-in-main-thread.patch [RHEL-32276] | ||||||
|  | - kvm-hw-virtio-Introduce-virtio_bh_new_guarded-helper.patch [RHEL-32276] | ||||||
|  | - kvm-hw-display-virtio-gpu-Protect-from-DMA-re-entrancy-b.patch [RHEL-32276] | ||||||
|  | - kvm-hw-char-virtio-serial-bus-Protect-from-DMA-re-entran.patch [RHEL-32276] | ||||||
|  | - kvm-hw-virtio-virtio-crypto-Protect-from-DMA-re-entrancy.patch [RHEL-32276] | ||||||
|  | - Resolves: RHEL-32276 | ||||||
|  |   (CVE-2024-3446 virt:rhel/qemu-kvm: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability [rhel-8]) | ||||||
|  | 
 | ||||||
|  | * Thu Jul 04 2024 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-50 | ||||||
|  | - kvm-qcow2-Don-t-open-data_file-with-BDRV_O_NO_IO.patch [RHEL-35616] | ||||||
|  | - kvm-iotests-244-Don-t-store-data-file-with-protocol-in-i.patch [RHEL-35616] | ||||||
|  | - kvm-iotests-270-Don-t-store-data-file-with-json-prefix-i.patch [RHEL-35616] | ||||||
|  | - kvm-block-introduce-bdrv_open_file_child-helper.patch [RHEL-35616] | ||||||
|  | - kvm-block-Parse-filenames-only-when-explicitly-requested.patch [RHEL-35616] | ||||||
|  | - Resolves: RHEL-35616 | ||||||
|  |   (CVE-2024-4467 virt:rhel/qemu-kvm: QEMU: 'qemu-img info' leads to host file read/write [rhel-8.10.z]) | ||||||
|  | 
 | ||||||
|  | * Thu Mar 14 2024 Jon Maloy <jmaloy@redhat.com> - 6.2.0-49 | ||||||
|  | - kvm-glib-compat-Introduce-g_memdup2-wrapper.patch [RHEL-19628] | ||||||
|  | - kvm-ui-clipboard-mark-type-as-not-available-when-there-i.patch [RHEL-19628] | ||||||
|  | - kvm-virtio-net-correctly-copy-vnet-header-when-flushing-.patch [RHEL-19496] | ||||||
|  | - Resolves: RHEL-19628 | ||||||
|  |   (CVE-2023-6683 virt:rhel/qemu-kvm: QEMU: VNC: NULL pointer dereference in qemu_clipboard_request() [rhel-8]) | ||||||
|  | - Resolves: RHEL-19496 | ||||||
|  |   (CVE-2023-6693 virt:rhel/qemu-kvm: QEMU: virtio-net: stack buffer overflow in virtio_net_flush_tx() [rhel-8]) | ||||||
|  | 
 | ||||||
| * Mon Feb 26 2024 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-48 | * Mon Feb 26 2024 Miroslav Rezanina <mrezanin@redhat.com> - 6.2.0-48 | ||||||
| - kvm-iotests-add-filter_qmp_generated_node_ids.patch [RHEL-7353] | - kvm-iotests-add-filter_qmp_generated_node_ids.patch [RHEL-7353] | ||||||
| - kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch [RHEL-7353] | - kvm-iotests-port-141-to-Python-for-reliable-QMP-testing.patch [RHEL-7353] | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user