qemu/xen-block-Fix-double-qlist-remove-and-re.patch

156 lines
5.4 KiB
Diff
Raw Normal View History

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 22:48:15 +02:00
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;
}