Although defaulting the handshake limit to 10 seconds was a nice QoI
change to weed out intentionally slow clients, it can interfere with
integration testing done with manual NBD_OPT commands over 'nbdsh
--opt-mode'. Expose a QMP knob to allow the user to alter the timeout
away from the default.
Signed-off-by: Eric Blake <eblake@redhat.com>
---
I'm not sure if this is 9.1 material. It is a new feature
(user-visible QMP addition) implemented after soft freeze; on the
other hand, it allows one to recover the behavior that existed prior
to plugging the CVE which may be useful in integration testing.
---
qapi/block-export.json | 14 ++++++++++++--
include/block/nbd.h | 2 +-
block/monitor/block-hmp-cmds.c | 2 +-
blockdev-nbd.c | 19 ++++++++++++++-----
4 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/qapi/block-export.json b/qapi/block-export.json
index ce33fe378df..b485b380f1a 100644
--- a/qapi/block-export.json
+++ b/qapi/block-export.json
@@ -30,13 +30,18 @@
# server from advertising multiple client support (since 5.2;
# default: 100)
#
+# @handshake-limit: Time limit, in seconds, at which a client that
+# has not completed the negotiation handshake will be disconnected,
+# or 0 for no limit (since 9.1; default: 10).
+#
# Since: 4.2
##
{ 'struct': 'NbdServerOptions',
'data': { 'addr': 'SocketAddress',
'*tls-creds': 'str',
'*tls-authz': 'str',
- '*max-connections': 'uint32' } }
+ '*max-connections': 'uint32',
+ '*handshake-limit': 'uint32' } }
##
# @nbd-server-start:
@@ -65,6 +70,10 @@
# server from advertising multiple client support (since 5.2;
# default: 100).
#
+# @handshake-limit: Time limit, in seconds, at which a client that
+# has not completed the negotiation handshake will be disconnected,
+# or 0 for no limit (since 9.1; default: 10).
+#
# Errors:
# - if the server is already running
#
@@ -74,7 +83,8 @@
'data': { 'addr': 'SocketAddressLegacy',
'*tls-creds': 'str',
'*tls-authz': 'str',
- '*max-connections': 'uint32' },
+ '*max-connections': 'uint32',
+ '*handshake-limit': 'uint32' },
'allow-preconfig': true }
##
diff --git a/include/block/nbd.h b/include/block/nbd.h
index fd5044359dc..22071aea797 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -430,7 +430,7 @@ bool nbd_server_is_running(void);
int nbd_server_max_connections(void);
void nbd_server_start(SocketAddress *addr, const char *tls_creds,
const char *tls_authz, uint32_t max_connections,
- Error **errp);
+ uint32_t handshake_limit, Error **errp);
void nbd_server_start_options(NbdServerOptions *arg, Error **errp);
/* nbd_read
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index bdf2eb50b68..a258e029f78 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -403,7 +403,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
}
nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS,
- &local_err);
+ NBD_DEFAULT_HANDSHAKE_LIMIT, &local_err);
qapi_free_SocketAddress(addr);
if (local_err != NULL) {
goto exit;
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 4e38ff46747..ad21bd1412d 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -30,6 +30,7 @@ typedef struct NBDServerData {
QIONetListener *listener;
QCryptoTLSCreds *tlscreds;
char *tlsauthz;
+ uint32_t handshake_limit;
uint32_t max_connections;
uint32_t connections;
QLIST_HEAD(, NBDConn) conns;
@@ -84,8 +85,7 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
nbd_update_server_watch(nbd_server);
qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
- /* TODO - expose handshake limit as QMP option */
- nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_LIMIT,
+ nbd_client_new(cioc, nbd_server->handshake_limit,
nbd_server->tlscreds, nbd_server->tlsauthz,
nbd_blockdev_client_closed, conn);
}
@@ -160,7 +160,7 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
void nbd_server_start(SocketAddress *addr, const char *tls_creds,
const char *tls_authz, uint32_t max_connections,
- Error **errp)
+ uint32_t handshake_limit, Error **errp)
{
if (nbd_server) {
error_setg(errp, "NBD server already running");
@@ -169,6 +169,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->handshake_limit = handshake_limit;
nbd_server->listener = qio_net_listener_new();
qio_net_listener_set_name(nbd_server->listener,
@@ -206,15 +207,19 @@ void nbd_server_start_options(NbdServerOptions *arg, Error **errp)
if (!arg->has_max_connections) {
arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
}
+ if (!arg->has_handshake_limit) {
+ arg->handshake_limit = NBD_DEFAULT_HANDSHAKE_LIMIT;
+ }
nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz,
- arg->max_connections, errp);
+ arg->max_connections, arg->handshake_limit, errp);
}
void qmp_nbd_server_start(SocketAddressLegacy *addr,
const char *tls_creds,
const char *tls_authz,
bool has_max_connections, uint32_t max_connections,
+ bool has_handshake_limit, uint32_t handshake_limit,
Error **errp)
{
SocketAddress *addr_flat = socket_address_flatten(addr);
@@ -222,8 +227,12 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
if (!has_max_connections) {
max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
}
+ if (!has_handshake_limit) {
+ handshake_limit = NBD_DEFAULT_HANDSHAKE_LIMIT;
+ }
- nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp);
+ nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections,
+ handshake_limit, errp);
qapi_free_SocketAddress(addr_flat);
}
--
2.45.2
© 2016 - 2024 Red Hat, Inc.