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;
}