forked from rpms/qemu-kvm
c8-stream-rhel
imports/c8-stream-rhel/qemu-kvm-6.2.0-53.module+el8.10.0+22268+f82ccd96
parent
2041a12750
commit
1d7e016b3b
@ -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,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
|
||||
|
Loading…
Reference in new issue