Simplify buffer checks for NtQueryInformation...() and NtSetInformation...() using universal macros and information class tables Modified: trunk/reactos/ntoskrnl/include/internal/ob.h Modified: trunk/reactos/ntoskrnl/ps/process.c _____
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h --- trunk/reactos/ntoskrnl/include/internal/ob.h 2005-01-21 21:34:49 UTC (rev 13195) +++ trunk/reactos/ntoskrnl/include/internal/ob.h 2005-01-21 21:37:32 UTC (rev 13196) @@ -339,5 +339,169 @@
IN KPROCESSOR_MODE AccessMode, IN BOOLEAN CaptureIfKernel);
+/* object information classes */
+#define ICIF_QUERY 0x1 +#define ICIF_SET 0x2 +#define ICIF_QUERY_SIZE_VARIABLE 0x4 +#define ICIF_SET_SIZE_VARIABLE 0x8 +#define ICIF_SIZE_VARIABLE (ICIF_QUERY_SIZE_VARIABLE | ICIF_SET_SIZE_VARIABLE) + +typedef struct _INFORMATION_CLASS_INFO +{ + ULONG RequiredSizeQUERY; + ULONG RequiredSizeSET; + ULONG AlignmentSET; + ULONG AlignmentQUERY; + ULONG Flags; +} INFORMATION_CLASS_INFO, *PINFORMATION_CLASS_INFO; + +#define ICI_SQ_SAME(Size, Alignment, Flags) \ + { Size, Size, Alignment, Alignment, Flags } + +#define ICI_SQ(SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags) \ + { SizeQuery, SizeSet, AlignmentQuery, AlignmentSet, Flags } + +#define CheckInfoClass(Class, BufferLen, ClassList, StatusVar, Mode) \ + do { \ + if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \ + { \ + if(!(ClassList[Class].Flags & ICIF_##Mode)) \ + { \ + *(StatusVar) = STATUS_INVALID_INFO_CLASS; \ + } \ + else if(ClassList[Class].RequiredSize##Mode > 0 && \ + (BufferLen) != ClassList[Class].RequiredSize##Mode) \ + { \ + if(!(ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) || \ + ((ClassList[Class].Flags & ICIF_##Mode##_SIZE_VARIABLE) && \ + (BufferLen) < ClassList[Class].RequiredSize##Mode)) \ + { \ + *(StatusVar) = STATUS_INFO_LENGTH_MISMATCH; \ + } \ + } \ + } \ + else \ + { \ + *(StatusVar) = STATUS_INVALID_INFO_CLASS; \ + } \ + } while(0) + +#define GetInfoClassAlignment(Class, ClassList, AlignmentVar, Mode) \ + do { \ + if((Class) >= 0 && (Class) < sizeof(ClassList) / sizeof(ClassList[0])) \ + { \ + *(AlignmentVar) = ClassList[Class].Alignment##Mode; \ + } \ + else \ + { \ + *(AlignmentVar) = sizeof(ULONG); \ + } \ + } while(0) + +#define ProbeQueryInfoBuffer(Buffer, BufferLen, Alignment, RetLen, PrevMode, StatusVar) \ + do { \ + if(PrevMode == UserMode) \ + { \ + _SEH_TRY \ + { \ + ProbeForWrite(Buffer, \ + BufferLen, \ + Alignment); \ + if(RetLen != NULL) \ + { \ + ProbeForWrite(RetLen, \ + sizeof(ULONG), \ + 1); \ + } \ + } \ + _SEH_HANDLE \ + { \ + *(StatusVar) = _SEH_GetExceptionCode(); \ + } \ + _SEH_END; \ + \ + if(!NT_SUCCESS(*(StatusVar))) \ + { \ + DPRINT1("ProbeQueryInfoBuffer failed: 0x%x\n", *(StatusVar)); \ + return *(StatusVar); \ + } \ + } \ + } while(0) + +#define ProbeSetInfoBuffer(Buffer, BufferLen, Alignment, PrevMode, StatusVar) \ + do { \ + if(PrevMode == UserMode) \ + { \ + _SEH_TRY \ + { \ + ProbeForRead(Buffer, \ + BufferLen, \ + Alignment); \ + } \ + _SEH_HANDLE \ + { \ + *(StatusVar) = _SEH_GetExceptionCode(); \ + } \ + _SEH_END; \ + \ + if(!NT_SUCCESS(*(StatusVar))) \ + { \ + DPRINT1("ProbeAllInfoBuffer failed: 0x%x\n", *(StatusVar)); \ + return *(StatusVar); \ + } \ + } \ + } while(0) + +#define DefaultSetInfoBufferCheck(Class, ClassList, Buffer, BufferLen, PrevMode, StatusVar) \ + do { \ + ULONG _Alignment; \ + /* get the preferred alignment for the information class or return */ \ + /* default alignment in case the class doesn't exist */ \ + GetInfoClassAlignment(Class, \ + ClassList, \ + &_Alignment, \ + SET); \ + \ + /* probe the ENTIRE buffers and return on failure */ \ + ProbeSetInfoBuffer(Buffer, \ + BufferLen, \ + _Alignment, \ + PrevMode, \ + StatusVar); \ + \ + /* validate information class index and check buffer size */ \ + CheckInfoClass(Class, \ + BufferLen, \ + ClassList, \ + StatusVar, \ + SET); \ + } while(0) + +#define DefaultQueryInfoBufferCheck(Class, ClassList, Buffer, BufferLen, RetLen, PrevMode, StatusVar) \ + do { \ + ULONG _Alignment; \ + /* get the preferred alignment for the information class or return */ \ + /* alignment in case the class doesn't exist */ \ + GetInfoClassAlignment(Class, \ + ClassList, \ + &_Alignment, \ + QUERY); \ + \ + /* probe the ENTIRE buffers and return on failure */ \ + ProbeQueryInfoBuffer(Buffer, \ + BufferLen, \ + _Alignment, \ + RetLen, \ + PrevMode, \ + StatusVar); \ + \ + /* validate information class index and check buffer size */ \ + CheckInfoClass(Class, \ + BufferLen, \ + ClassList, \ + StatusVar, \ + QUERY); \ + } while(0) + #endif /* __INCLUDE_INTERNAL_OBJMGR_H */ _____
Modified: trunk/reactos/ntoskrnl/ps/process.c --- trunk/reactos/ntoskrnl/ps/process.c 2005-01-21 21:34:49 UTC (rev 13195) +++ trunk/reactos/ntoskrnl/ps/process.c 2005-01-21 21:37:32 UTC (rev 13196) @@ -33,6 +33,44 @@
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, PROCESS_ALL_ACCESS};
+static const INFORMATION_CLASS_INFO PsProcessInfoClass[] = +{ + ICI_SQ_SAME( sizeof(PROCESS_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* ProcessBasicInformation */ + ICI_SQ_SAME( sizeof(QUOTA_LIMITS), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessQuotaLimits */ + ICI_SQ_SAME( sizeof(IO_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessIoCounters */ + ICI_SQ_SAME( sizeof(VM_COUNTERS), sizeof(ULONG), ICIF_QUERY ), /* ProcessVmCounters */ + ICI_SQ_SAME( sizeof(KERNEL_USER_TIMES), sizeof(ULONG), ICIF_QUERY ), /* ProcessTimes */ + ICI_SQ_SAME( sizeof(KPRIORITY), sizeof(ULONG), ICIF_SET ), /* ProcessBasePriority */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_SET ), /* ProcessRaisePriority */ + ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDebugPort */ + ICI_SQ_SAME( sizeof(HANDLE), sizeof(ULONG), ICIF_SET ), /* ProcessExceptionPort */ + ICI_SQ_SAME( sizeof(PROCESS_ACCESS_TOKEN), sizeof(ULONG), ICIF_SET ), /* ProcessAccessToken */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessLdtInformation */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessLdtSize */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessDefaultHardErrorMode */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessIoPortHandlers */ + ICI_SQ_SAME( sizeof(POOLED_USAGE_AND_LIMITS), sizeof(ULONG), ICIF_QUERY ), /* ProcessPooledUsageAndLimits */ + ICI_SQ_SAME( sizeof(PROCESS_WS_WATCH_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessWorkingSetWatch */ + ICI_SQ_SAME( 0 /* FIXME */, sizeof(ULONG), ICIF_SET ), /* ProcessUserModeIOPL */ + ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessEnableAlignmentFaultFixup */ + ICI_SQ_SAME( sizeof(PROCESS_PRIORITY_CLASS), sizeof(ULONG), ICIF_SET ), /* ProcessPriorityClass */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWx86Information */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessHandleCount */ + ICI_SQ_SAME( sizeof(KAFFINITY), sizeof(ULONG), ICIF_SET ), /* ProcessAffinityMask */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessPriorityBoost */ + + ICI_SQ(/*Q*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Query), /* ProcessDeviceMap */ + /*S*/ sizeof(((PPROCESS_DEVICEMAP_INFORMATION)0x0)->Set), + /*Q*/ sizeof(ULONG), + /*S*/ sizeof(ULONG), + ICIF_QUERY | ICIF_SET ), + + ICI_SQ_SAME( sizeof(PROCESS_SESSION_INFORMATION), sizeof(ULONG), ICIF_QUERY | ICIF_SET ), /* ProcessSessionInformation */ + ICI_SQ_SAME( sizeof(BOOLEAN), sizeof(ULONG), ICIF_SET ), /* ProcessForegroundInformation */ + ICI_SQ_SAME( sizeof(ULONG), sizeof(ULONG), ICIF_QUERY ), /* ProcessWow64Information */ + ICI_SQ_SAME( sizeof(UNICODE_STRING), sizeof(ULONG), ICIF_QUERY | ICIF_SIZE_VARIABLE), /* ProcessImageFileName */ +}; + #define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8 #define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
@@ -1133,39 +1171,22 @@ OUT PULONG ReturnLength OPTIONAL) { PEPROCESS Process; - NTSTATUS Status; KPROCESSOR_MODE PreviousMode; - + NTSTATUS Status = STATUS_SUCCESS; + PreviousMode = ExGetPreviousMode();
- /* check for valid buffers */ - if(PreviousMode == UserMode) + DefaultQueryInfoBufferCheck(ProcessInformationClass, + PsProcessInfoClass, + ProcessInformation, + ProcessInformationLength, + ReturnLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) { - _SEH_TRY - { - /* probe with 32bit alignment */ - ProbeForWrite(ProcessInformation, - ProcessInformationLength, - sizeof(ULONG)); - if(ReturnLength) - { - ProbeForWrite(ReturnLength, - sizeof(ULONG), - 1); - } - - Status = STATUS_SUCCESS; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if(!NT_SUCCESS(Status)) - { - return Status; - } + DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status); + return Status; }
/* @@ -1669,46 +1690,37 @@ IN ULONG ProcessInformationLength) { PEPROCESS Process; - NTSTATUS Status; KPROCESSOR_MODE PreviousMode; ACCESS_MASK Access; + NTSTATUS Status = STATUS_SUCCESS;
PreviousMode = ExGetPreviousMode();
- /* check for valid buffers */ - if(PreviousMode == UserMode) + DefaultSetInfoBufferCheck(ProcessInformationClass, + PsProcessInfoClass, + ProcessInformation, + ProcessInformationLength, + PreviousMode, + &Status); + if(!NT_SUCCESS(Status)) { - _SEH_TRY - { - /* probe with 32bit alignment */ - ProbeForRead(ProcessInformation, - ProcessInformationLength, - sizeof(ULONG)); - Status = STATUS_SUCCESS; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if(!NT_SUCCESS(Status)) - { - return Status; - } + DPRINT1("NtSetInformationProcess() failed, Status: 0x%x\n", Status); + return Status; }
- Access = PROCESS_SET_INFORMATION; - switch(ProcessInformationClass) { case ProcessSessionInformation: - Access |= PROCESS_SET_SESSIONID; + Access = PROCESS_SET_INFORMATION | PROCESS_SET_SESSIONID; break; case ProcessExceptionPort: case ProcessDebugPort: - Access |= PROCESS_SET_PORT; + Access = PROCESS_SET_INFORMATION | PROCESS_SET_PORT; break; + + default: + Access = PROCESS_SET_INFORMATION; + break; }
Status = ObReferenceObjectByHandle(ProcessHandle,