mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 19:12:57 +00:00
- Fix MSVC breakage caused by recent modifications of cctypes.h.
- Remove structures from ntifs.h that shouldn't be there. - Add support for optimized detection of a DOS device path \?? or \??\ and implement it into ObpLookupObjectName. - Add support for proper re-parsing up to a maximum of 30 times to avoid reparse DOS attacks on the kernel. - Set WIN32_WINNT version to Windows 2003 SP1. svn path=/trunk/; revision=25602
This commit is contained in:
parent
b5edfb619c
commit
89056c2f7a
7 changed files with 546 additions and 427 deletions
|
@ -50,6 +50,9 @@ extern "C" {
|
|||
#define NTSYSAPI
|
||||
#endif
|
||||
|
||||
#define EX_PUSH_LOCK ULONG_PTR
|
||||
#define PEX_PUSH_LOCK PULONG_PTR
|
||||
|
||||
#include "csq.h"
|
||||
|
||||
typedef struct _SE_EXPORTS *PSE_EXPORTS;
|
||||
|
@ -1402,35 +1405,6 @@ typedef struct _PATHNAME_BUFFER {
|
|||
WCHAR Name[1];
|
||||
} PATHNAME_BUFFER, *PPATHNAME_BUFFER;
|
||||
|
||||
#if (VER_PRODUCTBUILD >= 2600)
|
||||
|
||||
typedef struct _PRIVATE_CACHE_MAP_FLAGS {
|
||||
ULONG DontUse : 16;
|
||||
ULONG ReadAheadActive : 1;
|
||||
ULONG ReadAheadEnabled : 1;
|
||||
ULONG Available : 14;
|
||||
} PRIVATE_CACHE_MAP_FLAGS, *PPRIVATE_CACHE_MAP_FLAGS;
|
||||
|
||||
typedef struct _PRIVATE_CACHE_MAP {
|
||||
_ANONYMOUS_UNION union {
|
||||
CSHORT NodeTypeCode;
|
||||
PRIVATE_CACHE_MAP_FLAGS Flags;
|
||||
ULONG UlongFlags;
|
||||
} DUMMYUNIONNAME;
|
||||
ULONG ReadAheadMask;
|
||||
PFILE_OBJECT FileObject;
|
||||
LARGE_INTEGER FileOffset1;
|
||||
LARGE_INTEGER BeyondLastByte1;
|
||||
LARGE_INTEGER FileOffset2;
|
||||
LARGE_INTEGER BeyondLastByte2;
|
||||
LARGE_INTEGER ReadAheadOffset[2];
|
||||
ULONG ReadAheadLength[2];
|
||||
KSPIN_LOCK ReadAheadSpinLock;
|
||||
LIST_ENTRY PrivateLinks;
|
||||
} PRIVATE_CACHE_MAP, *PPRIVATE_CACHE_MAP;
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum _RTL_GENERIC_COMPARE_RESULTS
|
||||
{
|
||||
GenericLessThan,
|
||||
|
@ -1715,16 +1689,6 @@ typedef struct _TUNNEL {
|
|||
USHORT NumEntries;
|
||||
} TUNNEL, *PTUNNEL;
|
||||
|
||||
typedef struct _VACB {
|
||||
PVOID BaseAddress;
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
union {
|
||||
LARGE_INTEGER FileOffset;
|
||||
USHORT ActiveCount;
|
||||
} Overlay;
|
||||
LIST_ENTRY LruList;
|
||||
} VACB, *PVACB;
|
||||
|
||||
typedef struct _VAD_HEADER {
|
||||
PVOID StartVPN;
|
||||
PVOID EndVPN;
|
||||
|
|
|
@ -35,10 +35,59 @@ extern ULONG NTSYSAPI CcFastReadResourceMiss;
|
|||
extern ULONG NTSYSAPI CcFastReadNoWait;
|
||||
extern ULONG NTSYSAPI CcFastMdlReadNotPossible;
|
||||
|
||||
//
|
||||
// Virtual Address Control BLock
|
||||
//
|
||||
typedef struct _VACB
|
||||
{
|
||||
PVOID BaseAddress;
|
||||
struct _SHARED_CACHE_MAP *SharedCacheMap;
|
||||
union
|
||||
{
|
||||
LARGE_INTEGER FileOffset;
|
||||
USHORT ActiveCount;
|
||||
} Overlay;
|
||||
LIST_ENTRY LruList;
|
||||
} VACB, *PVACB;
|
||||
|
||||
//
|
||||
// Private Cache Map Structure and Flags
|
||||
//
|
||||
typedef struct _PRIVATE_CACHE_MAP_FLAGS
|
||||
{
|
||||
ULONG DontUse:16;
|
||||
ULONG ReadAheadActive:1;
|
||||
ULONG ReadAheadEnabled:1;
|
||||
ULONG Available:14;
|
||||
} PRIVATE_CACHE_MAP_FLAGS;
|
||||
|
||||
typedef struct _PRIVATE_CACHE_MAP
|
||||
{
|
||||
union
|
||||
{
|
||||
CSHORT NodeTypeCode;
|
||||
PRIVATE_CACHE_MAP_FLAGS Flags;
|
||||
ULONG UlongFlags;
|
||||
};
|
||||
ULONG ReadAheadMask;
|
||||
PFILE_OBJECT FileObject;
|
||||
LARGE_INTEGER FileOffset1;
|
||||
LARGE_INTEGER BeyondLastByte1;
|
||||
LARGE_INTEGER FileOffset2;
|
||||
LARGE_INTEGER BeyondLastByte2;
|
||||
LARGE_INTEGER ReadAheadOffset[2];
|
||||
ULONG ReadAheadLength[2];
|
||||
KSPIN_LOCK ReadAheadSpinLock;
|
||||
LIST_ENTRY PrivateLinks;
|
||||
} PRIVATE_CACHE_MAP, *PPRIVATE_CACHE_MAP;
|
||||
|
||||
#ifdef _NTIFS_INCLUDED_
|
||||
|
||||
typedef struct _SHARED_CACHE_MAP {
|
||||
//
|
||||
// Shared Cache Map
|
||||
//
|
||||
typedef struct _SHARED_CACHE_MAP
|
||||
{
|
||||
SHORT NodeTypeCode;
|
||||
SHORT NodeByteSize;
|
||||
ULONG OpenCount;
|
||||
|
@ -78,12 +127,10 @@ typedef struct _SHARED_CACHE_MAP {
|
|||
ULONG BcbSpinLock;
|
||||
PVOID Reserved;
|
||||
KEVENT Event;
|
||||
/* FIX ME: This should be PEX_PUSH_LOCK */
|
||||
PVOID VacbPushLock;
|
||||
PEX_PUSH_LOCK VacbPushLock;
|
||||
PPRIVATE_CACHE_MAP PrivateCacheMap;
|
||||
} SHARED_CACHE_MAP;
|
||||
|
||||
|
||||
#endif /* _NTIFS_INCLUDED_ */
|
||||
#endif /* NTOS_MODE_USER */
|
||||
#endif /* _CCTYPES_H */
|
||||
|
|
|
@ -362,7 +362,7 @@ ExTimedWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
|
|||
VOID
|
||||
FASTCALL
|
||||
ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
|
||||
IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock)
|
||||
IN PVOID WaitBlock)
|
||||
{
|
||||
/* Call the timed function with no timeout */
|
||||
ExTimedWaitForUnblockPushLock(PushLock, WaitBlock, NULL);
|
||||
|
|
|
@ -652,18 +652,24 @@ _ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
|
|||
|
||||
VOID
|
||||
FASTCALL
|
||||
ExBlockPushLock(PEX_PUSH_LOCK PushLock,
|
||||
PVOID WaitBlock);
|
||||
ExBlockPushLock(
|
||||
IN PEX_PUSH_LOCK PushLock,
|
||||
IN PVOID WaitBlock
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ExfUnblockPushLock(PEX_PUSH_LOCK PushLock,
|
||||
PVOID CurrentWaitBlock);
|
||||
ExfUnblockPushLock(
|
||||
IN PEX_PUSH_LOCK PushLock,
|
||||
IN PVOID CurrentWaitBlock
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock,
|
||||
IN PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock);
|
||||
ExWaitForUnblockPushLock(
|
||||
IN PEX_PUSH_LOCK PushLock,
|
||||
IN PVOID WaitBlock
|
||||
);
|
||||
|
||||
/*++
|
||||
* @name ExInitializePushLock
|
||||
|
|
|
@ -102,6 +102,15 @@ typedef struct _OBP_FIND_HANDLE_DATA
|
|||
POBJECT_HANDLE_INFORMATION HandleInformation;
|
||||
} OBP_FIND_HANDLE_DATA, *POBP_FIND_HANDLE_DATA;
|
||||
|
||||
//
|
||||
// Structure for quick-compare of a DOS Device path
|
||||
//
|
||||
typedef union
|
||||
{
|
||||
WCHAR Name[sizeof(ULARGE_INTEGER) / sizeof(WCHAR)];
|
||||
ULARGE_INTEGER Alignment;
|
||||
} ALIGNEDNAME;
|
||||
|
||||
//
|
||||
// Private Temporary Buffer for Lookup Routines
|
||||
//
|
||||
|
@ -502,6 +511,9 @@ extern WORK_QUEUE_ITEM ObpReaperWorkItem;
|
|||
extern volatile PVOID ObpReaperList;
|
||||
extern NPAGED_LOOKASIDE_LIST ObpNmLookasideList, ObpCiLookasideList;
|
||||
extern BOOLEAN IoCountOperations;
|
||||
extern ALIGNEDNAME ObpDosDevicesShortNamePrefix;
|
||||
extern ALIGNEDNAME ObpDosDevicesShortNameRoot;
|
||||
extern UNICODE_STRING ObpDosDevicesShortName;
|
||||
|
||||
//
|
||||
// Inlined Functions
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/* INCLUDES ******************************************************************/
|
||||
|
||||
/* Always target Windows 2003 Service Pack 1 */
|
||||
#undef NTDDI_VERSION
|
||||
#define _WIN32_WINNT _WIN32_WINNT_WS03
|
||||
#define NTDDI_VERSION NTDDI_WS03SP1
|
||||
#define NTKERNELAPI
|
||||
|
||||
|
|
|
@ -16,8 +16,18 @@
|
|||
#include <debug.h>
|
||||
|
||||
BOOLEAN ObpCaseInsensitive = TRUE;
|
||||
POBJECT_DIRECTORY NameSpaceRoot = NULL;
|
||||
POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
|
||||
POBJECT_DIRECTORY NameSpaceRoot;
|
||||
POBJECT_DIRECTORY ObpTypeDirectoryObject;
|
||||
|
||||
/* DOS Device Prefix \??\ and \?? */
|
||||
ALIGNEDNAME ObpDosDevicesShortNamePrefix = {{L'\\',L'?',L'?',L'\\'}};
|
||||
ALIGNEDNAME ObpDosDevicesShortNameRoot = {{L'\\',L'?',L'?',L'\0'}};
|
||||
UNICODE_STRING ObpDosDevicesShortName =
|
||||
{
|
||||
sizeof(ObpDosDevicesShortNamePrefix),
|
||||
sizeof(ObpDosDevicesShortNamePrefix),
|
||||
(PWSTR)&ObpDosDevicesShortNamePrefix
|
||||
};
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
|
@ -256,22 +266,22 @@ ObpDeleteNameCheck(IN PVOID Object)
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ObpLookupObjectName(IN HANDLE RootHandle,
|
||||
ObpLookupObjectName(IN HANDLE RootHandle OPTIONAL,
|
||||
IN PUNICODE_STRING ObjectName,
|
||||
IN ULONG Attributes,
|
||||
IN POBJECT_TYPE ObjectType,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN OUT PVOID ParseContext,
|
||||
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
|
||||
IN PVOID InsertObject,
|
||||
IN PACCESS_STATE AccessState,
|
||||
IN POBP_LOOKUP_CONTEXT LookupContext,
|
||||
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
|
||||
IN PVOID InsertObject OPTIONAL,
|
||||
IN OUT PACCESS_STATE AccessState,
|
||||
OUT POBP_LOOKUP_CONTEXT LookupContext,
|
||||
OUT PVOID *FoundObject)
|
||||
{
|
||||
PVOID Object;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
UNICODE_STRING ComponentName, RemainingName;
|
||||
BOOLEAN InsideRoot = FALSE;
|
||||
BOOLEAN Reparse = FALSE, SymLink = FALSE;
|
||||
PDEVICE_MAP DeviceMap = NULL;
|
||||
POBJECT_DIRECTORY Directory = NULL, ParentDirectory = NULL, RootDirectory;
|
||||
POBJECT_DIRECTORY ReferencedDirectory = NULL, ReferencedParentDirectory = NULL;
|
||||
|
@ -281,6 +291,7 @@ ObpLookupObjectName(IN HANDLE RootHandle,
|
|||
KPROCESSOR_MODE AccessCheckMode;
|
||||
PWCHAR NewName;
|
||||
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
|
||||
ULONG MaxReparse = 30;
|
||||
PAGED_CODE();
|
||||
OBTRACE(OB_NAMESPACE_DEBUG,
|
||||
"%s - Finding Object: %wZ. Expecting: %p\n",
|
||||
|
@ -346,6 +357,9 @@ ObpLookupObjectName(IN HANDLE RootHandle,
|
|||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* Set default parse count */
|
||||
MaxReparse = 30;
|
||||
|
||||
/* Now parse */
|
||||
while (TRUE)
|
||||
{
|
||||
|
@ -397,7 +411,22 @@ ObpLookupObjectName(IN HANDLE RootHandle,
|
|||
|
||||
/* Don't use this anymore, since we're starting at root */
|
||||
RootHandle = NULL;
|
||||
break;
|
||||
goto ParseFromRoot;
|
||||
}
|
||||
else if (--MaxReparse)
|
||||
{
|
||||
/* Try reparsing again */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reparsed too many times */
|
||||
ObDereferenceObject(RootDirectory);
|
||||
|
||||
/* Return the object and normalized status */
|
||||
*FoundObject = Object;
|
||||
if (!Object) Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -465,22 +494,70 @@ ObpLookupObjectName(IN HANDLE RootHandle,
|
|||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseFromRoot:
|
||||
/* Check if we have a device map */
|
||||
if (DeviceMap)
|
||||
{
|
||||
/* Dereference it */
|
||||
ObfDereferenceDeviceMap(DeviceMap);
|
||||
DeviceMap = NULL;
|
||||
}
|
||||
|
||||
/* Save the name */
|
||||
ReparseNewDir:
|
||||
RemainingName = *ObjectName;
|
||||
/* Check if this is a possible DOS name */
|
||||
if (!((ULONG_PTR)(ObjectName->Buffer) & 7))
|
||||
{
|
||||
/*
|
||||
* This could be one. Does it match the prefix?
|
||||
* Note that as an optimization, the match is done as 64-bit
|
||||
* compare since the prefix is "\??\" which is exactly 8 bytes.
|
||||
*
|
||||
* In the second branch, we test for "\??" which is also valid.
|
||||
* This time, we use a 32-bit compare followed by a Unicode
|
||||
* character compare (16-bit), since the sum is 6 bytes.
|
||||
*/
|
||||
if ((ObjectName->Length >= ObpDosDevicesShortName.Length) &&
|
||||
(*(PULONGLONG)(ObjectName->Buffer) ==
|
||||
ObpDosDevicesShortNamePrefix.Alignment.QuadPart))
|
||||
{
|
||||
/* FIXME! */
|
||||
}
|
||||
else if ((ObjectName->Length == ObpDosDevicesShortName.Length -
|
||||
sizeof(WCHAR)) &&
|
||||
(*(PULONG)(ObjectName->Buffer) ==
|
||||
ObpDosDevicesShortNameRoot.Alignment.LowPart) &&
|
||||
(*((PWCHAR)(ObjectName->Buffer) + 2) ==
|
||||
(WCHAR)(ObpDosDevicesShortNameRoot.Alignment.HighPart)))
|
||||
{
|
||||
/* FIXME! */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we were reparsing a symbolic link */
|
||||
if (!SymLink)
|
||||
{
|
||||
/* Allow reparse */
|
||||
Reparse = TRUE;
|
||||
MaxReparse = 30;
|
||||
}
|
||||
|
||||
/* Reparse */
|
||||
while (Reparse)
|
||||
{
|
||||
/* Get the name */
|
||||
RemainingName = *ObjectName;
|
||||
|
||||
/* Disable reparsing again */
|
||||
Reparse = FALSE;
|
||||
|
||||
/* Start parse loop */
|
||||
while (TRUE)
|
||||
{
|
||||
/* Check if we should use the Root Directory */
|
||||
if (!InsideRoot)
|
||||
{
|
||||
/* Yes, use the root directory and remember that */
|
||||
Directory = RootDirectory;
|
||||
InsideRoot = TRUE;
|
||||
}
|
||||
/* Clear object */
|
||||
Object = NULL;
|
||||
|
||||
/* Check if the name starts with a path separator */
|
||||
if ((RemainingName.Length) &&
|
||||
|
@ -512,6 +589,9 @@ ReparseNewDir:
|
|||
break;
|
||||
}
|
||||
|
||||
/* Check if we're in the root */
|
||||
if (!Directory) Directory = RootDirectory;
|
||||
|
||||
/* Check if this is a user-mode call that needs to traverse */
|
||||
if ((AccessCheckMode != KernelMode) &&
|
||||
!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE))
|
||||
|
@ -656,7 +736,7 @@ ReparseNewDir:
|
|||
break;
|
||||
}
|
||||
|
||||
Reparse:
|
||||
ReparseObject:
|
||||
/* We found it, so now get its header */
|
||||
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
||||
|
||||
|
@ -669,7 +749,7 @@ Reparse:
|
|||
(!(InsertObject) || (ParseRoutine == ObpParseSymbolicLink)))
|
||||
{
|
||||
/* Use the Root Directory next time */
|
||||
InsideRoot = FALSE;
|
||||
Directory = NULL;
|
||||
|
||||
/* Increment the pointer count */
|
||||
InterlockedExchangeAdd(&ObjectHeader->PointerCount, 1);
|
||||
|
@ -714,6 +794,9 @@ Reparse:
|
|||
if ((Status == STATUS_REPARSE) ||
|
||||
(Status == STATUS_REPARSE_OBJECT))
|
||||
{
|
||||
/* Reparse again */
|
||||
Reparse = TRUE;
|
||||
|
||||
/* Start over from root if we got sent back there */
|
||||
if ((Status == STATUS_REPARSE_OBJECT) ||
|
||||
(ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
|
||||
|
@ -733,6 +816,9 @@ Reparse:
|
|||
/* Check for reparse status */
|
||||
if (Status == STATUS_REPARSE_OBJECT)
|
||||
{
|
||||
/* Don't reparse again */
|
||||
Reparse = FALSE;
|
||||
|
||||
/* Did we actually get an object to which to reparse? */
|
||||
if (!Object)
|
||||
{
|
||||
|
@ -742,19 +828,22 @@ Reparse:
|
|||
else
|
||||
{
|
||||
/* We did, so we're free to parse the new object */
|
||||
InsideRoot = TRUE;
|
||||
goto Reparse;
|
||||
goto ReparseObject;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restart the search */
|
||||
goto ReparseNewDir;
|
||||
else
|
||||
{
|
||||
/* This is a symbolic link */
|
||||
SymLink = TRUE;
|
||||
goto ParseFromRoot;
|
||||
}
|
||||
}
|
||||
else if (RootDirectory == NameSpaceRoot)
|
||||
{
|
||||
/* We got STATUS_REPARSE but are at the Root Directory */
|
||||
Object = NULL;
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
Reparse = FALSE;
|
||||
}
|
||||
}
|
||||
else if (!NT_SUCCESS(Status))
|
||||
|
@ -836,6 +925,7 @@ Reparse:
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we failed */
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue