From bbcfbe1a04eda9e75b1643be88cf9d4842a8aa86 Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Thu, 22 Oct 2009 11:12:30 -0500 Subject: [PATCH] Avoid 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. Change-Id: I6fd5cbb924053446689c576026f9044f78ba71be Reviewed-on: http://gerrit.openafs.org/717 Tested-by: Andrew Deason Reviewed-by: Jeffrey Altman Tested-by: Derrick Brashear Reviewed-by: Derrick Brashear --- src/viced/host.c | 40 +++++++++++----------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/src/viced/host.c b/src/viced/host.c index 615c30358..ed0b5a385 100644 --- a/src/viced/host.c +++ b/src/viced/host.c @@ -1444,22 +1444,6 @@ removeAddress_r(struct host *host, afs_uint32 addr, afs_uint16 port) if (host->host == addr && host->port == port) { removeInterfaceAddr_r(host, addr, port); - 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, @@ -1483,6 +1467,14 @@ removeAddress_r(struct host *host, afs_uint32 addr, afs_uint16 port) host->host = 0; host->port = 0; } else { + rxconn = host->callback_rxcon; + host->callback_rxcon = NULL; + + if (rxconn) { + rx_DestroyConnection(rxconn); + rxconn = NULL; + } + if (!sc) sc = rxnull_NewClientSecurityObject(); host->callback_rxcon = @@ -2000,20 +1992,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; + host->callback_rxcon = rxconn; - 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); - } + /* 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); -- 2.39.5