qemu/xen-block-Fix-double-qlist-remove-and-re.patch
Bruce Rogers 7325eaecfb Accepting request 795118 from home:bfrogers:branches:Virtualization
- Include upstream patches targeted for the next stable release
  (bug fixes only)
  spapr-Fix-failure-path-for-attempting-to.patch
  target-i386-do-not-set-unsupported-VMX-s.patch
  target-xtensa-fix-pasto-in-pfwait.r-opco.patch
  tcg-i386-Fix-INDEX_op_dup2_vec.patch
  tcg-mips-mips-sync-encode-error.patch
  vhost-user-gpu-Release-memory-returned-b.patch
  vpc-Don-t-round-up-already-aligned-BAT-s.patch
  xen-block-Fix-double-qlist-remove-and-re.patch
- Fix bug causing weak encryption in PAuth for ARM
  (CVE-2020-10702 bsc#1168681)
  target-arm-Fix-PAuth-sbox-functions.patch
- Fix OOB in tulip NIC emulation (CVE-2020-11102 bsc#1168713
  net-tulip-check-frame-size-and-r-w-data-.patch
- Note that previously included patch addresses CVE-2020-1711
  and bsc#1166240
  iscsi-Cap-block-count-from-GET-LBA-STATU.patch
- Include performance improvement (and related?) patch
  aio-wait-delegate-polling-of-main-AioCon.patch
  async-use-explicit-memory-barriers.patch
- Rework previous patch at Olaf H.'s direction
  hw-i386-disable-smbus-migration-for-xenf.patch
- Eliminate is_opensuse usage in producing seabios version string
  what we are doing here is just replacing the upstream string
  with one indicating that the openSUSE build service built it,
  and so just leave it as "-rebuilt.opensuse.org"
- Alter algorithm used to produce "unique" symbol for coordinating
  qemu with the optional modules it may load. This is a reasonable
  relaxation for broader compatibility
  configure-remove-pkgversion-from-CONFIG_.patch
- Tweak supported.*.txt for latest deprecations, and other fixes
- Tweak update_git.sh, config.sh
- One more fix is needed for: s390x Protected Virtualization support
  - start and control guest in secure mode (bsc#1167075 jsc#SLE-7407)
  s390x-s390-virtio-ccw-Fix-build-on-syste.patch

OBS-URL: https://build.opensuse.org/request/show/795118
OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=542
2020-04-17 20:48:15 +00:00

156 lines
5.4 KiB
Diff

From: Anthony PERARD <anthony.perard@citrix.com>
Date: Mon, 6 Apr 2020 15:02:17 +0100
Subject: xen-block: Fix double qlist remove and request leak
Git-commit: 36d883ba0de8a281072ded2b51e0a711fd002139
Commit a31ca6801c02 ("qemu/queue.h: clear linked list pointers on
remove") revealed that a request was removed twice from a list, once
in xen_block_finish_request() and a second time in
xen_block_release_request() when both function are called from
xen_block_complete_aio(). But also, the `requests_inflight' counter is
decreased twice, and thus became negative.
This is a bug that was introduced in bfd0d6366043 ("xen-block: improve
response latency"), where a `finished' list was removed.
That commit also introduced a leak of request in xen_block_do_aio().
That function calls xen_block_finish_request() but the request is
never released after that.
To fix both issue, we do two changes:
- we squash finish_request() and release_request() together as we want
to remove a request from 'inflight' list to add it to 'freelist'.
- before releasing a request, we need to let the other end know the
result, thus we should call xen_block_send_response() before
releasing a request.
The first change fixes the double QLIST_REMOVE() as we remove the extra
call. The second change makes the leak go away because if we want to
call finish_request(), we need to call a function that does all of
finish, send response, and release.
Fixes: bfd0d6366043 ("xen-block: improve response latency")
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Message-Id: <20200406140217.1441858-1-anthony.perard@citrix.com>
Reviewed-by: Paul Durrant <paul@xen.org>
[mreitz: Amended commit message as per Paul's suggestions]
Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
hw/block/dataplane/xen-block.c | 48 ++++++++++++----------------------
1 file changed, 16 insertions(+), 32 deletions(-)
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index 3b9caeb2fa00a1f4eb338fca7a89..c4ed2870ecd779bf40eb4f3eded3 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -64,6 +64,8 @@ struct XenBlockDataPlane {
AioContext *ctx;
};
+static int xen_block_send_response(XenBlockRequest *request);
+
static void reset_request(XenBlockRequest *request)
{
memset(&request->req, 0, sizeof(request->req));
@@ -115,23 +117,26 @@ out:
return request;
}
-static void xen_block_finish_request(XenBlockRequest *request)
+static void xen_block_complete_request(XenBlockRequest *request)
{
XenBlockDataPlane *dataplane = request->dataplane;
- QLIST_REMOVE(request, list);
- dataplane->requests_inflight--;
-}
+ if (xen_block_send_response(request)) {
+ Error *local_err = NULL;
-static void xen_block_release_request(XenBlockRequest *request)
-{
- XenBlockDataPlane *dataplane = request->dataplane;
+ xen_device_notify_event_channel(dataplane->xendev,
+ dataplane->event_channel,
+ &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ }
+ }
QLIST_REMOVE(request, list);
+ dataplane->requests_inflight--;
reset_request(request);
request->dataplane = dataplane;
QLIST_INSERT_HEAD(&dataplane->freelist, request, list);
- dataplane->requests_inflight--;
}
/*
@@ -246,7 +251,6 @@ static int xen_block_copy_request(XenBlockRequest *request)
}
static int xen_block_do_aio(XenBlockRequest *request);
-static int xen_block_send_response(XenBlockRequest *request);
static void xen_block_complete_aio(void *opaque, int ret)
{
@@ -286,7 +290,6 @@ static void xen_block_complete_aio(void *opaque, int ret)
}
request->status = request->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
- xen_block_finish_request(request);
switch (request->req.operation) {
case BLKIF_OP_WRITE:
@@ -306,17 +309,8 @@ static void xen_block_complete_aio(void *opaque, int ret)
default:
break;
}
- if (xen_block_send_response(request)) {
- Error *local_err = NULL;
- xen_device_notify_event_channel(dataplane->xendev,
- dataplane->event_channel,
- &local_err);
- if (local_err) {
- error_report_err(local_err);
- }
- }
- xen_block_release_request(request);
+ xen_block_complete_request(request);
if (dataplane->more_work) {
qemu_bh_schedule(dataplane->bh);
@@ -420,8 +414,8 @@ static int xen_block_do_aio(XenBlockRequest *request)
return 0;
err:
- xen_block_finish_request(request);
request->status = BLKIF_RSP_ERROR;
+ xen_block_complete_request(request);
return -1;
}
@@ -575,17 +569,7 @@ static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
break;
};
- if (xen_block_send_response(request)) {
- Error *local_err = NULL;
-
- xen_device_notify_event_channel(dataplane->xendev,
- dataplane->event_channel,
- &local_err);
- if (local_err) {
- error_report_err(local_err);
- }
- }
- xen_block_release_request(request);
+ xen_block_complete_request(request);
continue;
}