https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6ca1c55c6e849cd1430a47cf866527b89bcc2ddf

commit 6ca1c55c6e849cd1430a47cf866527b89bcc2ddf
Author:     Pierre Schweitzer <[email protected]>
AuthorDate: Tue Dec 18 23:08:19 2018 +0100
Commit:     Pierre Schweitzer <[email protected]>
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-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 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 */

Reply via email to