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