mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[NDK]: Add OB_FLAG_KERNEL_EXCLUSIVE and OBJ_KERNEL_EXCLUSIVE flags
[NTOSKRNL]: Add a helper function such that user-mode cannot pass certain kernel-only object attributes to ObOpenObjectByPointer. [NTOSKRNL]: Make \Device\PhysicalMemory OBJ_KERNEL_EXCLUSIVE [NTOSKRNL]: Deny access to user-mode when opening a handle to an object with OBJ_KERNEL_EXCLUSIVE [NTOSKRNL]: Fix NtOpenProcess, NtOpenThread, NtOpenThreadTokenEx, NtOpenProcessTokenEx to use the helper function. Should fix Rtl using OBJ_KERNEL_HANDLE in user-mode. Thanks to ThFabba for finding out these bugs, and the hbelusca for adding a missing check to NtOpenProcessTokenEx. svn path=/trunk/; revision=69340
This commit is contained in:
parent
d65c53b046
commit
f8f8f5c96b
10 changed files with 65 additions and 12 deletions
|
@ -85,6 +85,12 @@ typedef enum _OBJECT_INFORMATION_CLASS
|
|||
|
||||
#else
|
||||
|
||||
//
|
||||
// Undocumented Attribute for Kernel-Only Access
|
||||
//
|
||||
#define OBJ_KERNEL_EXCLUSIVE 0x00010000L
|
||||
#define OBJ_VALID_KERNEL_ATTRIBUTES (OBJ_VALID_ATTRIBUTES | \
|
||||
OBJ_KERNEL_EXCLUSIVE)
|
||||
//
|
||||
// Object Flags
|
||||
//
|
||||
|
@ -97,6 +103,11 @@ typedef enum _OBJECT_INFORMATION_CLASS
|
|||
#define OB_FLAG_SINGLE_PROCESS 0x40
|
||||
#define OB_FLAG_DEFER_DELETE 0x80
|
||||
|
||||
//
|
||||
// Object Flags encoded in "QueryReferences" field
|
||||
//
|
||||
#define OB_FLAG_KERNEL_EXCLUSIVE 0x40000000
|
||||
|
||||
#define OBJECT_TO_OBJECT_HEADER(o) \
|
||||
CONTAINING_RECORD((o), OBJECT_HEADER, Body)
|
||||
|
||||
|
|
|
@ -17,6 +17,24 @@
|
|||
|
||||
#define OBP_NAME_LOOKASIDE_MAX_SIZE 248
|
||||
|
||||
FORCEINLINE
|
||||
ULONG
|
||||
ObpValidateAttributes(IN ULONG Attributes,
|
||||
IN KPROCESSOR_MODE PreviousMode)
|
||||
{
|
||||
if (PreviousMode == KernelMode)
|
||||
{
|
||||
/* For kernel, allow any valid attributes */
|
||||
return Attributes & OBJ_VALID_KERNEL_ATTRIBUTES;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For user, mask out kernel-only attributes */
|
||||
return (Attributes & OBJ_VALID_ATTRIBUTES) &
|
||||
~(OBJ_KERNEL_HANDLE);
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
ULONG
|
||||
ObpSelectObjectLockSlot(IN POBJECT_HEADER ObjectHeader)
|
||||
|
|
|
@ -2756,7 +2756,7 @@ MmCreatePhysicalMemorySection(VOID)
|
|||
SectionSize.QuadPart = 0xFFFFFFFF;
|
||||
InitializeObjectAttributes(&Obj,
|
||||
&Name,
|
||||
OBJ_PERMANENT,
|
||||
OBJ_PERMANENT | OBJ_KERNEL_EXCLUSIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = MmCreateSection((PVOID)&PhysSection,
|
||||
|
|
|
@ -807,6 +807,7 @@ ObpIncrementHandleCount(IN PVOID Object,
|
|||
KIRQL CalloutIrql;
|
||||
KPROCESSOR_MODE ProbeMode;
|
||||
ULONG Total;
|
||||
POBJECT_HEADER_NAME_INFO NameInfo;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the object header and type */
|
||||
|
@ -872,6 +873,16 @@ ObpIncrementHandleCount(IN PVOID Object,
|
|||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Check for exclusive kernel object */
|
||||
NameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||
if ((NameInfo) && (NameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE) &&
|
||||
(ProbeMode != KernelMode))
|
||||
{
|
||||
/* Caller is not kernel, but the object is kernel exclusive */
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if this is an object that went from 0 handles back to existence,
|
||||
* but doesn't have an open procedure, only a close procedure. This means
|
||||
|
|
|
@ -731,10 +731,10 @@ ObpAllocateObject(IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
|
|||
/* Check if this is a call with the special protection flag */
|
||||
if ((PreviousMode == KernelMode) &&
|
||||
(ObjectCreateInfo) &&
|
||||
(ObjectCreateInfo->Attributes & 0x10000))
|
||||
(ObjectCreateInfo->Attributes & OBJ_KERNEL_EXCLUSIVE))
|
||||
{
|
||||
/* Set flag which will make the object protected from user-mode */
|
||||
NameInfo->QueryReferences |= 0x40000000;
|
||||
NameInfo->QueryReferences |= OB_FLAG_KERNEL_EXCLUSIVE;
|
||||
}
|
||||
|
||||
/* Set the header pointer */
|
||||
|
|
|
@ -261,14 +261,14 @@ ObpDeleteNameCheck(IN PVOID Object)
|
|||
ObpDeleteSymbolicLinkName(Object);
|
||||
}
|
||||
|
||||
/* Check if the magic protection flag is set */
|
||||
/* Check if the kernel exclusive is set */
|
||||
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
|
||||
if ((ObjectNameInfo) &&
|
||||
(ObjectNameInfo->QueryReferences & 0x40000000))
|
||||
(ObjectNameInfo->QueryReferences & OB_FLAG_KERNEL_EXCLUSIVE))
|
||||
{
|
||||
/* Remove protection flag */
|
||||
InterlockedExchangeAdd((PLONG)&ObjectNameInfo->QueryReferences,
|
||||
-0x40000000);
|
||||
-OB_FLAG_KERNEL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/* Get the directory */
|
||||
|
|
|
@ -1483,7 +1483,9 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
|
|||
sizeof(OBJECT_ATTRIBUTES),
|
||||
sizeof(ULONG));
|
||||
HasObjectName = (ObjectAttributes->ObjectName != NULL);
|
||||
Attributes = ObjectAttributes->Attributes;
|
||||
|
||||
/* Validate user attributes */
|
||||
Attributes = ObpValidateAttributes(ObjectAttributes->Attributes, PreviousMode);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -1496,7 +1498,9 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
|
|||
{
|
||||
/* Otherwise just get the data directly */
|
||||
HasObjectName = (ObjectAttributes->ObjectName != NULL);
|
||||
Attributes = ObjectAttributes->Attributes;
|
||||
|
||||
/* Still have to sanitize attributes */
|
||||
Attributes = ObpValidateAttributes(ObjectAttributes->Attributes, PreviousMode);
|
||||
}
|
||||
|
||||
/* Can't pass both, fail */
|
||||
|
|
|
@ -371,6 +371,9 @@ NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
|
|||
_SEH2_END;
|
||||
}
|
||||
|
||||
/* Validate object attributes */
|
||||
HandleAttributes = ObpValidateAttributes(HandleAttributes, PreviousMode);
|
||||
|
||||
/* Open the process token */
|
||||
Status = PsOpenTokenOfProcess(ProcessHandle, &Token);
|
||||
if (NT_SUCCESS(Status))
|
||||
|
|
|
@ -1054,7 +1054,9 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
|
|||
sizeof(OBJECT_ATTRIBUTES),
|
||||
sizeof(ULONG));
|
||||
HasObjectName = (ObjectAttributes->ObjectName != NULL);
|
||||
Attributes = ObjectAttributes->Attributes;
|
||||
|
||||
/* Validate user attributes */
|
||||
Attributes = ObpValidateAttributes(ObjectAttributes->Attributes, PreviousMode);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -1067,7 +1069,9 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
|
|||
{
|
||||
/* Otherwise just get the data directly */
|
||||
HasObjectName = (ObjectAttributes->ObjectName != NULL);
|
||||
Attributes = ObjectAttributes->Attributes;
|
||||
|
||||
/* Still have to sanitize attributes */
|
||||
Attributes = ObpValidateAttributes(ObjectAttributes->Attributes, PreviousMode);
|
||||
}
|
||||
|
||||
/* Can't pass both, fail */
|
||||
|
|
|
@ -2952,10 +2952,12 @@ NtOpenThreadTokenEx(IN HANDLE ThreadHandle,
|
|||
_SEH2_END;
|
||||
}
|
||||
|
||||
/* Validate object attributes */
|
||||
HandleAttributes = ObpValidateAttributes(HandleAttributes, PreviousMode);
|
||||
|
||||
/*
|
||||
* At first open the thread token for information access and verify
|
||||
* that the token associated with thread is valid.
|
||||
*/
|
||||
* that the token associated with thread is valid. */
|
||||
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_QUERY_INFORMATION,
|
||||
PsThreadType, PreviousMode, (PVOID*)&Thread,
|
||||
|
|
Loading…
Reference in a new issue