Windows: AFSEvaluateTargetByID Sanity Check Result
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSCommSupport.cpp
index fb69008..e7d44f9 100644 (file)
@@ -311,7 +311,14 @@ AFSEnumerateDirectory( IN GUID *AuthGroup,
                             // The ObjectReferenceCount will be freed by AFSPerformObjectInvalidate
                             //
 
-                            lCount = AFSObjectInfoIncrement( pObjectInfo);
+                            lCount = AFSObjectInfoIncrement( pObjectInfo,
+                                                             AFS_OBJECT_REFERENCE_INVALIDATION);
+
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSEnumerateDirectory calling AFSPerformObjectInvalidate Increment count on object %p Cnt %d\n",
+                                          pObjectInfo,
+                                          lCount);
 
                             AFSPerformObjectInvalidate( pObjectInfo,
                                                         AFS_INVALIDATE_DATA_VERSION);
@@ -1090,13 +1097,27 @@ AFSVerifyDirectoryContent( IN AFSObjectInfoCB *ObjectInfoCB,
                             // lock hierarchy.
                             //
 
-                            lCount = AFSObjectInfoIncrement( pObjectInfo);
+                            lCount = AFSObjectInfoIncrement( pObjectInfo,
+                                                             AFS_OBJECT_REFERENCE_INVALIDATION);
+
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                          AFS_TRACE_LEVEL_VERBOSE,
+                                          "AFSVerifyDirectoryContent calling AFSQueueInvalidateObject Increment count on object %p Cnt %d\n",
+                                          pObjectInfo,
+                                          lCount);
 
                             if ( !NT_SUCCESS( AFSQueueInvalidateObject( pObjectInfo,
                                                                         AFS_INVALIDATE_DATA_VERSION)))
                             {
 
-                                lCount = AFSObjectInfoDecrement( pObjectInfo);
+                                lCount = AFSObjectInfoDecrement( pObjectInfo,
+                                                                 AFS_OBJECT_REFERENCE_INVALIDATION);
+
+                                AFSDbgLogMsg( AFS_SUBSYSTEM_OBJECT_REF_COUNTING,
+                                              AFS_TRACE_LEVEL_VERBOSE,
+                                              "AFSVerifyDirectoryContent AFSQueueInvalidateObject failed Decrement count on object %p Cnt %d\n",
+                                              pObjectInfo,
+                                              lCount);
                             }
                         }
                         else
@@ -1973,11 +1994,18 @@ AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
     AFSFileDeleteCB stDelete;
     AFSFileDeleteResultCB stDeleteResult;
     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
+    AFSObjectInfoCB *pObjectInfo = NULL;
+    AFSObjectInfoCB *pParentObjectInfo = NULL;
 
     __Enter
     {
 
-        stDelete.ParentId = DirectoryCB->ObjectInformation->ParentObjectInformation->FileId;
+        pObjectInfo = DirectoryCB->ObjectInformation;
+
+        pParentObjectInfo = AFSFindObjectInfo( pObjectInfo->VolumeCB,
+                                               &pObjectInfo->ParentFileId);
+
+        stDelete.ParentId = pObjectInfo->ParentFileId;
 
         stDelete.ProcessId = (ULONGLONG)PsGetCurrentProcessId();
 
@@ -1992,7 +2020,7 @@ AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
                                       ulRequestFlags,
                                       AuthGroup,
                                       &DirectoryCB->NameInformation.FileName,
-                                      &DirectoryCB->ObjectInformation->FileId,
+                                      &pObjectInfo->FileId,
                                       &stDelete,
                                       sizeof( AFSFileDeleteCB),
                                       &stDeleteResult,
@@ -2009,16 +2037,16 @@ AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
                           stDelete.ParentId.Vnode,
                           stDelete.ParentId.Unique,
                           &DirectoryCB->NameInformation.FileName,
-                          DirectoryCB->ObjectInformation->FileId.Cell,
-                          DirectoryCB->ObjectInformation->FileId.Volume,
-                          DirectoryCB->ObjectInformation->FileId.Vnode,
-                          DirectoryCB->ObjectInformation->FileId.Unique,
+                          pObjectInfo->FileId.Cell,
+                          pObjectInfo->FileId.Volume,
+                          pObjectInfo->FileId.Vnode,
+                          pObjectInfo->FileId.Unique,
                           ntStatus);
 
             try_return( ntStatus);
         }
 
-        AFSAcquireExcl( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock,
+        AFSAcquireExcl( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
                         TRUE);
 
         if( CheckOnly)
@@ -2028,12 +2056,12 @@ AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
             // Validate the parent data version
             //
 
-            if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
+            if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart)
             {
 
-                SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
-                DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
             }
         }
         else
@@ -2043,12 +2071,12 @@ AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
             // Update the parent data version
             //
 
-            if( DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
+            if( pParentObjectInfo->DataVersion.QuadPart != stDeleteResult.ParentDataVersion.QuadPart - 1)
             {
 
-                SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
-                DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
             }
             else
             {
@@ -2058,20 +2086,24 @@ AFSNotifyDelete( IN AFSDirectoryCB *DirectoryCB,
                 // Directory data version number can be updated.  Until then we must force
                 // a verification.
                 //
-                // DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
+                // pParentObjectInfor->DataVersion.QuadPart = stDeleteResult.ParentDataVersion.QuadPart;
                 //
 
-                SetFlag( DirectoryCB->ObjectInformation->ParentObjectInformation->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
-                DirectoryCB->ObjectInformation->ParentObjectInformation->DataVersion.QuadPart = (ULONGLONG)-1;
+                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
             }
         }
 
-        AFSReleaseResource( DirectoryCB->ObjectInformation->Specific.Directory.DirectoryNodeHdr.TreeLock);
+        AFSReleaseResource( pObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
 
 try_exit:
 
-        NOTHING;
+        if ( pParentObjectInfo)
+        {
+
+            AFSReleaseObjectInfo( &pParentObjectInfo);
+        }
     }
 
     return ntStatus;
@@ -2673,7 +2705,7 @@ AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
     AFSFileEvalResultCB *pEvalResultCB = NULL;
     AFSDirEnumEntry *pDirEnumCB = NULL;
     ULONG ulRequestFlags = AFS_REQUEST_FLAG_SYNCHRONOUS;
-    AFSObjectInfoCB *pParentInfo = NULL;
+    AFSObjectInfoCB *pParentObjectInfo = NULL;
 
     __Enter
     {
@@ -2681,12 +2713,13 @@ AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
         RtlZeroMemory( &stTargetID,
                        sizeof( AFSEvalTargetCB));
 
-        pParentInfo = ObjectInfo->ParentObjectInformation;
-
-        if( pParentInfo != NULL)
+        if ( BooleanFlagOn( ObjectInfo->Flags, AFS_OBJECT_FLAGS_PARENT_FID))
         {
 
-            stTargetID.ParentId = pParentInfo->FileId;
+            pParentObjectInfo = AFSFindObjectInfo( ObjectInfo->VolumeCB,
+                                                   &ObjectInfo->ParentFileId);
+
+            stTargetID.ParentId = ObjectInfo->ParentFileId;
         }
 
         //
@@ -2736,17 +2769,17 @@ AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
             if( ntStatus == STATUS_OBJECT_PATH_INVALID)
             {
 
-                if( pParentInfo != NULL)
+                if( pParentObjectInfo != NULL)
                 {
 
-                    AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+                    AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
                                     TRUE);
 
-                    SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                    SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
-                    pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                    pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
 
-                    AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+                    AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
                 }
             }
 
@@ -2754,24 +2787,80 @@ AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
         }
 
         //
+        // A BSOD can occur if the pEvalResultCB->FileType is FILE but the
+        // ObjectInfo->FileType is something else.  The same is true for
+        // pDirEnumEntry->FileType is DIRECTORY.  Perform a sanity check
+        // to ensure consistency.  An inconsistent pDirEnumEntry can be
+        // produced as a result of invalid status info received from a file
+        // server.  If the types are inconsistent or if the type does not
+        // match the implied type derived from the vnode (odd values are
+        // directories and even values are other types), prevent the request
+        // from completing successfully.  This may prevent access to the file or
+        // directory but will prevent a BSOD.
+        //
+
+        if ( !AFSIsEqualFID( &ObjectInfo->FileId,
+                             &pEvalResultCB->DirEnum.FileId))
+        {
+
+            try_return( ntStatus = STATUS_UNSUCCESSFUL);
+        }
+
+        switch ( pEvalResultCB->DirEnum.FileType)
+        {
+
+        case AFS_FILE_TYPE_DIRECTORY:
+            if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x1)
+            {
+
+                try_return( ntStatus = STATUS_UNSUCCESSFUL);
+            }
+
+            if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
+                 ObjectInfo->FileType != AFS_FILE_TYPE_DIRECTORY)
+            {
+
+                try_return( ntStatus = STATUS_UNSUCCESSFUL);
+            }
+
+            break;
+
+        case AFS_FILE_TYPE_FILE:
+            if ( (pEvalResultCB->DirEnum.FileId.Vnode & 0x1) != 0x0)
+            {
+
+                try_return( ntStatus = STATUS_UNSUCCESSFUL);
+            }
+
+            if ( ObjectInfo->FileType != AFS_FILE_TYPE_UNKNOWN &&
+                 ObjectInfo->FileType != AFS_FILE_TYPE_FILE)
+            {
+
+                try_return( ntStatus = STATUS_UNSUCCESSFUL);
+            }
+
+            break;
+        }
+
+        //
         // Validate the parent data version
         //
 
-        if ( pParentInfo != NULL)
+        if ( pParentObjectInfo != NULL)
         {
 
-            AFSAcquireExcl( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
+            AFSAcquireExcl( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock,
                             TRUE);
 
-            if ( pParentInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
+            if ( pParentObjectInfo->DataVersion.QuadPart != pEvalResultCB->ParentDataVersion.QuadPart)
             {
 
-                SetFlag( pParentInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
+                SetFlag( pParentObjectInfo->Flags, AFS_OBJECT_FLAGS_VERIFY);
 
-                pParentInfo->DataVersion.QuadPart = (ULONGLONG)-1;
+                pParentObjectInfo->DataVersion.QuadPart = (ULONGLONG)-1;
             }
 
-            AFSReleaseResource( pParentInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
+            AFSReleaseResource( pParentObjectInfo->Specific.Directory.DirectoryNodeHdr.TreeLock);
         }
 
         //
@@ -2799,6 +2888,12 @@ AFSEvaluateTargetByID( IN AFSObjectInfoCB *ObjectInfo,
 
 try_exit:
 
+        if ( pParentObjectInfo != NULL)
+        {
+
+            AFSReleaseObjectInfo( &pParentObjectInfo);
+        }
+
         if( pEvalResultCB != NULL)
         {