securely access buffers in NtSetContextThread() and NtGetContextThread()

svn path=/trunk/; revision=13360
This commit is contained in:
Thomas Bluemel 2005-01-29 12:24:15 +00:00
parent 1291972098
commit a725df1b30

View file

@ -186,28 +186,43 @@ NtGetContextThread(IN HANDLE ThreadHandle,
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))
{
return Status;
}
if (Thread == PsGetCurrentThread())
if(NT_SUCCESS(Status))
{
if(Thread == PsGetCurrentThread())
{
/*
* I don't know if trying to get your own context makes much
@ -215,15 +230,13 @@ NtGetContextThread(IN HANDLE ThreadHandle,
*/
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 @@ NtGetContextThread(IN HANDLE ThreadHandle,
(PVOID)&Context);
if (!KeInsertQueueApc(&Apc,
(PVOID)&Event,
(PVOID)&AStatus,
(PVOID)&Status,
IO_NO_INCREMENT))
{
Status = STATUS_THREAD_IS_TERMINATING;
@ -243,21 +256,27 @@ NtGetContextThread(IN HANDLE ThreadHandle,
{
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,29 +310,45 @@ NtSetContextThread(IN HANDLE ThreadHandle,
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))
{
return Status;
}
if (Thread == PsGetCurrentThread())
if(NT_SUCCESS(Status))
{
if (Thread == PsGetCurrentThread())
{
/*
* I don't know if trying to set your own context makes much
@ -321,14 +356,12 @@ NtSetContextThread(IN HANDLE ThreadHandle,
*/
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 @@ NtSetContextThread(IN HANDLE ThreadHandle,
(PVOID)&Context);
if (!KeInsertQueueApc(&Apc,
(PVOID)&Event,
(PVOID)&AStatus,
(PVOID)&Status,
IO_NO_INCREMENT))
{
Status = STATUS_THREAD_IS_TERMINATING;
@ -349,17 +382,14 @@ NtSetContextThread(IN HANDLE ThreadHandle,
{
Status = KeWaitForSingleObject(&Event,
0,
UserMode,
KernelMode,
FALSE,
NULL);
if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus))
{
Status = AStatus;
}
NULL);
}
}
ObDereferenceObject(Thread);
ObDereferenceObject(Thread);
}
return Status;
}