https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6ca1c55c6e849cd1430a4…
commit 6ca1c55c6e849cd1430a47cf866527b89bcc2ddf
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Tue Dec 18 23:08:19 2018 +0100
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Tue Dec 18 23:12:41 2018 +0100
[NTOSKRNL] Only allow SYSTEM to call NtSetUuidSeed()
Also, validate input buffer before attempting any operation on it.
This will avoid userland applications to be able to trigger an invalid
read in the kernel (and thus a BSOD).
Regarding access restriction, see:
https://stackoverflow.com/questions/1254244/need-access-to-ntsetuuidseed-fr…
CORE-15460
---
ntoskrnl/ex/uuid.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 50 insertions(+), 4 deletions(-)
diff --git a/ntoskrnl/ex/uuid.c b/ntoskrnl/ex/uuid.c
index ecb69dc003..e43f6d12de 100644
--- a/ntoskrnl/ex/uuid.c
+++ b/ntoskrnl/ex/uuid.c
@@ -377,12 +377,58 @@ NTSTATUS
NTAPI
NtSetUuidSeed(IN PUCHAR Seed)
{
+ NTSTATUS Status;
+ BOOLEAN GotContext;
+ PACCESS_TOKEN Token;
+ SECURITY_SUBJECT_CONTEXT SubjectContext;
+ LUID CallerLuid, SystemLuid = SYSTEM_LUID;
+
PAGED_CODE();
- RtlCopyMemory(UuidSeed,
- Seed,
- SEED_BUFFER_SIZE);
- return STATUS_SUCCESS;
+ /* Should only be done by umode */
+ ASSERT(KeGetPreviousMode() != KernelMode);
+
+ /* No context to release */
+ GotContext = FALSE;
+ _SEH2_TRY
+ {
+ /* Get our caller context and remember to release it */
+ SeCaptureSubjectContext(&SubjectContext);
+ GotContext = TRUE;
+
+ /* Get caller access token and its associated ID */
+ Token = SeQuerySubjectContextToken(&SubjectContext);
+ Status = SeQueryAuthenticationIdToken(Token, &CallerLuid);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlRaiseStatus(Status);
+ }
+
+ /* This call is only allowed for SYSTEM */
+ if (!RtlEqualLuid(&CallerLuid, &SystemLuid))
+ {
+ RtlRaiseStatus(STATUS_ACCESS_DENIED);
+ }
+
+ /* Check for buffer validity and then copy it to our seed */
+ ProbeForRead(Seed, SEED_BUFFER_SIZE, 1);
+ RtlCopyMemory(UuidSeed, Seed, SEED_BUFFER_SIZE);
+
+ Status = STATUS_SUCCESS;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Release context if required */
+ if (GotContext)
+ {
+ SeReleaseSubjectContext(&SubjectContext);
+ }
+
+ return Status;
}
/* EOF */