Commit fd8788eb authored by Witold Krecicki's avatar Witold Krecicki

Fix possible race in socket destruction.

When two threads unreferenced handles coming from one socket while
the socket was being destructed we could get a use-after-free:
Having handle H1 coming from socket S1, H2 coming from socket S2,
S0 being a parent socket to S1 and S2:

Thread A                             Thread B
Unref handle H1                      Unref handle H2
Remove H1 from S1 active handles     Remove H2 from S2 active handles
nmsocket_maybe_destroy(S1)           nmsocket_maybe_destroy(S2)
nmsocket_maybe_destroy(S0)           nmsocket_maybe_destroy(S0)
LOCK(S0->lock)
Go through all children, figure
out that we have no more active
handles:
sum of S0->children[i]->ah == 0
UNLOCK(S0->lock)
destroy(S0)
                                     LOCK(S0->lock)
                                      - but S0 is already gone
parent 42f0e25a
Pipeline #31319 passed with stages
in 32 minutes and 18 seconds
......@@ -1158,7 +1158,7 @@ nmhandle_deactivate(isc_nmsocket_t *sock, isc_nmhandle_t *handle) {
void
isc_nmhandle_unref(isc_nmhandle_t *handle) {
isc_nmsocket_t *sock = NULL;
isc_nmsocket_t *sock = NULL, *tmp = NULL;
REQUIRE(VALID_NMHANDLE(handle));
......@@ -1199,8 +1199,14 @@ isc_nmhandle_unref(isc_nmhandle_t *handle) {
}
}
/*
* Temporarily reference the socket to ensure that it can't
* be deleted by another thread while we're deactivating the
* handle.
*/
isc_nmsocket_attach(sock, &tmp);
nmhandle_deactivate(sock, handle);
nmsocket_maybe_destroy(sock);
isc_nmsocket_detach(&tmp);
}
void *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment