[NTOS:EX]

- Use all handles enumeration in system instead of enumeration for each process
See issue 11906 for more details.

svn path=/trunk/; revision=72530
This commit is contained in:
Dmitry Chapyshev 2016-09-01 16:39:54 +00:00
parent 27e451c99f
commit 125c4571ad

View file

@ -17,6 +17,9 @@
/* The maximum size of an environment value (in bytes) */ /* The maximum size of an environment value (in bytes) */
#define MAX_ENVVAL_SIZE 1024 #define MAX_ENVVAL_SIZE 1024
extern LIST_ENTRY HandleTableListHead;
extern EX_PUSH_LOCK HandleTableListLock;
FAST_MUTEX ExpEnvironmentLock; FAST_MUTEX ExpEnvironmentLock;
ERESOURCE ExpFirmwareTableResource; ERESOURCE ExpFirmwareTableResource;
LIST_ENTRY ExpFirmwareTableProviderListHead; LIST_ENTRY ExpFirmwareTableProviderListHead;
@ -1168,53 +1171,25 @@ QSI_DEF(SystemNonPagedPoolInformation)
QSI_DEF(SystemHandleInformation) QSI_DEF(SystemHandleInformation)
{ {
PSYSTEM_HANDLE_INFORMATION HandleInformation; PSYSTEM_HANDLE_INFORMATION HandleInformation;
KPROCESSOR_MODE PreviousMode; ULONG Index = 0;
PEPROCESS Process;
PEPROCESS SystemProcess;
ULONG CurrentSize;
ULONG NumberOfHandles = 0;
ULONG Index;
NTSTATUS Status; NTSTATUS Status;
PMDL Mdl; PMDL Mdl;
DPRINT("NtQuerySystemInformation - SystemHandleInformation\n"); DPRINT("NtQuerySystemInformation - SystemHandleInformation\n");
/* Set initial required buffer size */
*ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION);
/* Check user's buffer size */ /* Check user's buffer size */
if (Size < sizeof(SYSTEM_HANDLE_INFORMATION)) if (Size < *ReqSize)
{ {
*ReqSize = sizeof(SYSTEM_HANDLE_INFORMATION);
return STATUS_INFO_LENGTH_MISMATCH; return STATUS_INFO_LENGTH_MISMATCH;
} }
/* Retrieve needed buffer size to hold the list of handles */
SystemProcess = PsGetNextProcess(NULL);
Process = SystemProcess;
do
{
NumberOfHandles += ObGetProcessHandleCount(Process);
Process = PsGetNextProcess(Process);
}
while ((Process != SystemProcess) && (Process != NULL));
/* Dereference the process which was referenced by PsGetNextProcess */
if (Process != NULL) ObDereferenceObject(Process);
/* Calculate the current size of all handles */
CurrentSize = sizeof(SYSTEM_HANDLE_INFORMATION) +
((sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO) * NumberOfHandles) -
(sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO)));
*ReqSize = CurrentSize;
/* Check user's buffer size */
if (CurrentSize > Size) return STATUS_INFO_LENGTH_MISMATCH;
/* We need to lock down the memory */ /* We need to lock down the memory */
PreviousMode = ExGetPreviousMode();
Status = ExLockUserBuffer(Buffer, Status = ExLockUserBuffer(Buffer,
Size, Size,
PreviousMode, ExGetPreviousMode(),
IoWriteAccess, IoWriteAccess,
(PVOID*)&HandleInformation, (PVOID*)&HandleInformation,
&Mdl); &Mdl);
@ -1224,91 +1199,111 @@ QSI_DEF(SystemHandleInformation)
return Status; return Status;
} }
/* Initialization of count of handles */ _SEH2_TRY
HandleInformation->NumberOfHandles = NumberOfHandles;
/* Now get handles from all processes. */
SystemProcess = PsGetNextProcess(NULL);
Process = SystemProcess;
Index = 0;
do
{ {
PHANDLE_TABLE_ENTRY HandleTableEntry; PLIST_ENTRY NextTableEntry;
EXHANDLE Handle;
/* Enter a critical region */ /* Enumerate all system handles */
KeEnterCriticalRegion(); for (NextTableEntry = HandleTableListHead.Flink;
NextTableEntry != &HandleTableListHead;
_SEH2_TRY NextTableEntry = NextTableEntry->Flink)
{ {
/* Set the initial value and loop the entries */ PHANDLE_TABLE HandleTable;
Handle.Value = 0;
while ((HandleTableEntry = ExpLookupHandleTableEntry(Process->ObjectTable, Handle))) /* Enter a critical region */
KeEnterCriticalRegion();
/* Acquire the handle table lock */
ExAcquirePushLockExclusive(&HandleTableListLock);
/* Get current handle table */
HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList);
_SEH2_TRY
{ {
/* Validate the entry */ PHANDLE_TABLE_ENTRY HandleTableEntry;
if ((HandleTableEntry->Object) && EXHANDLE Handle;
(HandleTableEntry->NextFreeTableEntry != -2))
/* Set the initial value and loop the entries */
Handle.Value = 0;
while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
{ {
/* Lock the entry */ /* Validate the entry */
if (ExpLockHandleTableEntry(Process->ObjectTable, HandleTableEntry)) if ((HandleTableEntry->Object) &&
(HandleTableEntry->NextFreeTableEntry != -2))
{ {
_SEH2_TRY /* Increase of count of handles */
++HandleInformation->NumberOfHandles;
/* Increase required buffer size */
*ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO);
/* Check user's buffer size */
if (*ReqSize > Size)
{ {
POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); /* It is correct? How it is correct to leave the enclosed SEH blocks? */
_SEH2_YIELD(return STATUS_INFO_LENGTH_MISMATCH);
/* Filling handle information */
HandleInformation->Handles[Index].UniqueProcessId =
(USHORT)(ULONG_PTR) Process->UniqueProcessId;
HandleInformation->Handles[Index].CreatorBackTraceIndex = 0;
HandleInformation->Handles[Index].ObjectTypeIndex =
(UCHAR) ObjectHeader->Type->Index;
HandleInformation->Handles[Index].HandleAttributes =
HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
HandleInformation->Handles[Index].HandleValue =
(USHORT)(ULONG_PTR) Handle.GenericHandleOverlay;
HandleInformation->Handles[Index].Object = &ObjectHeader->Body;
HandleInformation->Handles[Index].GrantedAccess =
HandleTableEntry->GrantedAccess;
++Index;
} }
_SEH2_FINALLY
/* Lock the entry */
if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
{ {
/* Unlock it */ _SEH2_TRY
ExUnlockHandleTableEntry(Process->ObjectTable, HandleTableEntry); {
POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry);
/* Filling handle information */
HandleInformation->Handles[Index].UniqueProcessId =
(USHORT)(ULONG_PTR) HandleTable->UniqueProcessId;
HandleInformation->Handles[Index].CreatorBackTraceIndex = 0;
HandleInformation->Handles[Index].ObjectTypeIndex =
(UCHAR) ObjectHeader->Type->Index;
HandleInformation->Handles[Index].HandleAttributes =
HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES;
HandleInformation->Handles[Index].HandleValue =
(USHORT)(ULONG_PTR) Handle.GenericHandleOverlay;
HandleInformation->Handles[Index].Object = &ObjectHeader->Body;
HandleInformation->Handles[Index].GrantedAccess =
HandleTableEntry->GrantedAccess;
++Index;
}
_SEH2_FINALLY
{
/* Unlock it */
ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
}
_SEH2_END;
} }
_SEH2_END;
} }
/* Go to the next entry */
Handle.Value += sizeof(HANDLE);
} }
/* Go to the next entry */
Handle.Value += sizeof(HANDLE);
} }
} _SEH2_FINALLY
_SEH2_FINALLY {
{ /* Release the lock */
/* Leave the critical region */ ExReleasePushLockExclusive(&HandleTableListLock);
KeLeaveCriticalRegion();
}
_SEH2_END;
Process = PsGetNextProcess(Process); /* Leave the critical region */
KeLeaveCriticalRegion();
}
_SEH2_END;
}
} }
while ((Process != SystemProcess) && (Process != NULL)); _SEH2_FINALLY
{
/* Dereference the process which was referenced by PsGetNextProcess */ /* Release the locked user buffer */
if (Process != NULL) ObDereferenceObject(Process); ExUnlockUserBuffer(Mdl);
}
/* Release the locked user buffer */ _SEH2_END;
ExUnlockUserBuffer(Mdl);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }