File 0290-nbd-Add-max-connections-to-nbd-serv.patch of Package qemu
From: Kevin Wolf <kwolf@redhat.com>
Date: Thu, 24 Sep 2020 17:26:54 +0200
Subject: nbd: Add max-connections to nbd-server-start (bsc#1229007,
bsc#1245423, CVE-2024-7409)
This is a QMP equivalent of qemu-nbd's --shared option, limiting the
maximum number of clients that can attach at the same time.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200924152717.287415-9-kwolf@redhat.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 1c8222b014484145d66740d0597ae86b4a989b73)
References: bsc#1229007, bsc#1245423
References: CVE-2024-7409
Signed-off-by: Lin Ma <lma@suse.de>
---
blockdev-nbd.c | 29 +++++++++++++++++++++++------
hmp.c | 2 +-
include/block/nbd.h | 2 +-
qapi/block.json | 5 ++++-
4 files changed, 29 insertions(+), 9 deletions(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 12c57df258935b588ba5194f77b8..9d3fd79dde4ecbae72fcd564328f 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -23,18 +23,28 @@
typedef struct NBDServerData {
QIONetListener *listener;
QCryptoTLSCreds *tlscreds;
+ uint32_t max_connections;
+ uint32_t connections;
} NBDServerData;
static NBDServerData *nbd_server;
+static void nbd_update_server_watch(NBDServerData *s);
+
static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
{
nbd_client_put(client);
+ assert(nbd_server->connections > 0);
+ nbd_server->connections--;
+ nbd_update_server_watch(nbd_server);
}
static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
gpointer opaque)
{
+ nbd_server->connections++;
+ 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,
@@ -42,6 +52,14 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
nbd_blockdev_client_closed, NULL);
}
+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);
+ }
+}
static void nbd_server_free(NBDServerData *server)
{
@@ -89,7 +107,7 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
void nbd_server_start(SocketAddress *addr, const char *tls_creds,
- Error **errp)
+ uint32_t max_connections, Error **errp)
{
if (nbd_server) {
error_setg(errp, "NBD server already running");
@@ -97,6 +115,7 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
}
nbd_server = g_new0(NBDServerData, 1);
+ nbd_server->max_connections = max_connections;
nbd_server->listener = qio_net_listener_new();
qio_net_listener_set_name(nbd_server->listener,
@@ -119,10 +138,7 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
}
}
- qio_net_listener_set_client_func(nbd_server->listener,
- nbd_accept,
- NULL,
- NULL);
+ nbd_update_server_watch(nbd_server);
return;
@@ -133,11 +149,12 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
void qmp_nbd_server_start(SocketAddressLegacy *addr,
bool has_tls_creds, const char *tls_creds,
+ bool has_max_connections, uint32_t max_connections,
Error **errp)
{
SocketAddress *addr_flat = socket_address_flatten(addr);
- nbd_server_start(addr_flat, tls_creds, errp);
+ nbd_server_start(addr_flat, tls_creds, max_connections, errp);
qapi_free_SocketAddress(addr_flat);
}
diff --git a/hmp.c b/hmp.c
index 7828f93a3945ba6baeb752dfb31d..8dbfa6e0802d3b10ebde39042131 100644
--- a/hmp.c
+++ b/hmp.c
@@ -2302,7 +2302,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
goto exit;
}
- nbd_server_start(addr, NULL, &local_err);
+ nbd_server_start(addr, NULL, 0, &local_err);
qapi_free_SocketAddress(addr);
if (local_err != NULL) {
goto exit;
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 1cd79071e43e66b2851cfef1b709..3df3220bd0bf0bec6c5cd56da118 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -327,7 +327,7 @@ void nbd_client_get(NBDClient *client);
void nbd_client_put(NBDClient *client);
void nbd_server_start(SocketAddress *addr, const char *tls_creds,
- Error **errp);
+ uint32_t max_connections, Error **errp);
void nbd_export_bitmap(NBDExport *exp, const char *bitmap,
const char *bitmap_export_name, Error **errp);
diff --git a/qapi/block.json b/qapi/block.json
index 11f01f28efe68c8ee69d897873db..e55fd4f254053750b06f775e6f3c 100644
--- a/qapi/block.json
+++ b/qapi/block.json
@@ -225,6 +225,8 @@
#
# @addr: Address on which to listen.
# @tls-creds: (optional) ID of the TLS credentials object. Since 2.6
+# @max-connections: The maximum number of connections to allow at the same
+# time, 0 for unlimited. (since 5.2; default: 0)
#
# Returns: error if the server is already running.
#
@@ -232,7 +234,8 @@
##
{ 'command': 'nbd-server-start',
'data': { 'addr': 'SocketAddressLegacy',
- '*tls-creds': 'str'} }
+ '*tls-creds': 'str',
+ '*max-connections': 'uint32' } }
##
# @nbd-server-add: