From 6ca1c55c6e849cd1430a47cf866527b89bcc2ddf Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 18 Dec 2018 23:08:19 +0100 Subject: [PATCH] [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-from-a-non-localsystem-process 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 ecb69dc0039..e43f6d12de3 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 */