https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a7dd057ce2b622aa2d7aa…
commit a7dd057ce2b622aa2d7aaf3abb993c9e50fb2dd3
Author: George Bișoc <fraizeraust99(a)gmail.com>
AuthorDate: Sat Jun 6 17:47:38 2020 +0200
Commit: GitHub <noreply(a)github.com>
CommitDate: Sat Jun 6 17:47:38 2020 +0200
[NTDLL_APITEST] Add ProcessBasePriority and ProcessRaisePriority classes unit tests (#2740)
ProcessRaisePriority expects a buffer input information argument of KPRIORITY type definition as shown in this documentation (see the PROCESS_INFORMATION_CLASS structure members list of classes).
https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumente…
---
.../apitests/ntdll/NtSetInformationProcess.c | 143 +++++++++++++++++++++
1 file changed, 143 insertions(+)
diff --git a/modules/rostests/apitests/ntdll/NtSetInformationProcess.c b/modules/rostests/apitests/ntdll/NtSetInformationProcess.c
index b5fcc18e2db..0b805b3ca66 100644
--- a/modules/rostests/apitests/ntdll/NtSetInformationProcess.c
+++ b/modules/rostests/apitests/ntdll/NtSetInformationProcess.c
@@ -7,6 +7,147 @@
#include "precomp.h"
+static
+void
+Test_ProcBasePriorityClass(void)
+{
+ NTSTATUS Status;
+
+ /*
+ * Assign a priority of HIGH_PRIORITY (see pstypes.h).
+ * The function will fail with a status of STATUS_PRIVILEGE_NOT_HELD
+ * as the process who executed the caller doesn't have the requested
+ * privileges to perform the operation.
+ */
+ KPRIORITY BasePriority = HIGH_PRIORITY;
+
+ /* Everything is NULL */
+ Status = NtSetInformationProcess(NULL,
+ ProcessBasePriority,
+ NULL,
+ 0);
+ ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
+
+ /* Set the base priority to an invalid process handle */
+ Status = NtSetInformationProcess(NULL,
+ ProcessBasePriority,
+ &BasePriority,
+ sizeof(KPRIORITY));
+ ok_hex(Status, STATUS_INVALID_HANDLE);
+
+ /* Don't input anything to the caller but the length information is valid */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessBasePriority,
+ NULL,
+ sizeof(KPRIORITY));
+ ok_hex(Status, STATUS_ACCESS_VIOLATION);
+
+ /* Give the base priority input to the caller but length is invalid */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessBasePriority,
+ &BasePriority,
+ 0);
+ ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
+
+ /* The input buffer is misaligned and length information invalid */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessBasePriority,
+ (PVOID)1,
+ 0);
+ ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
+
+ /* The input buffer is misaligned */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessBasePriority,
+ (PVOID)1,
+ sizeof(KPRIORITY));
+ ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
+
+ /* The input buffer is misaligned (try with an alignment of 2) */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessBasePriority,
+ (PVOID)2,
+ sizeof(KPRIORITY));
+ ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
+
+ /* Set the base priority but we have lack privileges to do so */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessBasePriority,
+ &BasePriority,
+ sizeof(KPRIORITY));
+ ok_hex(Status, STATUS_PRIVILEGE_NOT_HELD);
+
+ /*
+ * Assign a random priority value this time and
+ * set the base priority to the current process.
+ */
+ BasePriority = 8;
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessBasePriority,
+ &BasePriority,
+ sizeof(KPRIORITY));
+ ok_hex(Status, STATUS_SUCCESS);
+}
+
+static
+void
+Test_ProcRaisePriorityClass(void)
+{
+ NTSTATUS Status;
+
+ /* Raise the priority as much as possible */
+ ULONG RaisePriority = MAXIMUM_PRIORITY;
+
+ /* Everything is NULL */
+ Status = NtSetInformationProcess(NULL,
+ ProcessRaisePriority,
+ NULL,
+ 0);
+ ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
+
+ /* A invalid handle to process is given */
+ Status = NtSetInformationProcess(NULL,
+ ProcessRaisePriority,
+ &RaisePriority,
+ sizeof(ULONG));
+ ok_hex(Status, STATUS_INVALID_HANDLE);
+
+ /* The input buffer is misaligned and length information invalid */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessRaisePriority,
+ (PVOID)1,
+ 0);
+ ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
+
+ /* A NULL buffer has been accessed */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessRaisePriority,
+ NULL,
+ sizeof(ULONG));
+ ok_hex(Status, STATUS_ACCESS_VIOLATION);
+
+ /* The input buffer is misaligned */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessRaisePriority,
+ (PVOID)1,
+ sizeof(ULONG));
+ ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
+
+ /* The input buffer is misaligned -- try with an alignment size of 2 */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessRaisePriority,
+ (PVOID)2,
+ sizeof(ULONG));
+ ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
+
+ /* Raise the priority of the given current process */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ ProcessRaisePriority,
+ &RaisePriority,
+ sizeof(ULONG));
+ ok_hex(Status, STATUS_SUCCESS);
+}
+
static
void
Test_ProcForegroundBackgroundClass(void)
@@ -77,4 +218,6 @@ Test_ProcForegroundBackgroundClass(void)
START_TEST(NtSetInformationProcess)
{
Test_ProcForegroundBackgroundClass();
+ Test_ProcBasePriorityClass();
+ Test_ProcRaisePriorityClass();
}
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4f49a9c792b8334a5ad8d…
commit 4f49a9c792b8334a5ad8d6daaecd26dde6870f3c
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Fri May 22 22:34:56 2020 +0200
Commit: Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Sat Jun 6 08:44:30 2020 +0200
[NTOS:KE] Save ExceptionList in the assembly version of KiEnterTrap. CORE-15723
If SEH is used in a C trap handler, the exception frame will be
registered before the call to KiEnterTrap, which means we save
the wrong trap handler. We'll therefore also restore this wrong
frame for the excepting code, resulting in a stale SEH chain.
We avoid this problem by saving the handler in the assembly
trap entry code instead of from C. While SEH in a C trap handler
should now theoretically be safe, we still forbid it through
asserts in the C KiEnterTrap variants to make any potential
future problems more obvious. Should this functionality be
needed at some point and deemed safe, these asserts can then be
removed.
---
ntoskrnl/include/internal/i386/asmmacro.S | 4 ++++
ntoskrnl/include/internal/i386/trap_x.h | 24 ++++++++++++++++++------
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/ntoskrnl/include/internal/i386/asmmacro.S b/ntoskrnl/include/internal/i386/asmmacro.S
index f7af217cc9f..543ce3f1bc4 100644
--- a/ntoskrnl/include/internal/i386/asmmacro.S
+++ b/ntoskrnl/include/internal/i386/asmmacro.S
@@ -207,6 +207,10 @@ set_sane_segs:
mov fs, ax
endif
+ /* Save ExceptionList, since the C handler might use SEH */
+ mov eax, fs:[KPCR_EXCEPTION_LIST]
+ mov [esp + KTRAP_FRAME_EXCEPTION_LIST], eax
+
#if DBG
/* Keep the frame chain intact */
mov eax, [esp + KTRAP_FRAME_EIP]
diff --git a/ntoskrnl/include/internal/i386/trap_x.h b/ntoskrnl/include/internal/i386/trap_x.h
index 06443c9dc90..cd79c2a40c4 100644
--- a/ntoskrnl/include/internal/i386/trap_x.h
+++ b/ntoskrnl/include/internal/i386/trap_x.h
@@ -349,8 +349,12 @@ FORCEINLINE
VOID
KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
{
- /* Save exception list */
- TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ PVOID ExceptionList;
+
+ /* Check exception list */
+ ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ ASSERTMSG("V86 trap handler must not register an SEH frame\n",
+ ExceptionList == TrapFrame->ExceptionList);
/* Save DR7 and check for debugging */
TrapFrame->Dr7 = __readdr(7);
@@ -368,8 +372,12 @@ FORCEINLINE
VOID
KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
{
- /* Save exception list and terminate it */
- TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ PVOID ExceptionList;
+
+ /* Check exception list and terminate it */
+ ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ ASSERTMSG("Interrupt handler must not register an SEH frame\n",
+ ExceptionList == TrapFrame->ExceptionList);
KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
/* Default to debugging disabled */
@@ -398,8 +406,12 @@ FORCEINLINE
VOID
KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
{
- /* Save exception list */
- TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ PVOID ExceptionList;
+
+ /* Check exception list */
+ ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+ ASSERTMSG("Trap handler must not register an SEH frame\n",
+ ExceptionList == TrapFrame->ExceptionList);
/* Default to debugging disabled */
TrapFrame->Dr7 = 0;
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d40ff3ca985daf8ea9927…
commit d40ff3ca985daf8ea9927d9902282f6aa813824b
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Fri May 22 11:18:39 2020 +0200
Commit: Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Sat Jun 6 08:42:22 2020 +0200
[NTOS:KE] Split KiCheckForSListFault into its own function. CORE-15723
This avoids SEH in a trap handler.
See the following commit for more details.
---
ntoskrnl/ke/i386/traphdlr.c | 114 ++++++++++++++++++++++++--------------------
1 file changed, 62 insertions(+), 52 deletions(-)
diff --git a/ntoskrnl/ke/i386/traphdlr.c b/ntoskrnl/ke/i386/traphdlr.c
index 8ef4031b601..0614efc398b 100644
--- a/ntoskrnl/ke/i386/traphdlr.c
+++ b/ntoskrnl/ke/i386/traphdlr.c
@@ -1216,56 +1216,11 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
KiTrapReturn(TrapFrame);
}
-DECLSPEC_NORETURN
-VOID
+BOOLEAN
FASTCALL
-KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
+KiCheckForSListFault(PKTRAP_FRAME TrapFrame)
{
- PKTHREAD Thread;
- BOOLEAN StoreInstruction;
- ULONG_PTR Cr2;
- NTSTATUS Status;
-
- /* Save trap frame */
- KiEnterTrap(TrapFrame);
-
- /* Check if this is the base frame */
- Thread = KeGetCurrentThread();
- if (KeGetTrapFrame(Thread) != TrapFrame)
- {
- /* It isn't, check if this is a second nested frame */
- if (((ULONG_PTR)KeGetTrapFrame(Thread) - (ULONG_PTR)TrapFrame) <=
- FIELD_OFFSET(KTRAP_FRAME, EFlags))
- {
- /* The stack is somewhere in between frames, we need to fix it */
- UNIMPLEMENTED_FATAL();
- }
- }
-
- /* Save CR2 */
- Cr2 = __readcr2();
-
- /* Enable interrupts */
- _enable();
-
- /* Interpret the error code */
- StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
-
- /* Check if we came in with interrupts disabled */
- if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
- {
- /* This is completely illegal, bugcheck the system */
- KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
- Cr2,
- (ULONG_PTR)-1,
- TrapFrame->ErrCode,
- TrapFrame->Eip,
- TrapFrame);
- }
-
- /* Check for S-List fault
-
- Explanation: An S-List fault can occur due to a race condition between 2
+ /* Explanation: An S-List fault can occur due to a race condition between 2
threads simultaneously trying to pop an element from the S-List. After
thread 1 has read the pointer to the top element on the S-List it is
preempted and thread 2 calls InterlockedPopEntrySlist on the same S-List,
@@ -1329,7 +1284,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* The S-List pointer is not valid! */
- goto NotSListFault;
+ return FALSE;
}
_SEH2_END;
ResumeAddress = KeUserPopEntrySListResume;
@@ -1353,11 +1308,66 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
/* Restart the operation */
TrapFrame->Eip = (ULONG_PTR)ResumeAddress;
- /* Continue execution */
- KiEoiHelper(TrapFrame);
+ return TRUE;
}
}
-NotSListFault:
+
+ return FALSE;
+}
+
+DECLSPEC_NORETURN
+VOID
+FASTCALL
+KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
+{
+ PKTHREAD Thread;
+ BOOLEAN StoreInstruction;
+ ULONG_PTR Cr2;
+ NTSTATUS Status;
+
+ /* Save trap frame */
+ KiEnterTrap(TrapFrame);
+
+ /* Check if this is the base frame */
+ Thread = KeGetCurrentThread();
+ if (KeGetTrapFrame(Thread) != TrapFrame)
+ {
+ /* It isn't, check if this is a second nested frame */
+ if (((ULONG_PTR)KeGetTrapFrame(Thread) - (ULONG_PTR)TrapFrame) <=
+ FIELD_OFFSET(KTRAP_FRAME, EFlags))
+ {
+ /* The stack is somewhere in between frames, we need to fix it */
+ UNIMPLEMENTED_FATAL();
+ }
+ }
+
+ /* Save CR2 */
+ Cr2 = __readcr2();
+
+ /* Enable interrupts */
+ _enable();
+
+ /* Interpret the error code */
+ StoreInstruction = (TrapFrame->ErrCode & 2) != 0;
+
+ /* Check if we came in with interrupts disabled */
+ if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
+ {
+ /* This is completely illegal, bugcheck the system */
+ KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL,
+ Cr2,
+ (ULONG_PTR)-1,
+ TrapFrame->ErrCode,
+ TrapFrame->Eip,
+ TrapFrame);
+ }
+
+ /* Check for S-List fault */
+ if (KiCheckForSListFault(TrapFrame))
+ {
+ /* Continue execution */
+ KiEoiHelper(TrapFrame);
+ }
/* Call the access fault handler */
Status = MmAccessFault(TrapFrame->ErrCode,