Author: pschweitzer
Date: Thu May 5 16:58:16 2016
New Revision: 71264
URL:
http://svn.reactos.org/svn/reactos?rev=71264&view=rev
Log:
[NTOSKRNL_VISTA]
Implement FsRtlValidateReparsePointBuffer().
CORE-11172
Modified:
trunk/reactos/sdk/lib/drivers/ntoskrnl_vista/fsrtl.c
Modified: trunk/reactos/sdk/lib/drivers/ntoskrnl_vista/fsrtl.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/sdk/lib/drivers/ntoskrnl_v…
==============================================================================
--- trunk/reactos/sdk/lib/drivers/ntoskrnl_vista/fsrtl.c [iso-8859-1] (original)
+++ trunk/reactos/sdk/lib/drivers/ntoskrnl_vista/fsrtl.c [iso-8859-1] Thu May 5 16:58:16
2016
@@ -119,3 +119,124 @@
return STATUS_SUCCESS;
}
+
+FORCEINLINE
+BOOLEAN
+IsNullGuid(IN PGUID Guid)
+{
+ if (Guid->Data1 == 0 && Guid->Data2 == 0 && Guid->Data3 == 0
&&
+ ((ULONG *)Guid->Data4)[0] == 0 && ((ULONG *)Guid->Data4)[1] == 0)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+FORCEINLINE
+BOOLEAN
+IsEven(IN USHORT Digit)
+{
+ return ((Digit & 1) != 1);
+}
+
+NTKERNELAPI
+NTSTATUS
+NTAPI
+FsRtlValidateReparsePointBuffer(IN ULONG BufferLength,
+ IN PREPARSE_DATA_BUFFER ReparseBuffer)
+{
+ USHORT DataLength;
+ ULONG ReparseTag;
+ PREPARSE_GUID_DATA_BUFFER GuidBuffer;
+
+ /* Validate data size range */
+ if (BufferLength < REPARSE_DATA_BUFFER_HEADER_SIZE || BufferLength >
MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
+ {
+ return STATUS_IO_REPARSE_DATA_INVALID;
+ }
+
+ GuidBuffer = (PREPARSE_GUID_DATA_BUFFER)ReparseBuffer;
+ DataLength = ReparseBuffer->ReparseDataLength;
+ ReparseTag = ReparseBuffer->ReparseTag;
+
+ /* Validate size consistency */
+ if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE != BufferLength &&
DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE != BufferLength)
+ {
+ return STATUS_IO_REPARSE_DATA_INVALID;
+ }
+
+ /* REPARSE_DATA_BUFFER is reserved for MS tags */
+ if (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE == BufferLength &&
!IsReparseTagMicrosoft(ReparseTag))
+ {
+ return STATUS_IO_REPARSE_DATA_INVALID;
+ }
+
+ /* If that a GUID data buffer, its GUID cannot be null, and it cannot contain a MS
tag */
+ if (DataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE == BufferLength &&
((!IsReparseTagMicrosoft(ReparseTag)
+ && IsNullGuid(&GuidBuffer->ReparseGuid)) || (ReparseTag ==
IO_REPARSE_TAG_MOUNT_POINT || ReparseTag == IO_REPARSE_TAG_SYMLINK)))
+ {
+ return STATUS_IO_REPARSE_DATA_INVALID;
+ }
+
+ /* Check the data for MS non reserved tags */
+ if (!(ReparseTag & 0xFFF0000) && ReparseTag !=
IO_REPARSE_TAG_RESERVED_ZERO && ReparseTag != IO_REPARSE_TAG_RESERVED_ONE)
+ {
+ /* If that's a mount point, validate the MountPointReparseBuffer branch */
+ if (ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
+ {
+ /* We need information */
+ if (DataLength >= REPARSE_DATA_BUFFER_HEADER_SIZE)
+ {
+ /* Substitue must be the first in row */
+ if (!ReparseBuffer->MountPointReparseBuffer.SubstituteNameOffset)
+ {
+ /* Substitude must be null-terminated */
+ if (ReparseBuffer->MountPointReparseBuffer.PrintNameOffset ==
ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength + sizeof(UNICODE_NULL))
+ {
+ /* There must just be the Offset/Length fields + buffer + 2 null
chars */
+ if (DataLength ==
ReparseBuffer->MountPointReparseBuffer.PrintNameLength +
ReparseBuffer->MountPointReparseBuffer.SubstituteNameLength +
(FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) -
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.SubstituteNameOffset)) + 2 *
sizeof(UNICODE_NULL))
+ {
+ return STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+#define FIELDS_SIZE (FIELD_OFFSET(REPARSE_DATA_BUFFER,
SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER,
SymbolicLinkReparseBuffer.SubstituteNameOffset))
+
+ /* If that's not a symlink, accept the MS tag as it */
+ if (ReparseTag != IO_REPARSE_TAG_SYMLINK)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ /* We need information */
+ if (DataLength >= FIELDS_SIZE)
+ {
+ /* Validate lengths */
+ if (ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength
&& ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength)
+ {
+ /* Validate unicode strings */
+ if
(IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength) &&
IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength) &&
+
IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset) &&
IsEven(ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset))
+ {
+ if ((DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE >=
ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset +
ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength + FIELDS_SIZE +
REPARSE_DATA_BUFFER_HEADER_SIZE)
+ && (DataLength + REPARSE_DATA_BUFFER_HEADER_SIZE
>= ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength +
ReparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset + FIELDS_SIZE +
REPARSE_DATA_BUFFER_HEADER_SIZE))
+ {
+ return STATUS_SUCCESS;
+ }
+ }
+ }
+ }
+#undef FIELDS_SIZE
+ }
+
+ return STATUS_IO_REPARSE_DATA_INVALID;
+ }
+
+ return STATUS_IO_REPARSE_TAG_INVALID;
+}
+