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,21 +150,43 @@ 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;
OldIrql = KeRaiseIrqlToDpcLevel(); KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
State = KeCancelTimer(&Timer->Timer); State = KeCancelTimer(&Timer->Timer);
KeRemoveQueueDpc(&Timer->Dpc); KeRemoveQueueDpc(&Timer->Dpc);
@ -171,11 +197,20 @@ NtCancelTimer(IN HANDLE TimerHandle,
ObDereferenceObject(Timer); ObDereferenceObject(Timer);
if(CurrentState != NULL) if(CurrentState != NULL)
{
_SEH_TRY
{ {
*CurrentState = State; *CurrentState = State;
} }
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
}
return STATUS_SUCCESS; return Status;
} }
@ -186,21 +221,45 @@ 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, KeInitializeTimerEx(&Timer->Timer,
TimerType); TimerType);
@ -215,10 +274,23 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
DesiredAccess, DesiredAccess,
0, 0,
NULL, NULL,
TimerHandle); &hTimer);
ObDereferenceObject(Timer); ObDereferenceObject(Timer);
if(NT_SUCCESS(Status))
{
_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;
} }
@ -249,57 +360,66 @@ NtQueryTimer(IN HANDLE TimerHandle,
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;
PreviousMode = ExGetPreviousMode();
DefaultQueryInfoBufferCheck(TimerInformationClass,
ExTimerInfoClass,
TimerInformation,
TimerInformationLength,
ReturnLength,
PreviousMode,
&Status);
if(!NT_SUCCESS(Status))
{
DPRINT1("NtQueryTimer() failed, Status: 0x%x\n", Status);
return Status;
}
Status = ObReferenceObjectByHandle(TimerHandle, Status = ObReferenceObjectByHandle(TimerHandle,
TIMER_QUERY_STATE, TIMER_QUERY_STATE,
ExTimerType, ExTimerType,
(KPROCESSOR_MODE)KeGetPreviousMode(), PreviousMode,
(PVOID*)&Timer, (PVOID*)&Timer,
NULL); NULL);
if (!NT_SUCCESS(Status)) if(NT_SUCCESS(Status))
{ {
return(Status); switch(TimerInformationClass)
} {
case TimerBasicInformation:
{
PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation;
if (TimerInformationClass != TimerBasicInformation) _SEH_TRY
{ {
ObDereferenceObject(Timer); /* FIXME - interrupt correction */
return(STATUS_INVALID_INFO_CLASS); BasicInfo->TimeRemaining.QuadPart = Timer->Timer.DueTime.QuadPart;
} BasicInfo->SignalState = (BOOLEAN)Timer->Timer.Header.SignalState;
if (TimerInformationLength < sizeof(TIMER_BASIC_INFORMATION))
{
ObDereferenceObject(Timer);
return(STATUS_INFO_LENGTH_MISMATCH);
}
memcpy(&SafeTimerInformation.TimeRemaining, &Timer->Timer.DueTime,
sizeof(LARGE_INTEGER));
SafeTimerInformation.SignalState = (BOOLEAN)Timer->Timer.Header.SignalState;
ResultLength = sizeof(TIMER_BASIC_INFORMATION);
Status = MmCopyToCaller(TimerInformation, &SafeTimerInformation,
sizeof(TIMER_BASIC_INFORMATION));
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Timer);
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); Status = _SEH_GetExceptionCode();
return(Status);
} }
_SEH_END;
break;
} }
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
ObDereferenceObject(Timer); ObDereferenceObject(Timer);
return(STATUS_SUCCESS); }
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 */