From 890cbf6cae893179d053c23d45b03bb0e28be4d8 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 1 Aug 2008 14:09:50 +0000 Subject: [PATCH] windows-smb-dead-vc-gc-20080801 LICENSE MIT deltas windows-smb-dead-vc-gc-20080627 and windows-dead-vc-cleanup-take-two-20080703 attempted to protect against an infinite recursion when cleaning up dead smb virtual circuits. they failed to address the incrementing of the vc refcount in smb_ReleaseVCInternal when it is about to call smb_CleanupDeadVC. If the vc is already being cleaned, then smb_ReleaseVCInternal should not increment the refCount and should not call smb_CleanupDeadVC. --- src/WINNT/afsd/smb.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 384c61b20e..a9a6a19e62 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -1023,30 +1023,32 @@ void smb_ReleaseVCInternal(smb_vc_t *vcp) break; } osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d", - avcp?"not ":"",vcp, vcp->refCount); -#ifdef DEBUG - GenerateMiniDump(NULL); -#endif + avcp?"":"not ",vcp, vcp->refCount); + /* This is a wrong. However, I suspect that there is an undercount * and I don't want to release 1.4.1 in a state that will allow * smb_vc_t objects to be deallocated while still in the * smb_allVCsp list. The list is supposed to keep a reference * to the smb_vc_t. Put it back. - */ - vcp->refCount++; + */ + if (avcp) + vcp->refCount++; } } else if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) { /* The reference count is non-zero but the VC is dead. * This implies that some FIDs, TIDs, etc on the VC have yet to - * be cleaned up. Add a reference that will be dropped by + * be cleaned up. If we were not called by smb_CleanupDeadVC(), + * add a reference that will be dropped by * smb_CleanupDeadVC() and try to cleanup the VC again. * Eventually the refCount will drop to zero when all of the * active threads working with the VC end their task. */ - vcp->refCount++; /* put the refCount back */ - lock_ReleaseWrite(&smb_rctLock); - smb_CleanupDeadVC(vcp); - lock_ObtainWrite(&smb_rctLock); + if (!(vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS)) { + vcp->refCount++; /* put the refCount back */ + lock_ReleaseWrite(&smb_rctLock); + smb_CleanupDeadVC(vcp); + lock_ObtainWrite(&smb_rctLock); + } } }