sys,dll: SYMLINK_FLAG_RELATIVE

This commit is contained in:
Bill Zissimopoulos 2016-09-11 13:18:54 -07:00
parent af2cc10c15
commit f89c91cd10
4 changed files with 28 additions and 17 deletions

View File

@ -1141,29 +1141,35 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
return Result; return Result;
} }
/* found a reparse point */ /*
* Found a reparse point!
*/
/* if not a symlink return the full reparse point */
if (IO_REPARSE_TAG_SYMLINK != ReparseData->ReparseTag) if (IO_REPARSE_TAG_SYMLINK != ReparseData->ReparseTag)
/* not a symlink; return the full reparse point! */
goto reparse_data_exit; goto reparse_data_exit;
ReparseTargetPath = ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseTargetPath = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR); ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength; ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
if (ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0]) /* if an absolute (in the NT namespace) symlink return the full reparse point */
/* absolute symlink; return the full reparse point! */ if (0 == (ReparseData->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) &&
ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
goto reparse_data_exit; goto reparse_data_exit;
if (0 == --MaxTries) if (0 == --MaxTries)
return STATUS_REPARSE_POINT_NOT_RESOLVED; return STATUS_REPARSE_POINT_NOT_RESOLVED;
/* relative symlink; replace last path component seen */ /* if device relative symlink replace whole path; else replace last path component */
if (ReparseTargetPathLength + sizeof(WCHAR) > (TargetPathEnd - lastp) * sizeof(WCHAR)) p = ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0] ?
TargetPath : lastp;
if (ReparseTargetPathLength + sizeof(WCHAR) > (TargetPathEnd - p) * sizeof(WCHAR))
return STATUS_REPARSE_POINT_NOT_RESOLVED; return STATUS_REPARSE_POINT_NOT_RESOLVED;
memcpy(lastp, ReparseTargetPath, ReparseTargetPathLength);
lastp[ReparseTargetPathLength / sizeof(WCHAR)] = L'\0'; memcpy(p, ReparseTargetPath, ReparseTargetPathLength);
p = lastp; p[ReparseTargetPathLength / sizeof(WCHAR)] = L'\0';
} }
exit: exit:
@ -1196,8 +1202,8 @@ FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
else if (*(PULONG)CurrentReparseData != *(PULONG)ReplaceReparseData) else if (*(PULONG)CurrentReparseData != *(PULONG)ReplaceReparseData)
return STATUS_IO_REPARSE_TAG_MISMATCH; return STATUS_IO_REPARSE_TAG_MISMATCH;
else if (!IsReparseTagMicrosoft(*(PULONG)CurrentReparseData) && ( else if (!IsReparseTagMicrosoft(*(PULONG)CurrentReparseData) && (
REPARSE_GUID_DATA_BUFFER_HEADER_SIZE > CurrentReparseDataSize || (SIZE_T)REPARSE_GUID_DATA_BUFFER_HEADER_SIZE > CurrentReparseDataSize ||
REPARSE_GUID_DATA_BUFFER_HEADER_SIZE > ReplaceReparseDataSize || (SIZE_T)REPARSE_GUID_DATA_BUFFER_HEADER_SIZE > ReplaceReparseDataSize ||
*(PUINT32)&((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data1 != *(PUINT32)&((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data1 !=
*(PUINT32)&((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data1 || *(PUINT32)&((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data1 ||
*(PUINT32)&((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data2 != *(PUINT32)&((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data2 !=

View File

@ -2005,7 +2005,8 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength; ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
/* is this an absolute path? */ /* is this an absolute path? */
if (ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0]) if (0 == (ReparseData->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) &&
ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
{ {
/* we do not support absolute paths that point outside this file system */ /* we do not support absolute paths that point outside this file system */
if (0 == Request->Req.FileSystemControl.TargetOnFileSystem) if (0 == Request->Req.FileSystemControl.TargetOnFileSystem)

View File

@ -516,9 +516,8 @@ NTSTATUS FspFsvolCreateComplete(
* path. Prefix it with our device name and send it to the IO Manager. * path. Prefix it with our device name and send it to the IO Manager.
* *
* IO_REPARSE_TAG_SYMLINK means that the user-mode file system has returned a full * IO_REPARSE_TAG_SYMLINK means that the user-mode file system has returned a full
* symbolic link reparse buffer. In this case send the target path to the IO Manager * symbolic link reparse buffer. In this case send the target path to the IO Manager,
* without prefixing it with our device name as it is expected to be absolute in the * and prefix it with our device name depending on SYMLINK_FLAG_RELATIVE.
* NT namespace.
*/ */
if (IO_REPARSE == Response->IoStatus.Information) if (IO_REPARSE == Response->IoStatus.Information)
@ -550,7 +549,11 @@ NTSTATUS FspFsvolCreateComplete(
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
FSP_RETURN(); FSP_RETURN();
RtlZeroMemory(&ReparseTargetPrefix, sizeof ReparseTargetPrefix); if (0 == (ReparseData->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE))
RtlZeroMemory(&ReparseTargetPrefix, sizeof ReparseTargetPrefix);
else
RtlCopyMemory(&ReparseTargetPrefix, &FsvolDeviceExtension->VolumeName,
sizeof ReparseTargetPrefix);
ReparseTargetPath.Buffer = ReparseData->SymbolicLinkReparseBuffer.PathBuffer + ReparseTargetPath.Buffer = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR); ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);

View File

@ -145,7 +145,8 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength; ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
/* is this an absolute path? determine if target resides on same device as link */ /* is this an absolute path? determine if target resides on same device as link */
if (ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0]) if (0 == (ReparseData->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) &&
ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
{ {
UNICODE_STRING TargetObjectName; UNICODE_STRING TargetObjectName;
PDEVICE_OBJECT TargetDeviceObject; PDEVICE_OBJECT TargetDeviceObject;