Windows: AFSEvaluateTargetByID Sanity Check Result
authorJeffrey Altman <jaltman@your-file-system.com>
Sun, 27 Jan 2013 20:06:09 +0000 (15:06 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Sat, 2 Feb 2013 17:24:40 +0000 (09:24 -0800)
If the file server provides the service with bogus status info
and that status info is inconsistent with the allocated fields
in the associated ObjectInformationCB and FCB structures, it can
result in a BSOD.  Perform some basic sanity checks and if an
inconsistency is discovered, fail the request.  This may result
in the inability to access a file/directory but will prevent a
BSOD.

Change-Id: Iabf66adc5e953dc4ae27ed701148a9ffbf55abcc
Reviewed-on: http://gerrit.openafs.org/8994
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsrdr/kernel/lib/AFSCommSupport.cpp

index f8a133a..e7d44f9 100644 (file)
@@ -2787,6 +2787,62 @@ 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
         //