[NTOSKRNL]

Fix user-mode access of pointers. From a patch by Sven Bjorn (private communication) and Aleksander Andrejevic.
"[...]In the routine NtSetTimerResolution() the pointer "CurrentResolution" is
checked using ProbeForWriteUlong(), but it is then accessed outside of a try-block.
This should be an error, since the user mode memory can become invalid at any point
in time and thus potentially make the kernel crash on access.
[...]"
CORE-7387 #comment A fix by Sven Bjorn was committed in revision 61468, thanks :)

svn path=/trunk/; revision=61468
This commit is contained in:
Hermès Bélusca-Maïto 2013-12-31 20:47:05 +00:00
parent 5661fc7c14
commit d5edd3f68c

View file

@ -417,7 +417,6 @@ NTAPI
NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime) NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
{ {
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
/* Check if we were called from user-mode */ /* Check if we were called from user-mode */
@ -429,16 +428,16 @@ NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
ProbeForWriteLargeInteger(SystemTime); ProbeForWriteLargeInteger(SystemTime);
/* /*
* It's safe to pass the pointer directly to KeQuerySystemTime as * It's safe to pass the pointer directly to KeQuerySystemTime
* it's just a basic copy to this pointer. If it raises an * as it's just a basic copy to this pointer. If it raises an
* exception nothing dangerous can happen! * exception nothing dangerous can happen!
*/ */
KeQuerySystemTime(SystemTime); KeQuerySystemTime(SystemTime);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
/* Get the exception code */ /* Return the exception code */
Status = _SEH2_GetExceptionCode(); _SEH2_YIELD(return _SEH2_GetExceptionCode());
} }
_SEH2_END; _SEH2_END;
} }
@ -448,8 +447,8 @@ NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
KeQuerySystemTime(SystemTime); KeQuerySystemTime(SystemTime);
} }
/* Return status to caller */ /* Return success */
return Status; return STATUS_SUCCESS;
} }
/* /*
@ -485,7 +484,7 @@ NtQueryTimerResolution(OUT PULONG MinimumResolution,
{ {
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
/* Check if the call came from user mode */ /* Check if the call came from user-mode */
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
_SEH2_TRY _SEH2_TRY
@ -494,6 +493,17 @@ NtQueryTimerResolution(OUT PULONG MinimumResolution,
ProbeForWriteUlong(MinimumResolution); ProbeForWriteUlong(MinimumResolution);
ProbeForWriteUlong(MaximumResolution); ProbeForWriteUlong(MaximumResolution);
ProbeForWriteUlong(ActualResolution); ProbeForWriteUlong(ActualResolution);
/*
* Set the parameters to the actual values.
*
* NOTE:
* MinimumResolution corresponds to the biggest time increment and
* MaximumResolution corresponds to the smallest time increment.
*/
*MinimumResolution = KeMaximumIncrement;
*MaximumResolution = KeMinimumIncrement;
*ActualResolution = KeTimeIncrement;
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
@ -502,17 +512,13 @@ NtQueryTimerResolution(OUT PULONG MinimumResolution,
} }
_SEH2_END; _SEH2_END;
} }
else
/* {
* Set the parameters to the actual values. /* Set the parameters to the actual values */
* *MinimumResolution = KeMaximumIncrement;
* NOTE: *MaximumResolution = KeMinimumIncrement;
* MinimumResolution corresponds to the biggest time increment and *ActualResolution = KeTimeIncrement;
* MaximumResolution corresponds to the smallest time increment. }
*/
*MinimumResolution = KeMaximumIncrement;
*MaximumResolution = KeMinimumIncrement;
*ActualResolution = KeTimeIncrement;
/* Return success */ /* Return success */
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -532,7 +538,7 @@ NtSetTimerResolution(IN ULONG DesiredResolution,
PEPROCESS Process = PsGetCurrentProcess(); PEPROCESS Process = PsGetCurrentProcess();
ULONG NewResolution; ULONG NewResolution;
/* Check if the call came from user mode */ /* Check if the call came from user-mode */
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
_SEH2_TRY _SEH2_TRY
@ -550,7 +556,24 @@ NtSetTimerResolution(IN ULONG DesiredResolution,
/* Set and return the new resolution */ /* Set and return the new resolution */
NewResolution = ExSetTimerResolution(DesiredResolution, SetResolution); NewResolution = ExSetTimerResolution(DesiredResolution, SetResolution);
*CurrentResolution = NewResolution;
if (PreviousMode != KernelMode)
{
_SEH2_TRY
{
*CurrentResolution = NewResolution;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
else
{
*CurrentResolution = NewResolution;
}
if (SetResolution || Process->SetTimerResolution) if (SetResolution || Process->SetTimerResolution)
{ {