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 <ebl...@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