[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:
Alex Ionescu 2015-09-24 02:40:30 +00:00
parent d65c53b046
commit f8f8f5c96b
10 changed files with 65 additions and 12 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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,

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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))

View file

@ -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 */

View file

@ -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,