mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
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:
parent
7c02041548
commit
064504a61d
2 changed files with 258 additions and 98 deletions
|
@ -240,12 +240,12 @@ NtQuerySemaphore(IN HANDLE SemaphoreHandle,
|
|||
&Status);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtQueryEvent() failed, Status: 0x%x\n", Status);
|
||||
DPRINT1("NtQuerySemaphore() failed, Status: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ObReferenceObjectByHandle(SemaphoreHandle,
|
||||
EVENT_QUERY_STATE,
|
||||
SEMAPHORE_QUERY_STATE,
|
||||
ExSemaphoreObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Semaphore,
|
||||
|
|
|
@ -36,6 +36,10 @@ static GENERIC_MAPPING ExpTimerMapping = {
|
|||
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||
TIMER_ALL_ACCESS};
|
||||
|
||||
static const INFORMATION_CLASS_INFO ExTimerInfoClass[] =
|
||||
{
|
||||
ICI_SQ_SAME( sizeof(TIMER_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ), /* TimerBasicInformation */
|
||||
};
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
@ -146,36 +150,67 @@ NtCancelTimer(IN HANDLE TimerHandle,
|
|||
OUT PBOOLEAN CurrentState OPTIONAL)
|
||||
{
|
||||
PNTTIMER Timer;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN State;
|
||||
KIRQL OldIrql;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
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,
|
||||
TIMER_ALL_ACCESS,
|
||||
ExTimerType,
|
||||
UserMode,
|
||||
PreviousMode,
|
||||
(PVOID*)&Timer,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
if(NT_SUCCESS(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);
|
||||
KeRemoveQueueDpc(&Timer->Dpc);
|
||||
KeRemoveQueueApc(&Timer->Apc);
|
||||
Timer->Running = FALSE;
|
||||
KeLowerIrql(OldIrql);
|
||||
ObDereferenceObject(Timer);
|
||||
|
||||
KeLowerIrql(OldIrql);
|
||||
ObDereferenceObject(Timer);
|
||||
|
||||
if (CurrentState != NULL)
|
||||
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)
|
||||
{
|
||||
PNTTIMER Timer;
|
||||
NTSTATUS Status;
|
||||
|
||||
HANDLE hTimer;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
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,
|
||||
ObjectAttributes,
|
||||
ExGetPreviousMode(),
|
||||
PreviousMode,
|
||||
NULL,
|
||||
sizeof(NTTIMER),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&Timer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
KeInitializeTimerEx(&Timer->Timer,
|
||||
TimerType);
|
||||
|
||||
KeInitializeTimerEx(&Timer->Timer,
|
||||
TimerType);
|
||||
KeInitializeDpc(&Timer->Dpc,
|
||||
&ExpTimerDpcRoutine,
|
||||
Timer);
|
||||
|
||||
KeInitializeDpc(&Timer->Dpc,
|
||||
&ExpTimerDpcRoutine,
|
||||
Timer);
|
||||
Timer->Running = FALSE;
|
||||
|
||||
Timer->Running = FALSE;
|
||||
|
||||
Status = ObInsertObject ((PVOID)Timer,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
TimerHandle);
|
||||
|
||||
ObDereferenceObject(Timer);
|
||||
Status = ObInsertObject ((PVOID)Timer,
|
||||
NULL,
|
||||
DesiredAccess,
|
||||
0,
|
||||
NULL,
|
||||
&hTimer);
|
||||
ObDereferenceObject(Timer);
|
||||
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*TimerHandle = hTimer;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -228,15 +300,54 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
|
|||
IN ACCESS_MASK DesiredAccess,
|
||||
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,
|
||||
ExTimerType,
|
||||
NULL,
|
||||
UserMode,
|
||||
PreviousMode,
|
||||
DesiredAccess,
|
||||
NULL,
|
||||
TimerHandle);
|
||||
&hTimer);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*TimerHandle = hTimer;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -248,58 +359,67 @@ NtQueryTimer(IN HANDLE TimerHandle,
|
|||
IN ULONG TimerInformationLength,
|
||||
OUT PULONG ReturnLength OPTIONAL)
|
||||
{
|
||||
PNTTIMER Timer;
|
||||
TIMER_BASIC_INFORMATION SafeTimerInformation;
|
||||
ULONG ResultLength;
|
||||
NTSTATUS Status;
|
||||
PNTTIMER Timer;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
Status = ObReferenceObjectByHandle(TimerHandle,
|
||||
TIMER_QUERY_STATE,
|
||||
ExTimerType,
|
||||
(KPROCESSOR_MODE)KeGetPreviousMode(),
|
||||
(PVOID*)&Timer,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
if (TimerInformationClass != TimerBasicInformation)
|
||||
{
|
||||
ObDereferenceObject(Timer);
|
||||
return(STATUS_INVALID_INFO_CLASS);
|
||||
}
|
||||
if (TimerInformationLength < sizeof(TIMER_BASIC_INFORMATION))
|
||||
{
|
||||
ObDereferenceObject(Timer);
|
||||
return(STATUS_INFO_LENGTH_MISMATCH);
|
||||
}
|
||||
DefaultQueryInfoBufferCheck(TimerInformationClass,
|
||||
ExTimerInfoClass,
|
||||
TimerInformation,
|
||||
TimerInformationLength,
|
||||
ReturnLength,
|
||||
PreviousMode,
|
||||
&Status);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtQueryTimer() failed, Status: 0x%x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
memcpy(&SafeTimerInformation.TimeRemaining, &Timer->Timer.DueTime,
|
||||
sizeof(LARGE_INTEGER));
|
||||
SafeTimerInformation.SignalState = (BOOLEAN)Timer->Timer.Header.SignalState;
|
||||
ResultLength = sizeof(TIMER_BASIC_INFORMATION);
|
||||
Status = ObReferenceObjectByHandle(TimerHandle,
|
||||
TIMER_QUERY_STATE,
|
||||
ExTimerType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Timer,
|
||||
NULL);
|
||||
if(NT_SUCCESS(Status))
|
||||
{
|
||||
switch(TimerInformationClass)
|
||||
{
|
||||
case TimerBasicInformation:
|
||||
{
|
||||
PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation;
|
||||
|
||||
Status = MmCopyToCaller(TimerInformation, &SafeTimerInformation,
|
||||
sizeof(TIMER_BASIC_INFORMATION));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ObDereferenceObject(Timer);
|
||||
return(Status);
|
||||
}
|
||||
_SEH_TRY
|
||||
{
|
||||
/* FIXME - interrupt correction */
|
||||
BasicInfo->TimeRemaining.QuadPart = Timer->Timer.DueTime.QuadPart;
|
||||
BasicInfo->SignalState = (BOOLEAN)Timer->Timer.Header.SignalState;
|
||||
|
||||
if (ReturnLength != NULL)
|
||||
{
|
||||
Status = MmCopyToCaller(ReturnLength, &ResultLength,
|
||||
sizeof(ULONG));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ObDereferenceObject(Timer);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
ObDereferenceObject(Timer);
|
||||
return(STATUS_SUCCESS);
|
||||
if(ReturnLength != NULL)
|
||||
{
|
||||
*ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
|
||||
}
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
ObDereferenceObject(Timer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -313,16 +433,48 @@ NtSetTimer(IN HANDLE TimerHandle,
|
|||
OUT PBOOLEAN PreviousState OPTIONAL)
|
||||
{
|
||||
PNTTIMER Timer;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Result;
|
||||
BOOLEAN State;
|
||||
LARGE_INTEGER TimerDueTime;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
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,
|
||||
TIMER_ALL_ACCESS,
|
||||
ExTimerType,
|
||||
(KPROCESSOR_MODE)KeGetPreviousMode(),
|
||||
PreviousMode,
|
||||
(PVOID*)&Timer,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
@ -351,15 +503,15 @@ NtSetTimer(IN HANDLE TimerHandle,
|
|||
&ExpTimerApcKernelRoutine,
|
||||
(PKRUNDOWN_ROUTINE)NULL,
|
||||
(PKNORMAL_ROUTINE)TimerApcRoutine,
|
||||
(KPROCESSOR_MODE)KeGetPreviousMode(),
|
||||
PreviousMode,
|
||||
TimerContext);
|
||||
}
|
||||
|
||||
Result = KeSetTimerEx(&Timer->Timer,
|
||||
*DueTime,
|
||||
TimerDueTime,
|
||||
Period,
|
||||
TimerApcRoutine ? &Timer->Dpc : 0 );
|
||||
if (Result == TRUE)
|
||||
if (Result)
|
||||
{
|
||||
ObDereferenceObject(Timer);
|
||||
DPRINT1( "KeSetTimer says the timer was already running, this shouldn't be\n" );
|
||||
|
@ -371,11 +523,19 @@ NtSetTimer(IN HANDLE TimerHandle,
|
|||
ObDereferenceObject(Timer);
|
||||
|
||||
if (PreviousState != NULL)
|
||||
{
|
||||
_SEH_TRY
|
||||
{
|
||||
*PreviousState = State;
|
||||
*PreviousState = State;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue