Windows: Use MountRoot for Absolute Symlinks
authorJeffrey Altman <jaltman@your-file-system.com>
Thu, 1 Nov 2012 00:59:30 +0000 (20:59 -0400)
committerJeffrey Altman <jaltman@your-file-system.com>
Fri, 2 Nov 2012 13:51:33 +0000 (06:51 -0700)
Replace the absolute symlink processing in AFSLocateName().
Implement AFSIsAbsoluteAFSName() to test whether or not the
path is in fact an absolute /afs path by comparing the input
string to the registry MountRoot value which specifies the
case sensitive root path for all absolute symlinks stored
in the AFS cell.

If a symlink target path begins with a directory separator
and is not an absolute afs path name, return an error.

Construct the substitution string using the target path
without the MountRoot prefix.

Add functionality to AFSRedir.sys to read the MountRoot
from the registry and pass it on to AFSRedirLib.sys.

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

13 files changed:
src/WINNT/afsrdr/common/AFSRedirCommonStructs.h
src/WINNT/afsrdr/kernel/fs/AFSData.cpp
src/WINNT/afsrdr/kernel/fs/AFSGeneric.cpp
src/WINNT/afsrdr/kernel/fs/AFSInit.cpp
src/WINNT/afsrdr/kernel/fs/AFSLibrarySupport.cpp
src/WINNT/afsrdr/kernel/fs/Include/AFSCommon.h
src/WINNT/afsrdr/kernel/fs/Include/AFSDefines.h
src/WINNT/afsrdr/kernel/fs/Include/AFSExtern.h
src/WINNT/afsrdr/kernel/lib/AFSData.cpp
src/WINNT/afsrdr/kernel/lib/AFSGeneric.cpp
src/WINNT/afsrdr/kernel/lib/AFSNameSupport.cpp
src/WINNT/afsrdr/kernel/lib/Include/AFSCommon.h
src/WINNT/afsrdr/kernel/lib/Include/AFSExtern.h

index 1303ec8..adbabfc 100644 (file)
@@ -786,6 +786,8 @@ typedef struct _AFS_LIBRARY_INIT_CB
 
     UNICODE_STRING      AFSServerName;
 
+    UNICODE_STRING      AFSMountRootName;
+
     ULONG               AFSDebugFlags;
 
     AFSFileID           GlobalRootFid;
index 4fd9894..f1cc27a 100644 (file)
@@ -64,6 +64,8 @@ HANDLE              AFSMUPHandle = NULL;
 
 UNICODE_STRING      AFSServerName;
 
+UNICODE_STRING      AFSMountRootName;
+
 UNICODE_STRING      AFSGlobalRootName;
 
 CACHE_MANAGER_CALLBACKS AFSCacheManagerCallbacks;
index 3b86737..8931992 100644 (file)
@@ -960,7 +960,7 @@ AFSReadServerName()
         AFSServerName.Buffer = NULL;
 
         paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
-        paramTable[0].Name = AFS_NETBIOS_NAME;
+        paramTable[0].Name = AFS_REG_NETBIOS_NAME;
         paramTable[0].EntryContext = &AFSServerName;
 
         paramTable[0].DefaultType = REG_NONE;
@@ -997,6 +997,107 @@ try_exit:
 }
 
 NTSTATUS
+AFSReadMountRootName()
+{
+
+    NTSTATUS ntStatus        = STATUS_SUCCESS;
+    ULONG Default            = 0;
+    UNICODE_STRING paramPath;
+    RTL_QUERY_REGISTRY_TABLE paramTable[2];
+
+    __Enter
+    {
+
+        //
+        // Setup the paramPath buffer.
+        //
+
+        paramPath.MaximumLength = PAGE_SIZE;
+        paramPath.Buffer = (PWSTR)AFSExAllocatePoolWithTag( PagedPool,
+                                                            paramPath.MaximumLength,
+                                                            AFS_GENERIC_MEMORY_17_TAG);
+
+        //
+        // If it exists, setup the path.
+        //
+
+        if( paramPath.Buffer == NULL)
+        {
+
+            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
+        }
+
+        //
+        // Move in the paths
+        //
+
+        RtlZeroMemory( paramPath.Buffer,
+                       paramPath.MaximumLength);
+
+        RtlCopyMemory( &paramPath.Buffer[ 0],
+                       L"\\TransarcAFSDaemon\\Parameters",
+                       58);
+
+        paramPath.Length = 58;
+
+        RtlZeroMemory( paramTable,
+                       sizeof( paramTable));
+
+        //
+        // Setup the table to query the registry for the needed value
+        //
+
+        AFSMountRootName.Length = 0;
+        AFSMountRootName.MaximumLength = 0;
+        AFSMountRootName.Buffer = NULL;
+
+        paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+        paramTable[0].Name = AFS_REG_MOUNT_ROOT;
+        paramTable[0].EntryContext = &AFSMountRootName;
+
+        paramTable[0].DefaultType = REG_NONE;
+        paramTable[0].DefaultData = NULL;
+        paramTable[0].DefaultLength = 0;
+
+        //
+        // Query the registry
+        //
+
+        ntStatus = RtlQueryRegistryValues( RTL_REGISTRY_SERVICES,
+                                           paramPath.Buffer,
+                                           paramTable,
+                                           NULL,
+                                           NULL);
+
+        if ( NT_SUCCESS( ntStatus))
+        {
+            if ( AFSMountRootName.Buffer[0] == L'/')
+            {
+
+                AFSMountRootName.Buffer[0] = L'\\';
+            }
+        }
+
+        //
+        // Free up the buffer
+        //
+
+        ExFreePool( paramPath.Buffer);
+
+try_exit:
+
+        if( !NT_SUCCESS( ntStatus))
+        {
+
+            RtlInitUnicodeString( &AFSMountRootName,
+                                  L"\\afs");
+        }
+    }
+
+    return ntStatus;
+}
+
+NTSTATUS
 AFSSetSysNameInformation( IN AFSSysNameNotificationCB *SysNameInfo,
                           IN ULONG SysNameInfoBufferLength)
 {
index 83e22f7..8ff1be2 100644 (file)
@@ -108,6 +108,8 @@ DriverEntry( PDRIVER_OBJECT DriverObject,
 
         AFSReadServerName();
 
+        AFSReadMountRootName();
+
         RtlZeroMemory( &sysVersion,
                        sizeof( RTL_OSVERSIONINFOW));
 
index bed174d..2186bc1 100644 (file)
@@ -870,6 +870,8 @@ AFSInitializeLibrary( IN AFSFileID *GlobalRootFid,
 
         stInitLib.AFSServerName = AFSServerName;
 
+        stInitLib.AFSMountRootName = AFSMountRootName;
+
         stInitLib.AFSDebugFlags = AFSDebugFlags;
 
         if( GlobalRootFid != NULL)
index e2b4643..65c14af 100644 (file)
@@ -457,6 +457,9 @@ NTSTATUS
 AFSReadServerName( void);
 
 NTSTATUS
+AFSReadMountRootName( void);
+
+NTSTATUS
 AFSSetSysNameInformation( IN AFSSysNameNotificationCB *SysNameInfo,
                           IN ULONG SysNameInfoBufferLength);
 
index 4f57d87..239e4ff 100644 (file)
@@ -48,7 +48,8 @@
 #define AFS_REG_TRACE_BUFFER_LENGTH      L"TraceBufferSize"  // in KB
 #define AFS_REG_MAX_DIRTY                L"MaxDirtyMb"
 #define AFS_REG_MAX_IO                   L"MaxIOMb"
-#define AFS_NETBIOS_NAME                 L"NetbiosName"
+#define AFS_REG_NETBIOS_NAME             L"NetbiosName"
+#define AFS_REG_MOUNT_ROOT               L"MountRoot"
 #define AFS_REG_SHUTDOWN_STATUS          L"ShutdownStatus"
 #define AFS_REG_REQUIRE_CLEAN_SHUTDOWN   L"RequireCleanShutdown"
 
index 9197d58..524c851 100644 (file)
@@ -67,6 +67,8 @@ extern HANDLE              AFSMUPHandle;
 
 extern UNICODE_STRING      AFSServerName;
 
+extern UNICODE_STRING      AFSMountRootName;
+
 extern UNICODE_STRING      AFSGlobalRootName;
 
 extern ERESOURCE           AFSDbgLogLock;
index 7f69fa1..b7b25d4 100644 (file)
@@ -56,6 +56,8 @@ HANDLE              AFSSysProcess = NULL;
 
 UNICODE_STRING      AFSServerName;
 
+UNICODE_STRING      AFSMountRootName;
+
 AFSVolumeCB        *AFSGlobalRoot = NULL;
 
 UNICODE_STRING      AFSPIOCtlName;
index dc26549..f5d00aa 100644 (file)
@@ -4778,7 +4778,8 @@ AFSIsRelativeName( IN UNICODE_STRING *Name)
 
     BOOLEAN bIsRelative = FALSE;
 
-    if( Name->Buffer[ 0] != L'\\')
+    if( Name->Length > 0 &&
+        Name->Buffer[ 0] != L'\\')
     {
 
         bIsRelative = TRUE;
@@ -4787,6 +4788,53 @@ AFSIsRelativeName( IN UNICODE_STRING *Name)
     return bIsRelative;
 }
 
+BOOLEAN
+AFSIsAbsoluteAFSName( IN UNICODE_STRING *Name)
+{
+    UNICODE_STRING uniTempName;
+    BOOLEAN        bIsAbsolute = FALSE;
+
+    //
+    // An absolute AFS path must begin with \afs\... or equivalent
+    //
+
+    if ( Name->Length == 0 ||
+         Name->Length <= AFSMountRootName.Length + sizeof( WCHAR) ||
+         Name->Buffer[ 0] != L'\\' ||
+         Name->Buffer[ AFSMountRootName.Length/sizeof( WCHAR)] != L'\\')
+    {
+
+        return FALSE;
+    }
+
+    uniTempName.Length = AFSMountRootName.Length;
+    uniTempName.MaximumLength = AFSMountRootName.Length;
+
+    uniTempName.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
+                                                            uniTempName.MaximumLength,
+                                                            AFS_NAME_BUFFER_TWO_TAG);
+
+    if( uniTempName.Buffer == NULL)
+    {
+
+        return FALSE;
+    }
+
+    RtlCopyMemory( uniTempName.Buffer,
+                   Name->Buffer,
+                   AFSMountRootName.Length);
+
+    bIsAbsolute = (0 == RtlCompareUnicodeString( &uniTempName,
+                                                 &AFSMountRootName,
+                                                 TRUE));
+
+    AFSExFreePoolWithTag( uniTempName.Buffer,
+                          AFS_NAME_BUFFER_TWO_TAG);
+
+    return bIsAbsolute;
+}
+
+
 void
 AFSUpdateName( IN UNICODE_STRING *Name)
 {
@@ -7735,6 +7783,8 @@ AFSInitializeLibrary( IN AFSLibraryInitCB *LibraryInit)
 
         AFSServerName = LibraryInit->AFSServerName;
 
+        AFSMountRootName = LibraryInit->AFSMountRootName;
+
         AFSDebugFlags = LibraryInit->AFSDebugFlags;
 
         //
index f637ef4..6f6783a 100644 (file)
@@ -619,6 +619,26 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                                       pCurrentObject->FileId.Vnode,
                                       pCurrentObject->FileId.Unique);
 
+                        if ( !AFSIsAbsoluteAFSName( &pDirEntry->NameInformation.TargetName))
+                        {
+
+                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
+                                          AFS_TRACE_LEVEL_ERROR,
+                                          "AFSLocateNameEntry Name %wZ contains invalid server name\n",
+                                          &pDirEntry->NameInformation.TargetName);
+
+                            //
+                            // The correct response would be STATUS_OBJECT_PATH_INVALID
+                            // but that prevents cmd.exe from performing a recursive
+                            // directory enumeration when opening a directory entry
+                            // that represents a symlink to an invalid path is discovered.
+                            //
+
+                            AFSReleaseResource( &pDirEntry->NonPaged->Lock);
+
+                            try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
+                        }
+
                         //
                         // We'll substitute this name into the current process name
                         // starting at where we sit in the path
@@ -664,10 +684,10 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
                         //
 
                         RtlCopyMemory( uniTempName.Buffer,
-                                       pDirEntry->NameInformation.TargetName.Buffer,
-                                       pDirEntry->NameInformation.TargetName.Length);
+                                       &pDirEntry->NameInformation.TargetName.Buffer[ AFSMountRootName.Length/sizeof( WCHAR)],
+                                       pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length);
 
-                        uniTempName.Length = pDirEntry->NameInformation.TargetName.Length;
+                        uniTempName.Length = pDirEntry->NameInformation.TargetName.Length - AFSMountRootName.Length;
 
                         //
                         // And now any remaining portion of the name
@@ -790,35 +810,6 @@ AFSLocateNameEntry( IN GUID *AuthGroup,
 
                         pNameArray->LinkCount = lLinkCount;
 
-                        //
-                        // Process over the \\<Global root> portion of the name
-                        //
-
-                        FsRtlDissectName( uniPathName,
-                                          &uniComponentName,
-                                          &uniRemainingPath);
-
-                        if( RtlCompareUnicodeString( &uniComponentName,
-                                                     &AFSServerName,
-                                                     TRUE) != 0)
-                        {
-
-                            AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
-                                          AFS_TRACE_LEVEL_ERROR,
-                                          "AFSLocateNameEntry Name %wZ contains invalid server name\n",
-                                          &uniPathName);
-
-                            //
-                            // The correct response would be STATUS_OBJECT_PATH_INVALID
-                            // but that prevents cmd.exe from performing a recursive
-                            // directory enumeration when opening a directory entry
-                            // that represents a symlink to an invalid path is discovered.
-                            //
-                            try_return( ntStatus = STATUS_OBJECT_PATH_NOT_FOUND);
-                        }
-
-                        uniPathName = uniRemainingPath;
-
                         pParentDirEntry = NULL;
                     }
 
index 022a6ba..416c39d 100644 (file)
@@ -1227,6 +1227,9 @@ AFSEnumerateGlobalRoot( IN GUID *AuthGroup);
 BOOLEAN
 AFSIsRelativeName( IN UNICODE_STRING *Name);
 
+BOOLEAN
+AFSIsAbsoluteAFSName( IN UNICODE_STRING *Name);
+
 void
 AFSUpdateName( IN UNICODE_STRING *Name);
 
index a9b23fb..09cbee0 100644 (file)
@@ -61,6 +61,8 @@ extern HANDLE              AFSSysProcess;
 
 extern UNICODE_STRING      AFSServerName;
 
+extern UNICODE_STRING      AFSMountRootName;
+
 extern AFSVolumeCB        *AFSGlobalRoot;
 
 extern UNICODE_STRING      AFSPIOCtlName;