Skip to content

Commit fb1c2aa

Browse files
committed
nbd/server: Plumb in new args to nbd_client_add()
Upcoming patches to fix a CVE need to track an opaque pointer passed in by the owner of a client object, as well as request for a time limit on how fast negotiation must complete. Prepare for that by changing the signature of nbd_client_new() and adding an accessor to get at the opaque pointer, although for now the two servers (qemu-nbd.c and blockdev-nbd.c) do not change behavior even though they pass in a new default timeout value. Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Signed-off-by: Eric Blake <eblake@redhat.com> Message-ID: <20240807174943.771624-11-eblake@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> [eblake: s/LIMIT/MAX_SECS/ as suggested by Dan] Signed-off-by: Eric Blake <eblake@redhat.com>
1 parent c719573 commit fb1c2aa

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

blockdev-nbd.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
6464
nbd_update_server_watch(nbd_server);
6565

6666
qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
67-
nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz,
68-
nbd_blockdev_client_closed);
67+
/* TODO - expose handshake timeout as QMP option */
68+
nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
69+
nbd_server->tlscreds, nbd_server->tlsauthz,
70+
nbd_blockdev_client_closed, NULL);
6971
}
7072

7173
static void nbd_update_server_watch(NBDServerData *s)

include/block/nbd.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ typedef struct NBDMetaContexts NBDMetaContexts;
3333

3434
extern const BlockExportDriver blk_exp_nbd;
3535

36+
/*
37+
* NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must
38+
* succeed at NBD_OPT_GO before being forcefully dropped as too slow.
39+
*/
40+
#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10
41+
3642
/* Handshake phase structs - this struct is passed on the wire */
3743

3844
typedef struct NBDOption {
@@ -403,9 +409,12 @@ AioContext *nbd_export_aio_context(NBDExport *exp);
403409
NBDExport *nbd_export_find(const char *name);
404410

405411
void nbd_client_new(QIOChannelSocket *sioc,
412+
uint32_t handshake_max_secs,
406413
QCryptoTLSCreds *tlscreds,
407414
const char *tlsauthz,
408-
void (*close_fn)(NBDClient *, bool));
415+
void (*close_fn)(NBDClient *, bool),
416+
void *owner);
417+
void *nbd_client_owner(NBDClient *client);
409418
void nbd_client_get(NBDClient *client);
410419
void nbd_client_put(NBDClient *client);
411420

nbd/server.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,14 @@ struct NBDMetaContexts {
124124
struct NBDClient {
125125
int refcount; /* atomic */
126126
void (*close_fn)(NBDClient *client, bool negotiated);
127+
void *owner;
127128

128129
QemuMutex lock;
129130

130131
NBDExport *exp;
131132
QCryptoTLSCreds *tlscreds;
132133
char *tlsauthz;
134+
uint32_t handshake_max_secs;
133135
QIOChannelSocket *sioc; /* The underlying data channel */
134136
QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
135137

@@ -3191,6 +3193,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
31913193

31923194
qemu_co_mutex_init(&client->send_lock);
31933195

3196+
/* TODO - utilize client->handshake_max_secs */
31943197
if (nbd_negotiate(client, &local_err)) {
31953198
if (local_err) {
31963199
error_report_err(local_err);
@@ -3205,14 +3208,17 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
32053208
}
32063209

32073210
/*
3208-
* Create a new client listener using the given channel @sioc.
3211+
* Create a new client listener using the given channel @sioc and @owner.
32093212
* Begin servicing it in a coroutine. When the connection closes, call
3210-
* @close_fn with an indication of whether the client completed negotiation.
3213+
* @close_fn with an indication of whether the client completed negotiation
3214+
* within @handshake_max_secs seconds (0 for unbounded).
32113215
*/
32123216
void nbd_client_new(QIOChannelSocket *sioc,
3217+
uint32_t handshake_max_secs,
32133218
QCryptoTLSCreds *tlscreds,
32143219
const char *tlsauthz,
3215-
void (*close_fn)(NBDClient *, bool))
3220+
void (*close_fn)(NBDClient *, bool),
3221+
void *owner)
32163222
{
32173223
NBDClient *client;
32183224
Coroutine *co;
@@ -3225,13 +3231,21 @@ void nbd_client_new(QIOChannelSocket *sioc,
32253231
object_ref(OBJECT(client->tlscreds));
32263232
}
32273233
client->tlsauthz = g_strdup(tlsauthz);
3234+
client->handshake_max_secs = handshake_max_secs;
32283235
client->sioc = sioc;
32293236
qio_channel_set_delay(QIO_CHANNEL(sioc), false);
32303237
object_ref(OBJECT(client->sioc));
32313238
client->ioc = QIO_CHANNEL(sioc);
32323239
object_ref(OBJECT(client->ioc));
32333240
client->close_fn = close_fn;
3241+
client->owner = owner;
32343242

32353243
co = qemu_coroutine_create(nbd_co_client_start, client);
32363244
qemu_coroutine_enter(co);
32373245
}
3246+
3247+
void *
3248+
nbd_client_owner(NBDClient *client)
3249+
{
3250+
return client->owner;
3251+
}

qemu-nbd.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,9 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
390390

391391
nb_fds++;
392392
nbd_update_server_watch();
393-
nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed);
393+
/* TODO - expose handshake timeout as command line option */
394+
nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
395+
tlscreds, tlsauthz, nbd_client_closed, NULL);
394396
}
395397

396398
static void nbd_update_server_watch(void)

0 commit comments

Comments
 (0)