1. fixed the timer functions to securely access buffers

2. minor fixes due to copy+paste

svn path=/trunk/; revision=13236
This commit is contained in:
Thomas Bluemel 2005-01-23 23:51:40 +00:00
parent 7c02041548
commit 064504a61d
2 changed files with 258 additions and 98 deletions

View file

@ -240,12 +240,12 @@ NtQuerySemaphore(IN HANDLE SemaphoreHandle,
&Status); &Status);
if(!NT_SUCCESS(Status)) if(!NT_SUCCESS(Status))
{ {
DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status); DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
return Status; return Status;
} }
Status = ObReferenceObjectByHandle(SemaphoreHandle, Status = ObReferenceObjectByHandle(SemaphoreHandle,
EVENT_QUERY_STATE, SEMAPHORE_QUERY_STATE,
ExSemaphoreObjectType, ExSemaphoreObjectType,
PreviousMode, PreviousMode,
(PVOID*)&Semaphore, (PVOID*)&Semaphore,

View file

@ -36,6 +36,10 @@ static GENERIC_MAPPING ExpTimerMapping = {
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
TIMER_ALL_ACCESS}; TIMER_ALL_ACCESS};
static const INFORMATION_CLASS_INFO ExTimerInfoClass[] =
{
ICI_SQ_SAME( sizeof(TIMER_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* TimerBasicInformation */
};
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -146,36 +150,67 @@ NtCancelTimer(IN HANDLE TimerHandle,
OUT PBOOLEAN CurrentState OPTIONAL) OUT PBOOLEAN CurrentState OPTIONAL)
{ {
PNTTIMER Timer; PNTTIMER Timer;
NTSTATUS Status; KPROCESSOR_MODE PreviousMode;
BOOLEAN State; NTSTATUS Status = STATUS_SUCCESS;
KIRQL OldIrql;
PreviousMode = ExGetPreviousMode();
DPRINT("NtCancelTimer(0x%x, 0x%x)\n", TimerHandle, CurrentState);
if(CurrentState != NULL && PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWrite(CurrentState,
sizeof(BOOLEAN),
sizeof(BOOLEAN));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
DPRINT("NtCancelTimer()\n");
Status = ObReferenceObjectByHandle(TimerHandle, Status = ObReferenceObjectByHandle(TimerHandle,
TIMER_ALL_ACCESS, TIMER_ALL_ACCESS,
ExTimerType, ExTimerType,
UserMode, PreviousMode,
(PVOID*)&Timer, (PVOID*)&Timer,
NULL); NULL);
if (!NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
return Status; {
BOOLEAN State;
KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
OldIrql = KeRaiseIrqlToDpcLevel(); State = KeCancelTimer(&Timer->Timer);
KeRemoveQueueDpc(&Timer->Dpc);
KeRemoveQueueApc(&Timer->Apc);
Timer->Running = FALSE;
State = KeCancelTimer(&Timer->Timer); KeLowerIrql(OldIrql);
KeRemoveQueueDpc(&Timer->Dpc); ObDereferenceObject(Timer);
KeRemoveQueueApc(&Timer->Apc);
Timer->Running = FALSE;
KeLowerIrql(OldIrql); if(CurrentState != NULL)
ObDereferenceObject(Timer);
if (CurrentState != NULL)
{ {
*CurrentState = State; _SEH_TRY
{
*CurrentState = State;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
} }
}
return STATUS_SUCCESS; return Status;
} }
@ -186,38 +221,75 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
IN TIMER_TYPE TimerType) IN TIMER_TYPE TimerType)
{ {
PNTTIMER Timer; PNTTIMER Timer;
NTSTATUS Status; HANDLE hTimer;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtCreateTimer()\n"); DPRINT("NtCreateTimer()\n");
Status = ObCreateObject(ExGetPreviousMode(),
PreviousMode = ExGetPreviousMode();
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWrite(TimerHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObCreateObject(PreviousMode,
ExTimerType, ExTimerType,
ObjectAttributes, ObjectAttributes,
ExGetPreviousMode(), PreviousMode,
NULL, NULL,
sizeof(NTTIMER), sizeof(NTTIMER),
0, 0,
0, 0,
(PVOID*)&Timer); (PVOID*)&Timer);
if (!NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
return Status; {
KeInitializeTimerEx(&Timer->Timer,
TimerType);
KeInitializeTimerEx(&Timer->Timer, KeInitializeDpc(&Timer->Dpc,
TimerType); &ExpTimerDpcRoutine,
Timer);
KeInitializeDpc(&Timer->Dpc, Timer->Running = FALSE;
&ExpTimerDpcRoutine,
Timer);
Timer->Running = FALSE; Status = ObInsertObject ((PVOID)Timer,
NULL,
Status = ObInsertObject ((PVOID)Timer, DesiredAccess,
NULL, 0,
DesiredAccess, NULL,
0, &hTimer);
NULL, ObDereferenceObject(Timer);
TimerHandle);
if(NT_SUCCESS(Status))
ObDereferenceObject(Timer); {
_SEH_TRY
{
*TimerHandle = hTimer;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return Status; return Status;
} }
@ -228,15 +300,54 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
IN ACCESS_MASK DesiredAccess, IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes) IN POBJECT_ATTRIBUTES ObjectAttributes)
{ {
NTSTATUS Status; HANDLE hTimer;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtOpenTimer()\n");
PreviousMode = ExGetPreviousMode();
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForWrite(TimerHandle,
sizeof(HANDLE),
sizeof(ULONG));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObOpenObjectByName(ObjectAttributes, Status = ObOpenObjectByName(ObjectAttributes,
ExTimerType, ExTimerType,
NULL, NULL,
UserMode, PreviousMode,
DesiredAccess, DesiredAccess,
NULL, NULL,
TimerHandle); &hTimer);
if(NT_SUCCESS(Status))
{
_SEH_TRY
{
*TimerHandle = hTimer;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return Status; return Status;
} }
@ -248,58 +359,67 @@ NtQueryTimer(IN HANDLE TimerHandle,
IN ULONG TimerInformationLength, IN ULONG TimerInformationLength,
OUT PULONG ReturnLength OPTIONAL) OUT PULONG ReturnLength OPTIONAL)
{ {
PNTTIMER Timer; PNTTIMER Timer;
TIMER_BASIC_INFORMATION SafeTimerInformation; KPROCESSOR_MODE PreviousMode;
ULONG ResultLength; NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS Status;
Status = ObReferenceObjectByHandle(TimerHandle, PreviousMode = ExGetPreviousMode();
TIMER_QUERY_STATE,
ExTimerType,
(KPROCESSOR_MODE)KeGetPreviousMode(),
(PVOID*)&Timer,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
if (TimerInformationClass != TimerBasicInformation) DefaultQueryInfoBufferCheck(TimerInformationClass,
{ ExTimerInfoClass,
ObDereferenceObject(Timer); TimerInformation,
return(STATUS_INVALID_INFO_CLASS); TimerInformationLength,
} ReturnLength,
if (TimerInformationLength < sizeof(TIMER_BASIC_INFORMATION)) PreviousMode,
{ &Status);
ObDereferenceObject(Timer); if(!NT_SUCCESS(Status))
return(STATUS_INFO_LENGTH_MISMATCH); {
} DPRINT1("NtQueryTimer() failed, Status: 0x%x\n", Status);
return Status;
}
memcpy(&SafeTimerInformation.TimeRemaining, &Timer->Timer.DueTime, Status = ObReferenceObjectByHandle(TimerHandle,
sizeof(LARGE_INTEGER)); TIMER_QUERY_STATE,
SafeTimerInformation.SignalState = (BOOLEAN)Timer->Timer.Header.SignalState; ExTimerType,
ResultLength = sizeof(TIMER_BASIC_INFORMATION); PreviousMode,
(PVOID*)&Timer,
NULL);
if(NT_SUCCESS(Status))
{
switch(TimerInformationClass)
{
case TimerBasicInformation:
{
PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation;
Status = MmCopyToCaller(TimerInformation, &SafeTimerInformation, _SEH_TRY
sizeof(TIMER_BASIC_INFORMATION)); {
if (!NT_SUCCESS(Status)) /* FIXME - interrupt correction */
{ BasicInfo->TimeRemaining.QuadPart = Timer->Timer.DueTime.QuadPart;
ObDereferenceObject(Timer); BasicInfo->SignalState = (BOOLEAN)Timer->Timer.Header.SignalState;
return(Status);
}
if (ReturnLength != NULL) if(ReturnLength != NULL)
{ {
Status = MmCopyToCaller(ReturnLength, &ResultLength, *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
sizeof(ULONG)); }
if (!NT_SUCCESS(Status)) }
{ _SEH_HANDLE
ObDereferenceObject(Timer); {
return(Status); Status = _SEH_GetExceptionCode();
} }
} _SEH_END;
ObDereferenceObject(Timer); break;
return(STATUS_SUCCESS); }
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
ObDereferenceObject(Timer);
}
return Status;
} }
@ -313,16 +433,48 @@ NtSetTimer(IN HANDLE TimerHandle,
OUT PBOOLEAN PreviousState OPTIONAL) OUT PBOOLEAN PreviousState OPTIONAL)
{ {
PNTTIMER Timer; PNTTIMER Timer;
NTSTATUS Status;
BOOLEAN Result; BOOLEAN Result;
BOOLEAN State; BOOLEAN State;
LARGE_INTEGER TimerDueTime;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtSetTimer()\n"); DPRINT("NtSetTimer()\n");
PreviousMode = ExGetPreviousMode();
if(PreviousMode != KernelMode)
{
_SEH_TRY
{
ProbeForRead(DueTime,
sizeof(LARGE_INTEGER),
sizeof(ULONG));
TimerDueTime = *DueTime;
if(PreviousState != NULL)
{
ProbeForWrite(PreviousState,
sizeof(BOOLEAN),
sizeof(BOOLEAN));
}
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
Status = ObReferenceObjectByHandle(TimerHandle, Status = ObReferenceObjectByHandle(TimerHandle,
TIMER_ALL_ACCESS, TIMER_ALL_ACCESS,
ExTimerType, ExTimerType,
(KPROCESSOR_MODE)KeGetPreviousMode(), PreviousMode,
(PVOID*)&Timer, (PVOID*)&Timer,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -351,15 +503,15 @@ NtSetTimer(IN HANDLE TimerHandle,
&ExpTimerApcKernelRoutine, &ExpTimerApcKernelRoutine,
(PKRUNDOWN_ROUTINE)NULL, (PKRUNDOWN_ROUTINE)NULL,
(PKNORMAL_ROUTINE)TimerApcRoutine, (PKNORMAL_ROUTINE)TimerApcRoutine,
(KPROCESSOR_MODE)KeGetPreviousMode(), PreviousMode,
TimerContext); TimerContext);
} }
Result = KeSetTimerEx(&Timer->Timer, Result = KeSetTimerEx(&Timer->Timer,
*DueTime, TimerDueTime,
Period, Period,
TimerApcRoutine ? &Timer->Dpc : 0 ); TimerApcRoutine ? &Timer->Dpc : 0 );
if (Result == TRUE) if (Result)
{ {
ObDereferenceObject(Timer); ObDereferenceObject(Timer);
DPRINT1( "KeSetTimer says the timer was already running, this shouldn't be\n" ); DPRINT1( "KeSetTimer says the timer was already running, this shouldn't be\n" );
@ -371,11 +523,19 @@ NtSetTimer(IN HANDLE TimerHandle,
ObDereferenceObject(Timer); ObDereferenceObject(Timer);
if (PreviousState != NULL) if (PreviousState != NULL)
{
_SEH_TRY
{ {
*PreviousState = State; *PreviousState = State;
} }
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
return STATUS_SUCCESS; return Status;
} }
/* EOF */ /* EOF */