From: Andrew Deason Date: Fri, 23 Oct 2009 19:33:06 +0000 (-0400) Subject: void prematurely destroying callback_rxcon X-Git-Tag: sna/patch/viced-null-callback-rxcon X-Git-Url: http://openafs.sinenomine.net/patch/viced-null-callback-rxcon?p=openafs.git;a=commitdiff_plain;h=refs%2Ftags%2Fsna%2Fpatch%2Fviced-null-callback-rxcon void prematurely destroying callback_rxcon Currently, h_GetHost_r and removeAddress_r can destroy the callback_rxcon of a host. Having a NULL callback_rxcon can cause segfaults in code that does not properly check if a host has been HOSTDELETED before trying to use it. Although such code is incorrect and should be fixed, we can still avoid a segfault in those situations by not destroying callback_rxcon until we destroy the host itself. This just prevents destroying callback_rxcon in h_GetHost_r and removeAddress_r, leaving it to h_TossStuff_r to destroy when it destroys the host. --- diff --git a/src/viced/host.c b/src/viced/host.c index 36614c4..a1dca8c 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -1336,22 +1336,6 @@ removeAddress_r(struct host *host, afs_uint32 addr, afs_uint16 port) } else { struct rx_connection *rxconn; - rxconn = host->callback_rxcon; - host->callback_rxcon = NULL; - - if (rxconn) { - struct client *client; - /* - * If rx_DestroyConnection calls h_FreeConnection we will - * deadlock on the host_glock_mutex. Work around the problem - * by unhooking the client from the connection before - * destroying the connection. - */ - client = rx_GetSpecific(rxconn, rxcon_client_key); - rx_SetSpecific(rxconn, rxcon_client_key, (void *)0); - rx_DestroyConnection(rxconn); - } - for (i=0; i < host->interface->numberOfInterfaces; i++) { if (host->interface->interface[i].valid) { ViceLog(25, @@ -1372,6 +1356,14 @@ removeAddress_r(struct host *host, afs_uint32 addr, afs_uint16 port) host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port))); host->hostFlags |= HOSTDELETED; } else { + rxconn = host->callback_rxcon; + host->callback_rxcon = NULL; + + if (rxconn) { + rx_DestroyConnection(rxconn); + rxconn = NULL; + } + if (!sc) sc = rxnull_NewClientSecurityObject(); host->callback_rxcon = @@ -1874,20 +1866,10 @@ h_GetHost_r(struct rx_connection *tcon) oldHost->port = hport; rxconn = oldHost->callback_rxcon; oldHost->callback_rxcon = host->callback_rxcon; - host->callback_rxcon = NULL; - - if (rxconn) { - struct client *client; - /* - * If rx_DestroyConnection calls h_FreeConnection we will - * deadlock on the host_glock_mutex. Work around the problem - * by unhooking the client from the connection before - * destroying the connection. - */ - client = rx_GetSpecific(rxconn, rxcon_client_key); - rx_SetSpecific(rxconn, rxcon_client_key, (void *)0); - rx_DestroyConnection(rxconn); - } + host->callback_rxcon = rxconn; + + /* don't destroy rxconn here; let h_TossStuff_r + * take care of that via h_Release_r below */ } host->hostFlags &= ~HWHO_INPROGRESS; h_Unlock_r(host);