windows-smb-dead-vc-gc-on-head-20080801
authorJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 1 Aug 2008 14:14:50 +0000 (14:14 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Fri, 1 Aug 2008 14:14:50 +0000 (14:14 +0000)
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.

(This commit was committed incorrectly to the 1-5
branch first.  delta name on the head was modified
to avoid the delta name collision.)

src/WINNT/afsd/smb.c

index 521606b..c4f785c 100644 (file)
@@ -941,30 +941,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);
+        }
     }
 }