Skip to content

Commit 9a36e91

Browse files
committed
Fix use after free in NBD server
Signed-off-by: Mark Syms <[email protected]>
1 parent 71e2207 commit 9a36e91

File tree

2 files changed

+15
-13
lines changed

2 files changed

+15
-13
lines changed

drivers/tapdisk-nbdserver.c

+14-12
Original file line numberDiff line numberDiff line change
@@ -283,17 +283,19 @@ tapdisk_nbdserver_set_free_request(td_nbdserver_client_t *client,
283283

284284
void
285285
tapdisk_nbdserver_free_request(td_nbdserver_client_t *client,
286-
td_nbdserver_req_t *req)
286+
td_nbdserver_req_t *req, bool free_client_if_dead)
287287
{
288288
tapdisk_nbdserver_set_free_request(client, req);
289-
if (unlikely(client->dead && !tapdisk_nbdserver_reqs_pending(client)))
290-
tapdisk_nbdserver_free_client(client);
291289

292290
if (unlikely(client->n_reqs_free == (client->n_reqs / 4))) {
293291
/* free requests, unmask the events */
294292
tapdisk_server_mask_event(client->client_event_id, 0);
295293
}
296294

295+
if (unlikely(free_client_if_dead &&
296+
client->dead &&
297+
!tapdisk_nbdserver_reqs_pending(client)))
298+
tapdisk_nbdserver_free_client(client);
297299
}
298300

299301
static void
@@ -835,11 +837,12 @@ static void
835837
return &(((struct sockaddr_in6*)ss)->sin6_addr);
836838
}
837839

838-
static void tapdisk_nbd_server_free_vreq(td_nbdserver_client_t *client, td_vbd_request_t *vreq)
840+
static void tapdisk_nbd_server_free_vreq(
841+
td_nbdserver_client_t *client, td_vbd_request_t *vreq, bool free_client_if_dead)
839842
{
840843
td_nbdserver_req_t *req = container_of(vreq, td_nbdserver_req_t, vreq);
841844
free(vreq->iov->base);
842-
tapdisk_nbdserver_free_request(client, req);
845+
tapdisk_nbdserver_free_request(client, req, free_client_if_dead);
843846
}
844847

845848

@@ -852,7 +855,7 @@ __tapdisk_nbdserver_block_status_cb(td_vbd_request_t *vreq, int err,
852855
tapdisk_extents_t* extents = (tapdisk_extents_t *)(vreq->data);
853856
send_structured_reply_block_status (client->client_fd, req->id, extents);
854857
free_extents(extents);
855-
tapdisk_nbd_server_free_vreq(client, vreq);
858+
tapdisk_nbd_server_free_vreq(client, vreq, true);
856859
}
857860

858861
static int
@@ -936,7 +939,7 @@ __tapdisk_nbdserver_structured_read_cb(
936939

937940
finish:
938941
free(vreq->iov->base);
939-
tapdisk_nbdserver_free_request(client, req);
942+
tapdisk_nbdserver_free_request(client, req, true);
940943
}
941944

942945
static void
@@ -1001,7 +1004,7 @@ __tapdisk_nbdserver_request_cb(td_vbd_request_t *vreq, int error,
10011004

10021005
finish:
10031006
free(vreq->iov->base);
1004-
tapdisk_nbdserver_free_request(client, req);
1007+
tapdisk_nbdserver_free_request(client, req, true);
10051008
}
10061009

10071010
void
@@ -1265,7 +1268,7 @@ tapdisk_nbdserver_clientcb(event_id_t id, char mode, void *data)
12651268
INFO("About to send initial connection message");
12661269
tapdisk_nbdserver_newclient_fd(server, fd);
12671270
INFO("Sent initial connection message");
1268-
goto free;
1271+
return;
12691272
case TAPDISK_NBD_CMD_BLOCK_STATUS:
12701273
{
12711274
if (!client->structured_reply)
@@ -1306,11 +1309,10 @@ tapdisk_nbdserver_clientcb(event_id_t id, char mode, void *data)
13061309
return;
13071310

13081311
fail:
1309-
tapdisk_nbdserver_free_client(client);
1310-
free:
13111312
if (vreq)
1312-
tapdisk_nbd_server_free_vreq(client, vreq);
1313+
tapdisk_nbd_server_free_vreq(client, vreq, false);
13131314

1315+
tapdisk_nbdserver_free_client(client);
13141316
return;
13151317
}
13161318

drivers/tapdisk-nbdserver.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ bool tapdisk_nbdserver_contains_client(td_nbdserver_t *server,
188188
td_nbdserver_req_t *tapdisk_nbdserver_alloc_request(
189189
td_nbdserver_client_t *client);
190190
void tapdisk_nbdserver_free_request(td_nbdserver_client_t *client,
191-
td_nbdserver_req_t *req);
191+
td_nbdserver_req_t *req, bool free_client_if_dead);
192192

193193
/**
194194
* Tells how many requests are pending.

0 commit comments

Comments
 (0)