securely access buffers in NtSetContextThread() and NtGetContextThread() Modified: trunk/reactos/ntoskrnl/ps/debug.c _____
Modified: trunk/reactos/ntoskrnl/ps/debug.c --- trunk/reactos/ntoskrnl/ps/debug.c 2005-01-29 03:15:05 UTC (rev 13359) +++ trunk/reactos/ntoskrnl/ps/debug.c 2005-01-29 12:24:15 UTC (rev 13360) @@ -186,44 +186,57 @@
OUT PCONTEXT ThreadContext) { PETHREAD Thread; - NTSTATUS Status; CONTEXT Context; KAPC Apc; KEVENT Event; - NTSTATUS AStatus; + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode();
- Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT)); - if (! NT_SUCCESS(Status)) + if(PreviousMode != KernelMode) + { + _SEH_TRY { + ProbeForWrite(ThreadContext, + sizeof(CONTEXT), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { return Status; } + } + Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_GET_CONTEXT, PsThreadType, - UserMode, + PreviousMode, (PVOID*)&Thread, NULL); - if (! NT_SUCCESS(Status)) + if(NT_SUCCESS(Status)) + { + if(Thread == PsGetCurrentThread()) { - return Status; - } - if (Thread == PsGetCurrentThread()) - { /* * I don't know if trying to get your own context makes much * sense but we can handle it more efficently. */ KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context); - Status = STATUS_SUCCESS; } - else + else { KeInitializeEvent(&Event, NotificationEvent, - FALSE); - AStatus = STATUS_SUCCESS; - + FALSE); + KeInitializeApc(&Apc, &Thread->Tcb, OriginalApcEnvironment, @@ -234,7 +247,7 @@ (PVOID)&Context); if (!KeInsertQueueApc(&Apc, (PVOID)&Event, - (PVOID)&AStatus, + (PVOID)&Status, IO_NO_INCREMENT)) { Status = STATUS_THREAD_IS_TERMINATING; @@ -243,21 +256,27 @@ { Status = KeWaitForSingleObject(&Event, 0, - UserMode, + KernelMode, FALSE, NULL); - if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus)) - { - Status = AStatus; - } } } - if (NT_SUCCESS(Status)) + ObDereferenceObject(Thread); + + if(NT_SUCCESS(Status)) { - Status = MmCopyToCaller(ThreadContext, &Context, sizeof(Context)); + _SEH_TRY + { + *ThreadContext = Context; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; } - - ObDereferenceObject(Thread); + } + return Status; }
@@ -291,44 +310,58 @@ IN PCONTEXT ThreadContext) { PETHREAD Thread; - NTSTATUS Status; KAPC Apc; KEVENT Event; - NTSTATUS AStatus; CONTEXT Context; - - Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT)); - if (! NT_SUCCESS(Status)) + KPROCESSOR_MODE PreviousMode; + NTSTATUS Status = STATUS_SUCCESS; + + PreviousMode = ExGetPreviousMode(); + + if(PreviousMode != KernelMode) + { + _SEH_TRY { + ProbeForRead(ThreadContext, + sizeof(CONTEXT), + sizeof(ULONG)); + Context = *ThreadContext; + ThreadContext = &Context; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { return Status; } + } + Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_SET_CONTEXT, PsThreadType, - UserMode, + PreviousMode, (PVOID*)&Thread, NULL); - if (!NT_SUCCESS(Status)) + if(NT_SUCCESS(Status)) + { + if (Thread == PsGetCurrentThread()) { - return Status; - } - - if (Thread == PsGetCurrentThread()) - { /* * I don't know if trying to set your own context makes much * sense but we can handle it more efficently. */ KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame); - Status = STATUS_SUCCESS; } - else + else { KeInitializeEvent(&Event, NotificationEvent, FALSE); - AStatus = STATUS_SUCCESS; KeInitializeApc(&Apc, &Thread->Tcb, @@ -340,7 +373,7 @@ (PVOID)&Context); if (!KeInsertQueueApc(&Apc, (PVOID)&Event, - (PVOID)&AStatus, + (PVOID)&Status, IO_NO_INCREMENT)) { Status = STATUS_THREAD_IS_TERMINATING; @@ -349,17 +382,14 @@ { Status = KeWaitForSingleObject(&Event, 0, - UserMode, + KernelMode, FALSE, - NULL); - if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus)) - { - Status = AStatus; - } + NULL); } } - - ObDereferenceObject(Thread); + ObDereferenceObject(Thread); + } + return Status; }