[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,14 +493,6 @@ NtQueryTimerResolution(OUT PULONG MinimumResolution,
ProbeForWriteUlong(MinimumResolution); ProbeForWriteUlong(MinimumResolution);
ProbeForWriteUlong(MaximumResolution); ProbeForWriteUlong(MaximumResolution);
ProbeForWriteUlong(ActualResolution); ProbeForWriteUlong(ActualResolution);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
/* /*
* Set the parameters to the actual values. * Set the parameters to the actual values.
@ -513,6 +504,21 @@ NtQueryTimerResolution(OUT PULONG MinimumResolution,
*MinimumResolution = KeMaximumIncrement; *MinimumResolution = KeMaximumIncrement;
*MaximumResolution = KeMinimumIncrement; *MaximumResolution = KeMinimumIncrement;
*ActualResolution = KeTimeIncrement; *ActualResolution = KeTimeIncrement;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Return the exception code */
_SEH2_YIELD(return _SEH2_GetExceptionCode());
}
_SEH2_END;
}
else
{
/* Set the parameters to the actual values */
*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);
if (PreviousMode != KernelMode)
{
_SEH2_TRY
{
*CurrentResolution = NewResolution; *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)
{ {