dll: relative symbolic link resolution testing

This commit is contained in:
Bill Zissimopoulos 2016-09-12 21:41:48 -07:00
parent c12b88286d
commit 5888e9ab05
2 changed files with 56 additions and 30 deletions

View File

@ -1017,35 +1017,41 @@ FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
PVOID Context, PVOID Context,
PWSTR FileName, PUINT32 PReparsePointIndex) PWSTR FileName, PUINT32 PReparsePointIndex)
{ {
WCHAR *p, *lastp; PWSTR RemainderPath, LastPathComponent;
NTSTATUS Result; NTSTATUS Result;
p = FileName; RemainderPath = FileName;
for (;;) for (;;)
{ {
while (L'\\' == *p) while (L'\\' == *RemainderPath)
p++; RemainderPath++;
lastp = p; LastPathComponent = RemainderPath;
while (L'\\' != *p) while (L'\\' != *RemainderPath)
{ {
if (L'\0' == *p) if (L'\0' == *RemainderPath)
return FALSE; return FALSE;
p++; RemainderPath++;
} }
*p = L'\0'; *RemainderPath = L'\0';
Result = GetReparsePointByName(FileSystem, Context, FileName, TRUE, 0, 0); Result = GetReparsePointByName(FileSystem, Context, FileName, TRUE, 0, 0);
*p = L'\\'; *RemainderPath = L'\\';
if (!NT_SUCCESS(Result)) if (STATUS_NOT_A_REPARSE_POINT == Result)
/* it was not a reparse point; continue */
continue;
else if (!NT_SUCCESS(Result))
return FALSE; return FALSE;
else
{
if (0 != PReparsePointIndex)
*PReparsePointIndex = (ULONG)(lastp - FileName);
return TRUE; /*
} * Found a reparse point!
*/
if (0 != PReparsePointIndex)
*PReparsePointIndex = (ULONG)(LastPathComponent - FileName);
return TRUE;
} }
return FALSE; return FALSE;
@ -1102,26 +1108,43 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
if (L'.' == LastPathComponent[0]) if (L'.' == LastPathComponent[0])
{ {
if (RemainderPath == LastPathComponent + 1) if (RemainderPath == LastPathComponent + 1)
{
/* dot */ /* dot */
continue; ReparseTargetPath = 0;
ReparseTargetPathLength = 0;
NewRemainderPath = LastPathComponent;
while (TargetPath < NewRemainderPath)
{
NewRemainderPath--;
if (L'\\' == *NewRemainderPath)
break;
}
goto reparse;
}
if (L'.' == LastPathComponent[1] && RemainderPath == LastPathComponent + 2) if (L'.' == LastPathComponent[1] && RemainderPath == LastPathComponent + 2)
{ {
/* dotdot */ /* dotdot */
RemainderPath = LastPathComponent; ReparseTargetPath = 0;
while (TargetPath < RemainderPath) ReparseTargetPathLength = 0;
NewRemainderPath = LastPathComponent;
while (TargetPath < NewRemainderPath)
{ {
RemainderPath--; NewRemainderPath--;
if (L'\\' != *RemainderPath) if (L'\\' != *NewRemainderPath)
break; break;
} }
while (TargetPath < RemainderPath) while (TargetPath < NewRemainderPath)
{ {
RemainderPath--; NewRemainderPath--;
if (L'\\' == *RemainderPath) if (L'\\' == *NewRemainderPath)
break; break;
} }
continue;
goto reparse;
} }
} }
@ -1158,20 +1181,22 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0]) ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
goto reparse_data_exit; goto reparse_data_exit;
if (0 == --MaxTries)
return STATUS_REPARSE_POINT_NOT_RESOLVED;
/* if device relative symlink replace whole path; else replace last path component */ /* if device relative symlink replace whole path; else replace last path component */
NewRemainderPath = ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0] ? NewRemainderPath = ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0] ?
TargetPath : LastPathComponent; TargetPath : LastPathComponent;
reparse:
if (0 == --MaxTries)
return STATUS_REPARSE_POINT_NOT_RESOLVED;
RemainderPathSize = (lstrlenW(RemainderPath) + 1) * sizeof(WCHAR); RemainderPathSize = (lstrlenW(RemainderPath) + 1) * sizeof(WCHAR);
if (NewRemainderPath + (ReparseTargetPathLength + RemainderPathSize) / sizeof(WCHAR) > if (NewRemainderPath + (ReparseTargetPathLength + RemainderPathSize) / sizeof(WCHAR) >
TargetPath + *PSize / sizeof(WCHAR)) TargetPath + *PSize / sizeof(WCHAR))
return STATUS_REPARSE_POINT_NOT_RESOLVED; return STATUS_REPARSE_POINT_NOT_RESOLVED;
/* move remainder path to its new position */ /* move remainder path to its new position */
memmove(NewRemainderPath + ReparseTargetPathLength, RemainderPath, RemainderPathSize); memmove(NewRemainderPath + ReparseTargetPathLength / sizeof(WCHAR),
RemainderPath, RemainderPathSize);
/* copy symlink target */ /* copy symlink target */
memcpy(NewRemainderPath, ReparseTargetPath, ReparseTargetPathLength); memcpy(NewRemainderPath, ReparseTargetPath, ReparseTargetPathLength);

View File

@ -452,6 +452,7 @@ static void reparse_symlink_relative_dotest(ULONG Flags, PWSTR Prefix, ULONG Fil
ASSERT(ERROR_FILE_NOT_FOUND == GetLastError()); ASSERT(ERROR_FILE_NOT_FOUND == GetLastError());
my_notexist(L"\\loop"); my_notexist(L"\\loop");
ASSERT(ERROR_CANT_RESOLVE_FILENAME == GetLastError()); ASSERT(ERROR_CANT_RESOLVE_FILENAME == GetLastError());
my_namecheck(L"\\1\\1.1\\l1.1.1", L"\\1\\1.1\\1.1.1"); my_namecheck(L"\\1\\1.1\\l1.1.1", L"\\1\\1.1\\1.1.1");
my_namecheck(L"\\2\\l1\\1.1\\l1.1.1", L"\\1\\1.1\\1.1.1"); my_namecheck(L"\\2\\l1\\1.1\\l1.1.1", L"\\1\\1.1\\1.1.1");