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) OUT PCONTEXT ThreadContext)
{ {
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status;
CONTEXT Context; CONTEXT Context;
KAPC Apc; KAPC Apc;
KEVENT Event; KEVENT Event;
NTSTATUS AStatus; KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT)); PreviousMode = ExGetPreviousMode();
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; return Status;
} }
}
Status = ObReferenceObjectByHandle(ThreadHandle, Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_GET_CONTEXT, THREAD_GET_CONTEXT,
PsThreadType, PsThreadType,
UserMode, PreviousMode,
(PVOID*)&Thread, (PVOID*)&Thread,
NULL); NULL);
if (! NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
{ {
return Status; if(Thread == PsGetCurrentThread())
}
if (Thread == PsGetCurrentThread())
{ {
/* /*
* I don't know if trying to get your own context makes much * I don't know if trying to get your own context makes much
@ -215,14 +230,12 @@ NtGetContextThread(IN HANDLE ThreadHandle,
*/ */
KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context); KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context);
Status = STATUS_SUCCESS;
} }
else else
{ {
KeInitializeEvent(&Event, KeInitializeEvent(&Event,
NotificationEvent, NotificationEvent,
FALSE); FALSE);
AStatus = STATUS_SUCCESS;
KeInitializeApc(&Apc, KeInitializeApc(&Apc,
&Thread->Tcb, &Thread->Tcb,
@ -234,7 +247,7 @@ NtGetContextThread(IN HANDLE ThreadHandle,
(PVOID)&Context); (PVOID)&Context);
if (!KeInsertQueueApc(&Apc, if (!KeInsertQueueApc(&Apc,
(PVOID)&Event, (PVOID)&Event,
(PVOID)&AStatus, (PVOID)&Status,
IO_NO_INCREMENT)) IO_NO_INCREMENT))
{ {
Status = STATUS_THREAD_IS_TERMINATING; Status = STATUS_THREAD_IS_TERMINATING;
@ -243,21 +256,27 @@ NtGetContextThread(IN HANDLE ThreadHandle,
{ {
Status = KeWaitForSingleObject(&Event, Status = KeWaitForSingleObject(&Event,
0, 0,
UserMode, KernelMode,
FALSE, FALSE,
NULL); NULL);
if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus)) }
}
ObDereferenceObject(Thread);
if(NT_SUCCESS(Status))
{ {
Status = AStatus; _SEH_TRY
}
}
}
if (NT_SUCCESS(Status))
{ {
Status = MmCopyToCaller(ThreadContext, &Context, sizeof(Context)); *ThreadContext = Context;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
} }
ObDereferenceObject(Thread);
return Status; return Status;
} }
@ -291,28 +310,44 @@ NtSetContextThread(IN HANDLE ThreadHandle,
IN PCONTEXT ThreadContext) IN PCONTEXT ThreadContext)
{ {
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status;
KAPC Apc; KAPC Apc;
KEVENT Event; KEVENT Event;
NTSTATUS AStatus;
CONTEXT Context; CONTEXT Context;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
Status = MmCopyFromCaller(&Context, ThreadContext, sizeof(CONTEXT)); PreviousMode = ExGetPreviousMode();
if (! NT_SUCCESS(Status))
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; return Status;
} }
}
Status = ObReferenceObjectByHandle(ThreadHandle, Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SET_CONTEXT, THREAD_SET_CONTEXT,
PsThreadType, PsThreadType,
UserMode, PreviousMode,
(PVOID*)&Thread, (PVOID*)&Thread,
NULL); NULL);
if (!NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
{ {
return Status;
}
if (Thread == PsGetCurrentThread()) if (Thread == PsGetCurrentThread())
{ {
/* /*
@ -321,14 +356,12 @@ NtSetContextThread(IN HANDLE ThreadHandle,
*/ */
KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame); KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame);
Status = STATUS_SUCCESS;
} }
else else
{ {
KeInitializeEvent(&Event, KeInitializeEvent(&Event,
NotificationEvent, NotificationEvent,
FALSE); FALSE);
AStatus = STATUS_SUCCESS;
KeInitializeApc(&Apc, KeInitializeApc(&Apc,
&Thread->Tcb, &Thread->Tcb,
@ -340,7 +373,7 @@ NtSetContextThread(IN HANDLE ThreadHandle,
(PVOID)&Context); (PVOID)&Context);
if (!KeInsertQueueApc(&Apc, if (!KeInsertQueueApc(&Apc,
(PVOID)&Event, (PVOID)&Event,
(PVOID)&AStatus, (PVOID)&Status,
IO_NO_INCREMENT)) IO_NO_INCREMENT))
{ {
Status = STATUS_THREAD_IS_TERMINATING; Status = STATUS_THREAD_IS_TERMINATING;
@ -349,17 +382,14 @@ NtSetContextThread(IN HANDLE ThreadHandle,
{ {
Status = KeWaitForSingleObject(&Event, Status = KeWaitForSingleObject(&Event,
0, 0,
UserMode, KernelMode,
FALSE, FALSE,
NULL); NULL);
if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus))
{
Status = AStatus;
} }
} }
ObDereferenceObject(Thread);
} }
ObDereferenceObject(Thread);
return Status; return Status;
} }